mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2025-01-12 20:03:28 +01:00
Update section 29-33.
This commit is contained in:
parent
bda0f28ad3
commit
3ada90257e
26 changed files with 1323 additions and 1604 deletions
|
@ -10,7 +10,8 @@ The table of contents is at the end of this abstract.
|
||||||
|
|
||||||
- Section 3 to 23 describes the basics, with the example of a simple editor `tfe` (Text File Editor).
|
- Section 3 to 23 describes the basics, with the example of a simple editor `tfe` (Text File Editor).
|
||||||
- Section 24 to 27 describes GtkDrawingArea.
|
- Section 24 to 27 describes GtkDrawingArea.
|
||||||
- Section 28 to 32 describes the list model and the list view (GtkListView, GtkGridView and GtkColumnView).
|
- Section 28 describes Drag and Drop.
|
||||||
|
- Section 29 to 33 describes the list model and the list view (GtkListView, GtkGridView and GtkColumnView).
|
||||||
It also describes GtkExpression.
|
It also describes GtkExpression.
|
||||||
|
|
||||||
The latest version of the tutorial is located at [GTK4-tutorial GitHub repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
The latest version of the tutorial is located at [GTK4-tutorial GitHub repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
||||||
|
|
|
@ -111,7 +111,8 @@ basics. The table of contents is at the end of this abstract.</p>
|
||||||
<li>Section 3 to 23 describes the basics, with the example of a simple
|
<li>Section 3 to 23 describes the basics, with the example of a simple
|
||||||
editor <code>tfe</code> (Text File Editor).</li>
|
editor <code>tfe</code> (Text File Editor).</li>
|
||||||
<li>Section 24 to 27 describes GtkDrawingArea.</li>
|
<li>Section 24 to 27 describes GtkDrawingArea.</li>
|
||||||
<li>Section 28 to 32 describes the list model and the list view
|
<li>Section 28 describes Drag and Drop.</li>
|
||||||
|
<li>Section 29 to 33 describes the list model and the list view
|
||||||
(GtkListView, GtkGridView and GtkColumnView). It also describes
|
(GtkListView, GtkGridView and GtkColumnView). It also describes
|
||||||
GtkExpression.</li>
|
GtkExpression.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -120,16 +120,17 @@ Reference – List Widget Overview</a>.</p>
|
||||||
GtkTreeView which are took over from GTK 3. There’s an article in <a
|
GtkTreeView which are took over from GTK 3. There’s an article in <a
|
||||||
href="https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/">Gtk
|
href="https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/">Gtk
|
||||||
Development blog</a> about list widgets by Matthias Clasen. He described
|
Development blog</a> about list widgets by Matthias Clasen. He described
|
||||||
why GtkListView are developed to replace GtkListBox and GtkTreeView.</p>
|
why GtkListView are developed to replace GtkTreeView. GtkTreeView is
|
||||||
|
deprecated since version 4.10.</p>
|
||||||
<p>GtkListView, GtkGridView, GtkColumnView and related objects are
|
<p>GtkListView, GtkGridView, GtkColumnView and related objects are
|
||||||
described in Section 26 to 29.</p>
|
described in Section 29 to 33.</p>
|
||||||
<h2 id="outline">Outline</h2>
|
<h2 id="outline">Outline</h2>
|
||||||
<p>A list is a sequential data structure. For example, an ordered string
|
<p>A list is a sequential data structure. For example, an ordered string
|
||||||
sequence “one”, “two”, “three”, “four” is a list. Each element is called
|
sequence “one”, “two”, “three”, “four” is a list. Each element is called
|
||||||
item. A list is like an array, but in many cases it is implemented with
|
item. A list is like an array, but in many cases it is implemented with
|
||||||
pointers which point to the next items of the list. And it has a start
|
pointers which point to the next items of the list. And it has a start
|
||||||
point. So, each item can be referred by the index of the item (first
|
point. So, each item can be referred by the index of the item (first
|
||||||
item, second item, …, nth item, …). There are two cases. One is the
|
item, second item, …, nth item, …). There are two cases. The one is the
|
||||||
index starts from one (one-based) and the other is from zero
|
index starts from one (one-based) and the other is from zero
|
||||||
(zero-based).</p>
|
(zero-based).</p>
|
||||||
<p>Gio provides GListModel interface. It is a zero-based list and its
|
<p>Gio provides GListModel interface. It is a zero-based list and its
|
||||||
|
@ -138,12 +139,12 @@ implement the same interface. An object implements GListModel is not a
|
||||||
widget. So, the list is not displayed on the screen directly. There’s
|
widget. So, the list is not displayed on the screen directly. There’s
|
||||||
another object GtkListView which is a widget to display the list. The
|
another object GtkListView which is a widget to display the list. The
|
||||||
items in the list need to be connected to the items in GtkListView.
|
items in the list need to be connected to the items in GtkListView.
|
||||||
GtkListItemFactory instance maps items in the list to GListView.</p>
|
GtkListItemFactory instance maps items in the list to GtkListView.</p>
|
||||||
<figure>
|
<figure>
|
||||||
<img src="image/list.png" alt="List" />
|
<img src="image/list.png" alt="List" />
|
||||||
<figcaption aria-hidden="true">List</figcaption>
|
<figcaption aria-hidden="true">List</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
<h2 id="glistmodel">GListModel</h2>
|
<h2 id="glistmodel-and-gtkstringlist">GListModel and GtkStringList</h2>
|
||||||
<p>If you want to make a list of strings with GListModel, for example,
|
<p>If you want to make a list of strings with GListModel, for example,
|
||||||
“one”, “two”, “three”, “four”, note that strings can’t be items of the
|
“one”, “two”, “three”, “four”, note that strings can’t be items of the
|
||||||
list. Because GListModel is a list of GObject objects and strings aren’t
|
list. Because GListModel is a list of GObject objects and strings aren’t
|
||||||
|
@ -356,7 +357,7 @@ instantiated.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>Therefore, GtkListItem instance is used as the <code>this</code>
|
<p>Therefore, GtkListItem instance is used as the <code>this</code>
|
||||||
object of the lookup tag when it is evaluated. <code>this</code> object
|
object of the lookup tag when it is evaluated. <code>this</code> object
|
||||||
will be explained in section 30.</p>
|
will be explained in section 31.</p>
|
||||||
<p>The C source code is as follows. Its name is <code>list2.c</code> and
|
<p>The C source code is as follows. Its name is <code>list2.c</code> and
|
||||||
located under src/misc directory.</p>
|
located under src/misc directory.</p>
|
||||||
<div class="sourceCode" id="cb7"><pre
|
<div class="sourceCode" id="cb7"><pre
|
||||||
|
@ -431,7 +432,7 @@ are information of files under a certain directory. It uses
|
||||||
<code>g_file_enumerate_children_async()</code> to get the GFileInfo
|
<code>g_file_enumerate_children_async()</code> to get the GFileInfo
|
||||||
objects. The list model is created by
|
objects. The list model is created by
|
||||||
<code>gtk_directory_list_new</code> function.</p>
|
<code>gtk_directory_list_new</code> function.</p>
|
||||||
<div class="sourceCode" id="cb8"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>GtkDirectoryList <span class="op">*</span>gtk_directory_list_new <span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>attributes<span class="op">,</span> GFile <span class="op">*</span>file<span class="op">);</span></span></code></pre></div>
|
<div class="sourceCode" id="cb8"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>GtkDirectoryList <span class="op">*</span>gtk_directory_list_new <span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>attributes<span class="op">,</span> GFile <span class="op">*</span>file<span class="op">);</span></span></code></pre></div>
|
||||||
<p><code>attributes</code> is a comma separated list of file attributes.
|
<p><code>attributes</code> is a comma separated list of file attributes.
|
||||||
File attributes are key-value pairs. A key consists of a namespace and a
|
File attributes are key-value pairs. A key consists of a namespace and a
|
||||||
name. For example, “standard::name” key is the name of a file.
|
name. For example, “standard::name” key is the name of a file.
|
||||||
|
@ -477,7 +478,7 @@ seconds since the UNIX epoch</td>
|
||||||
<p>The current directory is “.”. The following program makes
|
<p>The current directory is “.”. The following program makes
|
||||||
GtkDirectoryList <code>dl</code> and its contents are GFileInfo objects
|
GtkDirectoryList <code>dl</code> and its contents are GFileInfo objects
|
||||||
under the current directory.</p>
|
under the current directory.</p>
|
||||||
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>GFile <span class="op">*</span>file <span class="op">=</span> g_file_new_for_path <span class="op">(</span><span class="st">"."</span><span class="op">);</span></span>
|
<div class="sourceCode" id="cb9"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>GFile <span class="op">*</span>file <span class="op">=</span> g_file_new_for_path <span class="op">(</span><span class="st">"."</span><span class="op">);</span></span>
|
||||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>GtkDirectoryList <span class="op">*</span>dl <span class="op">=</span> gtk_directory_list_new <span class="op">(</span><span class="st">"standard::name"</span><span class="op">,</span> file<span class="op">);</span></span>
|
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>GtkDirectoryList <span class="op">*</span>dl <span class="op">=</span> gtk_directory_list_new <span class="op">(</span><span class="st">"standard::name"</span><span class="op">,</span> file<span class="op">);</span></span>
|
||||||
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>g_object_unref <span class="op">(</span>file<span class="op">);</span></span></code></pre></div>
|
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>g_object_unref <span class="op">(</span>file<span class="op">);</span></span></code></pre></div>
|
||||||
<p>It is not so difficult to make file listing program by changing
|
<p>It is not so difficult to make file listing program by changing
|
||||||
|
@ -486,7 +487,7 @@ GInfoFile doesn’t have properties. Lookup tag look for a property, so it
|
||||||
is useless for looking for a filename from a GFileInfo object. Instead,
|
is useless for looking for a filename from a GFileInfo object. Instead,
|
||||||
closure tag is appropriate in this case. Closure tag specifies a
|
closure tag is appropriate in this case. Closure tag specifies a
|
||||||
function and the type of the return value of the function.</p>
|
function and the type of the return value of the function.</p>
|
||||||
<div class="sourceCode" id="cb10"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span></span>
|
<div class="sourceCode" id="cb10"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> <span class="op">*</span></span>
|
||||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>get_file_name <span class="op">(</span>GtkListItem <span class="op">*</span>item<span class="op">,</span> GFileInfo <span class="op">*</span>info<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>get_file_name <span class="op">(</span>GtkListItem <span class="op">*</span>item<span class="op">,</span> GFileInfo <span class="op">*</span>info<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">)</span> <span class="op">?</span> g_strdup <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">))</span> <span class="op">:</span> NULL<span class="op">;</span></span>
|
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">)</span> <span class="op">?</span> g_strdup <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">))</span> <span class="op">:</span> NULL<span class="op">;</span></span>
|
||||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||||
|
@ -526,7 +527,7 @@ the function.
|
||||||
the value of the item property of the GtkListItem. This will be the
|
the value of the item property of the GtkListItem. This will be the
|
||||||
second argument of the function. The first parameter is always the
|
second argument of the function. The first parameter is always the
|
||||||
GListItem instance, which is a ‘this’ object. The ‘this’ object is
|
GListItem instance, which is a ‘this’ object. The ‘this’ object is
|
||||||
explained in section 28.</li>
|
explained in section 31.</li>
|
||||||
<li><code>gtk_file_name</code> function is the callback function for the
|
<li><code>gtk_file_name</code> function is the callback function for the
|
||||||
closure tag. It first checks the <code>info</code> parameter. Because it
|
closure tag. It first checks the <code>info</code> parameter. Because it
|
||||||
can be NULL when GListItem <code>item</code> is unbounded. If it’s
|
can be NULL when GListItem <code>item</code> is unbounded. If it’s
|
||||||
|
|
|
@ -173,8 +173,7 @@ registered to IANA media types. Such “x-” subtype is not a standard mime
|
||||||
type.) Content type is also used by desktop systems.</li>
|
type.) Content type is also used by desktop systems.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>GtkGridView uses the same GtkSingleSelection instance
|
<p>GtkGridView uses the same GtkSingleSelection instance
|
||||||
(<code>singleselection</code>). So, its model property is set with
|
(<code>singleselection</code>). So, its model property is set to it.</p>
|
||||||
it.</p>
|
|
||||||
<h2 id="ui-file-of-the-window">Ui file of the window</h2>
|
<h2 id="ui-file-of-the-window">Ui file of the window</h2>
|
||||||
<p>The window is built with the following ui file. (See the screenshot
|
<p>The window is built with the following ui file. (See the screenshot
|
||||||
at the beginning of this section).</p>
|
at the beginning of this section).</p>
|
||||||
|
@ -291,7 +290,7 @@ GtkListView or GtkGridView.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>The action <code>view</code> is created, connected to the “activate”
|
<p>The action <code>view</code> is created, connected to the “activate”
|
||||||
signal handler and inserted to the window (action map) as follows.</p>
|
signal handler and inserted to the window (action map) as follows.</p>
|
||||||
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>act_view <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">"view"</span><span class="op">,</span> g_variant_type_new<span class="op">(</span><span class="st">"s"</span><span class="op">),</span> g_variant_new_string <span class="op">(</span><span class="st">"list"</span><span class="op">));</span></span>
|
<div class="sourceCode" id="cb4"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>act_view <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">"view"</span><span class="op">,</span> g_variant_type_new<span class="op">(</span><span class="st">"s"</span><span class="op">),</span> g_variant_new_string <span class="op">(</span><span class="st">"list"</span><span class="op">));</span></span>
|
||||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>g_signal_connect <span class="op">(</span>act_view<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>view_activated<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>g_signal_connect <span class="op">(</span>act_view<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>view_activated<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>win<span class="op">),</span> G_ACTION <span class="op">(</span>act_view<span class="op">));</span></span></code></pre></div>
|
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>win<span class="op">),</span> G_ACTION <span class="op">(</span>act_view<span class="op">));</span></span></code></pre></div>
|
||||||
<p>The signal handler <code>view_activated</code> will be explained
|
<p>The signal handler <code>view_activated</code> will be explained
|
||||||
|
@ -464,7 +463,7 @@ pressed. You can do anything you like by connecting the “activate”
|
||||||
signal to the handler.</p>
|
signal to the handler.</p>
|
||||||
<p>The example <code>list4</code> launches <code>tfe</code> text file
|
<p>The example <code>list4</code> launches <code>tfe</code> text file
|
||||||
editor if the item of the list is a text file.</p>
|
editor if the item of the list is a text file.</p>
|
||||||
<div class="sourceCode" id="cb10"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<div class="sourceCode" id="cb10"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>list_activate <span class="op">(</span>GtkListView <span class="op">*</span>list<span class="op">,</span> <span class="dt">int</span> position<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>list_activate <span class="op">(</span>GtkListView <span class="op">*</span>list<span class="op">,</span> <span class="dt">int</span> position<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> GFileInfo <span class="op">*</span>info <span class="op">=</span> G_FILE_INFO <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>gtk_list_view_get_model <span class="op">(</span>list<span class="op">)),</span> position<span class="op">));</span></span>
|
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> GFileInfo <span class="op">*</span>info <span class="op">=</span> G_FILE_INFO <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>gtk_list_view_get_model <span class="op">(</span>list<span class="op">)),</span> position<span class="op">));</span></span>
|
||||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> launch_tfe_with_file <span class="op">(</span>info<span class="op">);</span></span>
|
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> launch_tfe_with_file <span class="op">(</span>info<span class="op">);</span></span>
|
||||||
|
@ -558,12 +557,12 @@ list and items.</li>
|
||||||
<code>g_app_info_launch_default_for_uri</code> is convenient. The
|
<code>g_app_info_launch_default_for_uri</code> is convenient. The
|
||||||
function automatically determines the default application from the file
|
function automatically determines the default application from the file
|
||||||
and launches it. For example, if the file is text, then it launches
|
and launches it. For example, if the file is text, then it launches
|
||||||
gedit with the file. Such feature comes from desktop.</p>
|
GNOME text editor with the file. Such feature comes from desktop.</p>
|
||||||
<h2 id="compilation-and-execution">Compilation and execution</h2>
|
<h2 id="compilation-and-execution">Compilation and execution</h2>
|
||||||
<p>The source files are located in src/list4 directory. To compile and
|
<p>The source files are located in src/list4 directory. To compile and
|
||||||
execute list4, type as follows.</p>
|
execute list4, type as follows.</p>
|
||||||
<pre><code>$ cd list4 # or cd src/list4. It depends your current directory.
|
<pre><code>$ cd list4 # or cd src/list4. It depends your current directory.
|
||||||
$ meson _build
|
$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/list4</code></pre>
|
$ _build/list4</code></pre>
|
||||||
<p>Then a file list appears as a list style. Click on a button on the
|
<p>Then a file list appears as a list style. Click on a button on the
|
||||||
|
|
748
docs/sec31.html
748
docs/sec31.html
|
@ -191,13 +191,13 @@ value of the expression. The type of the value is int.</li>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td style="text-align: left;">G_TYPE_POINTER</td>
|
<td style="text-align: left;">G_TYPE_POINTER</td>
|
||||||
<td style="text-align: left;"></td>
|
<td style="text-align: left;">void *</td>
|
||||||
<td style="text-align: left;">gpointer</td>
|
<td style="text-align: left;">gpointer</td>
|
||||||
<td style="text-align: left;"></td>
|
<td style="text-align: left;">general pointer</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd">
|
<tr class="odd">
|
||||||
<td style="text-align: left;">G_TYPE_STRING</td>
|
<td style="text-align: left;">G_TYPE_STRING</td>
|
||||||
<td style="text-align: left;"></td>
|
<td style="text-align: left;">char *</td>
|
||||||
<td style="text-align: left;">gchararray</td>
|
<td style="text-align: left;">gchararray</td>
|
||||||
<td style="text-align: left;">null-terminated Cstring</td>
|
<td style="text-align: left;">null-terminated Cstring</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -250,7 +250,7 @@ instance to another expression.</p>
|
||||||
<p>A property expression (GtkPropertyExpression) looks up a property in
|
<p>A property expression (GtkPropertyExpression) looks up a property in
|
||||||
a GObject instance. For example, a property expression that refers
|
a GObject instance. For example, a property expression that refers
|
||||||
“label” property in a GtkLabel object is created like this.</p>
|
“label” property in a GtkLabel object is created like this.</p>
|
||||||
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>expression <span class="op">=</span> gtk_property_expression_new <span class="op">(</span>GTK_TYPE_LABEL<span class="op">,</span> another_expression<span class="op">,</span> <span class="st">"label"</span><span class="op">);</span></span></code></pre></div>
|
<div class="sourceCode" id="cb4"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>expression <span class="op">=</span> gtk_property_expression_new <span class="op">(</span>GTK_TYPE_LABEL<span class="op">,</span> another_expression<span class="op">,</span> <span class="st">"label"</span><span class="op">);</span></span></code></pre></div>
|
||||||
<p>The second parameter <code>another_expression</code> is one of:</p>
|
<p>The second parameter <code>another_expression</code> is one of:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>An expression that gives a GtkLabel instance when it is
|
<li>An expression that gives a GtkLabel instance when it is
|
||||||
|
@ -259,14 +259,14 @@ evaluated.</li>
|
||||||
is evaluated. The instance is called <code>this</code> object.</li>
|
is evaluated. The instance is called <code>this</code> object.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>For example,</p>
|
<p>For example,</p>
|
||||||
<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>label <span class="op">=</span> gtk_label_new <span class="op">(</span><span class="st">"Hello"</span><span class="op">);</span></span>
|
<div class="sourceCode" id="cb5"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>label <span class="op">=</span> gtk_label_new <span class="op">(</span><span class="st">"Hello"</span><span class="op">);</span></span>
|
||||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>another_expression <span class="op">=</span> gtk_constant_expression_new <span class="op">(</span>GTK_TYPE_LABEL<span class="op">,</span> label<span class="op">);</span></span>
|
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>another_expression <span class="op">=</span> gtk_constant_expression_new <span class="op">(</span>GTK_TYPE_LABEL<span class="op">,</span> label<span class="op">);</span></span>
|
||||||
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>expression <span class="op">=</span> gtk_property_expression_new <span class="op">(</span>GTK_TYPE_LABEL<span class="op">,</span> another_expression<span class="op">,</span> <span class="st">"label"</span><span class="op">);</span></span></code></pre></div>
|
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>expression <span class="op">=</span> gtk_property_expression_new <span class="op">(</span>GTK_TYPE_LABEL<span class="op">,</span> another_expression<span class="op">,</span> <span class="st">"label"</span><span class="op">);</span></span></code></pre></div>
|
||||||
<p>If <code>expression</code> is evaluated, the second parameter
|
<p>If <code>expression</code> is evaluated, the second parameter
|
||||||
<code>another_expression</code> is evaluated in advance. The value of
|
<code>another_expression</code> is evaluated in advance. The value of
|
||||||
<code>another_expression</code> is the <code>label</code> (GtkLabel
|
<code>another_expression</code> is the <code>label</code> (GtkLabel
|
||||||
instance). Then, <code>expression</code> looks up “label” property of
|
instance). Then, <code>expression</code> looks up “label” property of
|
||||||
the label and the evaluation results “Hello”.</p>
|
the label and the evaluation results in “Hello”.</p>
|
||||||
<p>In the example above, the second argument of
|
<p>In the example above, the second argument of
|
||||||
<code>gtk_property_expression_new</code> is another expression. But the
|
<code>gtk_property_expression_new</code> is another expression. But the
|
||||||
second argument can be NULL. If it is NULL, <code>this</code> instance
|
second argument can be NULL. If it is NULL, <code>this</code> instance
|
||||||
|
@ -291,7 +291,7 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
||||||
<span id="cb6-14"><a href="#cb6-14"></a> <span class="cf">if</span> <span class="op">(</span>gtk_expression_evaluate <span class="op">(</span>expression<span class="op">,</span> label<span class="op">,</span> <span class="op">&</span>value<span class="op">))</span></span>
|
<span id="cb6-14"><a href="#cb6-14"></a> <span class="cf">if</span> <span class="op">(</span>gtk_expression_evaluate <span class="op">(</span>expression<span class="op">,</span> label<span class="op">,</span> <span class="op">&</span>value<span class="op">))</span></span>
|
||||||
<span id="cb6-15"><a href="#cb6-15"></a> g_print <span class="op">(</span><span class="st">"The value is %s.</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> g_value_get_string <span class="op">(&</span>value<span class="op">));</span></span>
|
<span id="cb6-15"><a href="#cb6-15"></a> g_print <span class="op">(</span><span class="st">"The value is %s.</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> g_value_get_string <span class="op">(&</span>value<span class="op">));</span></span>
|
||||||
<span id="cb6-16"><a href="#cb6-16"></a> <span class="cf">else</span></span>
|
<span id="cb6-16"><a href="#cb6-16"></a> <span class="cf">else</span></span>
|
||||||
<span id="cb6-17"><a href="#cb6-17"></a> g_print <span class="op">(</span><span class="st">"The constant expression wasn't evaluated correctly.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
<span id="cb6-17"><a href="#cb6-17"></a> g_print <span class="op">(</span><span class="st">"The property expression wasn't evaluated correctly.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||||
<span id="cb6-18"><a href="#cb6-18"></a> gtk_expression_unref <span class="op">(</span>expression<span class="op">);</span></span>
|
<span id="cb6-18"><a href="#cb6-18"></a> gtk_expression_unref <span class="op">(</span>expression<span class="op">);</span></span>
|
||||||
<span id="cb6-19"><a href="#cb6-19"></a> g_value_unset <span class="op">(&</span>value<span class="op">);</span></span>
|
<span id="cb6-19"><a href="#cb6-19"></a> g_value_unset <span class="op">(&</span>value<span class="op">);</span></span>
|
||||||
<span id="cb6-20"><a href="#cb6-20"></a></span>
|
<span id="cb6-20"><a href="#cb6-20"></a></span>
|
||||||
|
@ -311,8 +311,8 @@ the expression with a ‘this’ instance <code>label</code>. The result is
|
||||||
stored in the GValue <code>value</code>. The function
|
stored in the GValue <code>value</code>. The function
|
||||||
<code>g_value_get_string</code> gets a string from the GValue. But the
|
<code>g_value_get_string</code> gets a string from the GValue. But the
|
||||||
string is owned by the GValue so you must not free the string.</li>
|
string is owned by the GValue so you must not free the string.</li>
|
||||||
<li>18-19: Release the expression and unset the GValue. At the same time
|
<li>18-19: Releases the expression and unset the GValue. At the same
|
||||||
the string in the GValue is freed.</li>
|
time the string in the GValue is freed.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>If the second argument of <code>gtk_property_expression_new</code>
|
<p>If the second argument of <code>gtk_property_expression_new</code>
|
||||||
isn’t NULL, it is another expression. The expression is owned by a newly
|
isn’t NULL, it is another expression. The expression is owned by a newly
|
||||||
|
@ -334,79 +334,44 @@ respectively. When you program in C language, GtkCClosureExpression and
|
||||||
GCClosure are appropriate.</p>
|
GCClosure are appropriate.</p>
|
||||||
<p>A closure expression is created with
|
<p>A closure expression is created with
|
||||||
<code>gtk_cclosure_expression_new</code> function.</p>
|
<code>gtk_cclosure_expression_new</code> function.</p>
|
||||||
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>GtkExpression <span class="op">*</span></span>
|
<div class="sourceCode" id="cb7"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span></span>
|
||||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>gtk_cclosure_expression_new <span class="op">(</span>GType value_type<span class="op">,</span></span>
|
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>callback <span class="op">(</span>GObject <span class="op">*</span>object<span class="op">,</span> <span class="dt">int</span> x<span class="op">,</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>s<span class="op">)</span></span></code></pre></div>
|
||||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> GClosureMarshal marshal<span class="op">,</span></span>
|
|
||||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> guint n_params<span class="op">,</span></span>
|
|
||||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> GtkExpression <span class="op">**</span>params<span class="op">,</span></span>
|
|
||||||
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> GCallback callback_func<span class="op">,</span></span>
|
|
||||||
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> gpointer user_data<span class="op">,</span></span>
|
|
||||||
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> GClosureNotify user_destroy<span class="op">);</span></span></code></pre></div>
|
|
||||||
<ul>
|
|
||||||
<li><code>value_type</code> is the type of the value when it is
|
|
||||||
evaluated.</li>
|
|
||||||
<li><code>marshal</code> is a marshaller. You can assign NULL. If it is
|
|
||||||
NULL, then <code>g_cclosure_marshal_generic ()</code> is used as a
|
|
||||||
marshaller. It is a generic marshaller function implemented via
|
|
||||||
libffi.</li>
|
|
||||||
<li><code>n_params</code> is the number of parameters.</li>
|
|
||||||
<li><code>params</code> points expressions for each parameter of the
|
|
||||||
call back function.</li>
|
|
||||||
<li><code>callback_func</code> is a callback function. It is given
|
|
||||||
arguments <code>this</code> and parameters above. So, if
|
|
||||||
<code>n_params</code> is 3, the number of arguments of the function is
|
|
||||||
4. (<code>this</code> and <code>params</code>. See below.)</li>
|
|
||||||
<li><code>user_data</code> is user data. You can add it for the closure.
|
|
||||||
It is like <code>user_data</code> in <code>g_signal_connect</code>. If
|
|
||||||
it is not necessary, assign NULL.</li>
|
|
||||||
<li><code>user_destroy</code> is a destroy notify for
|
|
||||||
<code>user_data</code>. It is called to destroy <code>user_data</code>
|
|
||||||
when it is no longer needed. If NULL is assigned to
|
|
||||||
<code>user_data</code>, assign NULL to <code>user_destroy</code>,
|
|
||||||
too.</li>
|
|
||||||
</ul>
|
|
||||||
<p>Call back functions have the following format.</p>
|
|
||||||
<pre><code>C-type
|
|
||||||
callback (this, param1, param2, ...)</code></pre>
|
|
||||||
<p>For example,</p>
|
|
||||||
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span></span>
|
|
||||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>callback <span class="op">(</span>GObject <span class="op">*</span>object<span class="op">,</span> <span class="dt">int</span> x<span class="op">,</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>s<span class="op">)</span></span></code></pre></div>
|
|
||||||
<p>The following is <code>exp_closure_simple.c</code> in
|
<p>The following is <code>exp_closure_simple.c</code> in
|
||||||
<code>src/expression</code>.</p>
|
<code>src/expression</code>.</p>
|
||||||
<div class="sourceCode" id="cb10"><pre
|
<div class="sourceCode" id="cb8"><pre
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||||
<span id="cb10-2"><a href="#cb10-2"></a></span>
|
<span id="cb8-2"><a href="#cb8-2"></a></span>
|
||||||
<span id="cb10-3"><a href="#cb10-3"></a><span class="dt">static</span> <span class="dt">int</span></span>
|
<span id="cb8-3"><a href="#cb8-3"></a><span class="dt">static</span> <span class="dt">int</span></span>
|
||||||
<span id="cb10-4"><a href="#cb10-4"></a>calc <span class="op">(</span>GtkLabel <span class="op">*</span>label<span class="op">)</span> <span class="op">{</span> <span class="co">/* this object */</span></span>
|
<span id="cb8-4"><a href="#cb8-4"></a>calc <span class="op">(</span>GtkLabel <span class="op">*</span>label<span class="op">)</span> <span class="op">{</span> <span class="co">/* this object */</span></span>
|
||||||
<span id="cb10-5"><a href="#cb10-5"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span> s<span class="op">;</span></span>
|
<span id="cb8-5"><a href="#cb8-5"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span> s<span class="op">;</span></span>
|
||||||
<span id="cb10-6"><a href="#cb10-6"></a> <span class="dt">int</span> i<span class="op">,</span> j<span class="op">;</span></span>
|
<span id="cb8-6"><a href="#cb8-6"></a> <span class="dt">int</span> i<span class="op">,</span> j<span class="op">;</span></span>
|
||||||
<span id="cb10-7"><a href="#cb10-7"></a></span>
|
<span id="cb8-7"><a href="#cb8-7"></a></span>
|
||||||
<span id="cb10-8"><a href="#cb10-8"></a> s <span class="op">=</span> gtk_label_get_text <span class="op">(</span>label<span class="op">);</span> <span class="co">/* s is owned by the label. */</span></span>
|
<span id="cb8-8"><a href="#cb8-8"></a> s <span class="op">=</span> gtk_label_get_text <span class="op">(</span>label<span class="op">);</span> <span class="co">/* s is owned by the label. */</span></span>
|
||||||
<span id="cb10-9"><a href="#cb10-9"></a> sscanf <span class="op">(</span>s<span class="op">,</span> <span class="st">"%d+%d"</span><span class="op">,</span> <span class="op">&</span>i<span class="op">,</span> <span class="op">&</span>j<span class="op">);</span></span>
|
<span id="cb8-9"><a href="#cb8-9"></a> sscanf <span class="op">(</span>s<span class="op">,</span> <span class="st">"%d+%d"</span><span class="op">,</span> <span class="op">&</span>i<span class="op">,</span> <span class="op">&</span>j<span class="op">);</span></span>
|
||||||
<span id="cb10-10"><a href="#cb10-10"></a> <span class="cf">return</span> i<span class="op">+</span>j<span class="op">;</span></span>
|
<span id="cb8-10"><a href="#cb8-10"></a> <span class="cf">return</span> i<span class="op">+</span>j<span class="op">;</span></span>
|
||||||
<span id="cb10-11"><a href="#cb10-11"></a><span class="op">}</span></span>
|
<span id="cb8-11"><a href="#cb8-11"></a><span class="op">}</span></span>
|
||||||
<span id="cb10-12"><a href="#cb10-12"></a></span>
|
<span id="cb8-12"><a href="#cb8-12"></a></span>
|
||||||
<span id="cb10-13"><a href="#cb10-13"></a><span class="dt">int</span></span>
|
<span id="cb8-13"><a href="#cb8-13"></a><span class="dt">int</span></span>
|
||||||
<span id="cb10-14"><a href="#cb10-14"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb8-14"><a href="#cb8-14"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb10-15"><a href="#cb10-15"></a> GtkExpression <span class="op">*</span>expression<span class="op">;</span></span>
|
<span id="cb8-15"><a href="#cb8-15"></a> GtkExpression <span class="op">*</span>expression<span class="op">;</span></span>
|
||||||
<span id="cb10-16"><a href="#cb10-16"></a> GValue value <span class="op">=</span> G_VALUE_INIT<span class="op">;</span></span>
|
<span id="cb8-16"><a href="#cb8-16"></a> GValue value <span class="op">=</span> G_VALUE_INIT<span class="op">;</span></span>
|
||||||
<span id="cb10-17"><a href="#cb10-17"></a> GtkLabel <span class="op">*</span>label<span class="op">;</span></span>
|
<span id="cb8-17"><a href="#cb8-17"></a> GtkLabel <span class="op">*</span>label<span class="op">;</span></span>
|
||||||
<span id="cb10-18"><a href="#cb10-18"></a></span>
|
<span id="cb8-18"><a href="#cb8-18"></a></span>
|
||||||
<span id="cb10-19"><a href="#cb10-19"></a> gtk_init <span class="op">();</span></span>
|
<span id="cb8-19"><a href="#cb8-19"></a> gtk_init <span class="op">();</span></span>
|
||||||
<span id="cb10-20"><a href="#cb10-20"></a> label <span class="op">=</span> GTK_LABEL <span class="op">(</span>gtk_label_new <span class="op">(</span><span class="st">"123+456"</span><span class="op">));</span></span>
|
<span id="cb8-20"><a href="#cb8-20"></a> label <span class="op">=</span> GTK_LABEL <span class="op">(</span>gtk_label_new <span class="op">(</span><span class="st">"123+456"</span><span class="op">));</span></span>
|
||||||
<span id="cb10-21"><a href="#cb10-21"></a> g_object_ref_sink <span class="op">(</span>label<span class="op">);</span></span>
|
<span id="cb8-21"><a href="#cb8-21"></a> g_object_ref_sink <span class="op">(</span>label<span class="op">);</span></span>
|
||||||
<span id="cb10-22"><a href="#cb10-22"></a> expression <span class="op">=</span> gtk_cclosure_expression_new <span class="op">(</span>G_TYPE_INT<span class="op">,</span> NULL<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> NULL<span class="op">,</span></span>
|
<span id="cb8-22"><a href="#cb8-22"></a> expression <span class="op">=</span> gtk_cclosure_expression_new <span class="op">(</span>G_TYPE_INT<span class="op">,</span> NULL<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> NULL<span class="op">,</span></span>
|
||||||
<span id="cb10-23"><a href="#cb10-23"></a> G_CALLBACK <span class="op">(</span>calc<span class="op">),</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
<span id="cb8-23"><a href="#cb8-23"></a> G_CALLBACK <span class="op">(</span>calc<span class="op">),</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb10-24"><a href="#cb10-24"></a> <span class="cf">if</span> <span class="op">(</span>gtk_expression_evaluate <span class="op">(</span>expression<span class="op">,</span> label<span class="op">,</span> <span class="op">&</span>value<span class="op">))</span> <span class="co">/* 'this' object is the label. */</span></span>
|
<span id="cb8-24"><a href="#cb8-24"></a> <span class="cf">if</span> <span class="op">(</span>gtk_expression_evaluate <span class="op">(</span>expression<span class="op">,</span> label<span class="op">,</span> <span class="op">&</span>value<span class="op">))</span> <span class="co">/* 'this' object is the label. */</span></span>
|
||||||
<span id="cb10-25"><a href="#cb10-25"></a> g_print <span class="op">(</span><span class="st">"%d</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> g_value_get_int <span class="op">(&</span>value<span class="op">));</span></span>
|
<span id="cb8-25"><a href="#cb8-25"></a> g_print <span class="op">(</span><span class="st">"%d</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> g_value_get_int <span class="op">(&</span>value<span class="op">));</span></span>
|
||||||
<span id="cb10-26"><a href="#cb10-26"></a> <span class="cf">else</span></span>
|
<span id="cb8-26"><a href="#cb8-26"></a> <span class="cf">else</span></span>
|
||||||
<span id="cb10-27"><a href="#cb10-27"></a> g_print <span class="op">(</span><span class="st">"The closure expression wasn't evaluated correctly.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
<span id="cb8-27"><a href="#cb8-27"></a> g_print <span class="op">(</span><span class="st">"The closure expression wasn't evaluated correctly.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||||
<span id="cb10-28"><a href="#cb10-28"></a> gtk_expression_unref <span class="op">(</span>expression<span class="op">);</span></span>
|
<span id="cb8-28"><a href="#cb8-28"></a> gtk_expression_unref <span class="op">(</span>expression<span class="op">);</span></span>
|
||||||
<span id="cb10-29"><a href="#cb10-29"></a> g_value_unset <span class="op">(&</span>value<span class="op">);</span></span>
|
<span id="cb8-29"><a href="#cb8-29"></a> g_value_unset <span class="op">(&</span>value<span class="op">);</span></span>
|
||||||
<span id="cb10-30"><a href="#cb10-30"></a> g_object_unref <span class="op">(</span>label<span class="op">);</span></span>
|
<span id="cb8-30"><a href="#cb8-30"></a> g_object_unref <span class="op">(</span>label<span class="op">);</span></span>
|
||||||
<span id="cb10-31"><a href="#cb10-31"></a> </span>
|
<span id="cb8-31"><a href="#cb8-31"></a> </span>
|
||||||
<span id="cb10-32"><a href="#cb10-32"></a> <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
|
<span id="cb8-32"><a href="#cb8-32"></a> <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
|
||||||
<span id="cb10-33"><a href="#cb10-33"></a><span class="op">}</span></span></code></pre></div>
|
<span id="cb8-33"><a href="#cb8-33"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>3-11: A call back function. The parameter is only one and it is a
|
<li>3-11: A call back function. The parameter is only one and it is a
|
||||||
‘this’ object. It is a GtkLabel and its label is assumed to be
|
‘this’ object. It is a GtkLabel and its label is assumed to be
|
||||||
|
@ -419,16 +384,17 @@ argument of <code>gtk_cclosure_expression_new</code> is
|
||||||
<code>G_TYPE_POINTER</code>. There is a sample program
|
<code>G_TYPE_POINTER</code>. There is a sample program
|
||||||
<code>exp_closure_with_error_report</code> in
|
<code>exp_closure_with_error_report</code> in
|
||||||
<code>src/expression</code> directory.</li>
|
<code>src/expression</code> directory.</li>
|
||||||
<li>19: gtk_init initializes GTK. It is necessary for GtkLabel.</li>
|
<li>19: The function `gtk_init`` initializes GTK. It is necessary for
|
||||||
|
GtkLabel.</li>
|
||||||
<li>20: A GtkLabel instance is created with “123+456”.</li>
|
<li>20: A GtkLabel instance is created with “123+456”.</li>
|
||||||
<li>21: The instance has floating reference. It is changed to an
|
<li>21: The instance has floating reference. It is changed to an
|
||||||
ordinary reference count.</li>
|
ordinary reference count.</li>
|
||||||
<li>22-23: Create a closure expression. Its return value type is
|
<li>22-23: Creates a closure expression. Its return value type is
|
||||||
<code>G_TYPE_INT</code> and no parameters or ‘this’ object.</li>
|
<code>G_TYPE_INT</code> and no parameters or ‘this’ object.</li>
|
||||||
<li>24: Evaluates the expression with the label as a ‘this’ object.</li>
|
<li>24: Evaluates the expression with the label as a ‘this’ object.</li>
|
||||||
<li>25: If the evaluation successes, show the sum of “123+456”. It’s
|
<li>25: If the evaluation successes, the sum of “123+456”, which is 579,
|
||||||
579.</li>
|
is shown.</li>
|
||||||
<li>27: If it fails, show an error message.</li>
|
<li>27: If it fails, an error message appears.</li>
|
||||||
<li>28-30: Releases the expression and the label. Unsets the value.</li>
|
<li>28-30: Releases the expression and the label. Unsets the value.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Closure expression is flexible than other type of expression because
|
<p>Closure expression is flexible than other type of expression because
|
||||||
|
@ -436,18 +402,19 @@ you can specify your own callback function.</p>
|
||||||
<h2 id="gtkexpressionwatch">GtkExpressionWatch</h2>
|
<h2 id="gtkexpressionwatch">GtkExpressionWatch</h2>
|
||||||
<p>GtkExpressionWatch is a structure, not an object. It represents a
|
<p>GtkExpressionWatch is a structure, not an object. It represents a
|
||||||
watched GtkExpression. Two functions create GtkExpressionWatch
|
watched GtkExpression. Two functions create GtkExpressionWatch
|
||||||
structure.</p>
|
structure. They are <code>gtk_expression_bind</code> and
|
||||||
|
<code>gtk_expression_watch</code>.</p>
|
||||||
<h3 id="gtk_expression_bind-function">gtk_expression_bind function</h3>
|
<h3 id="gtk_expression_bind-function">gtk_expression_bind function</h3>
|
||||||
<p>This function binds the target object’s property to the expression.
|
<p>This function binds the target object’s property to the expression.
|
||||||
If the value of the expression changes, the property reflects the value
|
If the value of the expression changes, the property reflects the value
|
||||||
immediately.</p>
|
immediately.</p>
|
||||||
<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>GtkExpressionWatch<span class="op">*</span></span>
|
<div class="sourceCode" id="cb9"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>GtkExpressionWatch<span class="op">*</span></span>
|
||||||
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>gtk_expression_bind <span class="op">(</span></span>
|
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>gtk_expression_bind <span class="op">(</span></span>
|
||||||
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> GtkExpression<span class="op">*</span> self<span class="op">,</span></span>
|
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> GtkExpression<span class="op">*</span> self<span class="op">,</span></span>
|
||||||
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> GObject<span class="op">*</span> target<span class="op">,</span></span>
|
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a> GObject<span class="op">*</span> target<span class="op">,</span></span>
|
||||||
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> property<span class="op">,</span></span>
|
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> property<span class="op">,</span></span>
|
||||||
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a> GObject<span class="op">*</span> this_</span>
|
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a> GObject<span class="op">*</span> this_</span>
|
||||||
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
|
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
|
||||||
<p>This function takes the ownership of the expression. So, if you want
|
<p>This function takes the ownership of the expression. So, if you want
|
||||||
to own the expression, call <code>gtk_expression_ref ()</code> to
|
to own the expression, call <code>gtk_expression_ref ()</code> to
|
||||||
increase the reference count of the expression. And you should unref it
|
increase the reference count of the expression. And you should unref it
|
||||||
|
@ -463,41 +430,41 @@ about releasing the expression.</p>
|
||||||
the scale value increases and the number on the label also increases. In
|
the scale value increases and the number on the label also increases. In
|
||||||
the same way, if you move it to the left, the number on the label
|
the same way, if you move it to the left, the number on the label
|
||||||
decreases. The label is bound to the scale value via an adjustment.</p>
|
decreases. The label is bound to the scale value via an adjustment.</p>
|
||||||
<div class="sourceCode" id="cb12"><pre
|
<div class="sourceCode" id="cb10"><pre
|
||||||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb12-1"><a href="#cb12-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">'1.0'</span><span class="ot"> encoding=</span><span class="st">'UTF-8'</span><span class="fu">?></span></span>
|
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb10-1"><a href="#cb10-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">'1.0'</span><span class="ot"> encoding=</span><span class="st">'UTF-8'</span><span class="fu">?></span></span>
|
||||||
<span id="cb12-2"><a href="#cb12-2"></a><<span class="kw">interface</span>></span>
|
<span id="cb10-2"><a href="#cb10-2"></a><<span class="kw">interface</span>></span>
|
||||||
<span id="cb12-3"><a href="#cb12-3"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkApplicationWindow'</span><span class="ot"> id=</span><span class="st">'win'</span>></span>
|
<span id="cb10-3"><a href="#cb10-3"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkApplicationWindow'</span><span class="ot"> id=</span><span class="st">'win'</span>></span>
|
||||||
<span id="cb12-4"><a href="#cb12-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'default-width'</span>>600</<span class="kw">property</span>></span>
|
<span id="cb10-4"><a href="#cb10-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'default-width'</span>>600</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-5"><a href="#cb12-5"></a> <<span class="kw">child</span>></span>
|
<span id="cb10-5"><a href="#cb10-5"></a> <<span class="kw">child</span>></span>
|
||||||
<span id="cb12-6"><a href="#cb12-6"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkBox'</span>></span>
|
<span id="cb10-6"><a href="#cb10-6"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkBox'</span>></span>
|
||||||
<span id="cb12-7"><a href="#cb12-7"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'orientation'</span>>GTK_ORIENTATION_VERTICAL</<span class="kw">property</span>></span>
|
<span id="cb10-7"><a href="#cb10-7"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'orientation'</span>>GTK_ORIENTATION_VERTICAL</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-8"><a href="#cb12-8"></a> <<span class="kw">child</span>></span>
|
<span id="cb10-8"><a href="#cb10-8"></a> <<span class="kw">child</span>></span>
|
||||||
<span id="cb12-9"><a href="#cb12-9"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkLabel'</span><span class="ot"> id=</span><span class="st">'label'</span>></span>
|
<span id="cb10-9"><a href="#cb10-9"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkLabel'</span><span class="ot"> id=</span><span class="st">'label'</span>></span>
|
||||||
<span id="cb12-10"><a href="#cb12-10"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>10</<span class="kw">property</span>></span>
|
<span id="cb10-10"><a href="#cb10-10"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>10</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-11"><a href="#cb12-11"></a> </<span class="kw">object</span>></span>
|
<span id="cb10-11"><a href="#cb10-11"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb12-12"><a href="#cb12-12"></a> </<span class="kw">child</span>></span>
|
<span id="cb10-12"><a href="#cb10-12"></a> </<span class="kw">child</span>></span>
|
||||||
<span id="cb12-13"><a href="#cb12-13"></a> <<span class="kw">child</span>></span>
|
<span id="cb10-13"><a href="#cb10-13"></a> <<span class="kw">child</span>></span>
|
||||||
<span id="cb12-14"><a href="#cb12-14"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkScale'</span>></span>
|
<span id="cb10-14"><a href="#cb10-14"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkScale'</span>></span>
|
||||||
<span id="cb12-15"><a href="#cb12-15"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'adjustment'</span>></span>
|
<span id="cb10-15"><a href="#cb10-15"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'adjustment'</span>></span>
|
||||||
<span id="cb12-16"><a href="#cb12-16"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkAdjustment'</span><span class="ot"> id=</span><span class="st">'adjustment'</span>></span>
|
<span id="cb10-16"><a href="#cb10-16"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">'GtkAdjustment'</span><span class="ot"> id=</span><span class="st">'adjustment'</span>></span>
|
||||||
<span id="cb12-17"><a href="#cb12-17"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'upper'</span>>20.0</<span class="kw">property</span>></span>
|
<span id="cb10-17"><a href="#cb10-17"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'upper'</span>>20.0</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-18"><a href="#cb12-18"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'lower'</span>>0.0</<span class="kw">property</span>></span>
|
<span id="cb10-18"><a href="#cb10-18"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'lower'</span>>0.0</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-19"><a href="#cb12-19"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'value'</span>>10.0</<span class="kw">property</span>></span>
|
<span id="cb10-19"><a href="#cb10-19"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'value'</span>>10.0</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-20"><a href="#cb12-20"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'step-increment'</span>>1.0</<span class="kw">property</span>></span>
|
<span id="cb10-20"><a href="#cb10-20"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'step-increment'</span>>1.0</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-21"><a href="#cb12-21"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'page-increment'</span>>5.0</<span class="kw">property</span>></span>
|
<span id="cb10-21"><a href="#cb10-21"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'page-increment'</span>>5.0</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-22"><a href="#cb12-22"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'page-size'</span>>0.0</<span class="kw">property</span>></span>
|
<span id="cb10-22"><a href="#cb10-22"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'page-size'</span>>0.0</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-23"><a href="#cb12-23"></a> </<span class="kw">object</span>></span>
|
<span id="cb10-23"><a href="#cb10-23"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb12-24"><a href="#cb12-24"></a> </<span class="kw">property</span>></span>
|
<span id="cb10-24"><a href="#cb10-24"></a> </<span class="kw">property</span>></span>
|
||||||
<span id="cb12-25"><a href="#cb12-25"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'digits'</span>>0</<span class="kw">property</span>></span>
|
<span id="cb10-25"><a href="#cb10-25"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'digits'</span>>0</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-26"><a href="#cb12-26"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'draw-value'</span>>true</<span class="kw">property</span>></span>
|
<span id="cb10-26"><a href="#cb10-26"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'draw-value'</span>>true</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-27"><a href="#cb12-27"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'has-origin'</span>>true</<span class="kw">property</span>></span>
|
<span id="cb10-27"><a href="#cb10-27"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'has-origin'</span>>true</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-28"><a href="#cb12-28"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'round-digits'</span>>0</<span class="kw">property</span>></span>
|
<span id="cb10-28"><a href="#cb10-28"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">'round-digits'</span>>0</<span class="kw">property</span>></span>
|
||||||
<span id="cb12-29"><a href="#cb12-29"></a> </<span class="kw">object</span>></span>
|
<span id="cb10-29"><a href="#cb10-29"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb12-30"><a href="#cb12-30"></a> </<span class="kw">child</span>></span>
|
<span id="cb10-30"><a href="#cb10-30"></a> </<span class="kw">child</span>></span>
|
||||||
<span id="cb12-31"><a href="#cb12-31"></a> </<span class="kw">object</span>></span>
|
<span id="cb10-31"><a href="#cb10-31"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb12-32"><a href="#cb12-32"></a> </<span class="kw">child</span>></span>
|
<span id="cb10-32"><a href="#cb10-32"></a> </<span class="kw">child</span>></span>
|
||||||
<span id="cb12-33"><a href="#cb12-33"></a> </<span class="kw">object</span>></span>
|
<span id="cb10-33"><a href="#cb10-33"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb12-34"><a href="#cb12-34"></a></<span class="kw">interface</span>></span></code></pre></div>
|
<span id="cb10-34"><a href="#cb10-34"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||||
<p>The ui file describes the following parent-child relationship.</p>
|
<p>The ui file describes the following parent-child relationship.</p>
|
||||||
<pre><code>GtkApplicationWindow (win) -- GtkBox -+- GtkLabel (label)
|
<pre><code>GtkApplicationWindow (win) -- GtkBox -+- GtkLabel (label)
|
||||||
+- GtkScale</code></pre>
|
+- GtkScale</code></pre>
|
||||||
|
@ -523,73 +490,73 @@ orange bar appears between the origin and the current point.</li>
|
||||||
changes. For example, if it is zero, the slider moves to an integer
|
changes. For example, if it is zero, the slider moves to an integer
|
||||||
point.</li>
|
point.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="sourceCode" id="cb14"><pre
|
<div class="sourceCode" id="cb12"><pre
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb12-1"><a href="#cb12-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||||
<span id="cb14-2"><a href="#cb14-2"></a></span>
|
<span id="cb12-2"><a href="#cb12-2"></a></span>
|
||||||
<span id="cb14-3"><a href="#cb14-3"></a>GtkExpressionWatch <span class="op">*</span>watch<span class="op">;</span></span>
|
<span id="cb12-3"><a href="#cb12-3"></a>GtkExpressionWatch <span class="op">*</span>watch<span class="op">;</span></span>
|
||||||
<span id="cb14-4"><a href="#cb14-4"></a></span>
|
<span id="cb12-4"><a href="#cb12-4"></a></span>
|
||||||
<span id="cb14-5"><a href="#cb14-5"></a><span class="dt">static</span> <span class="dt">int</span></span>
|
<span id="cb12-5"><a href="#cb12-5"></a><span class="dt">static</span> <span class="dt">int</span></span>
|
||||||
<span id="cb14-6"><a href="#cb14-6"></a>f2i <span class="op">(</span>GObject <span class="op">*</span>object<span class="op">,</span> <span class="dt">double</span> d<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb12-6"><a href="#cb12-6"></a>f2i <span class="op">(</span>GObject <span class="op">*</span>object<span class="op">,</span> <span class="dt">double</span> d<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb14-7"><a href="#cb14-7"></a> <span class="cf">return</span> <span class="op">(</span><span class="dt">int</span><span class="op">)</span> d<span class="op">;</span></span>
|
<span id="cb12-7"><a href="#cb12-7"></a> <span class="cf">return</span> <span class="op">(</span><span class="dt">int</span><span class="op">)</span> d<span class="op">;</span></span>
|
||||||
<span id="cb14-8"><a href="#cb14-8"></a><span class="op">}</span></span>
|
<span id="cb12-8"><a href="#cb12-8"></a><span class="op">}</span></span>
|
||||||
<span id="cb14-9"><a href="#cb14-9"></a></span>
|
<span id="cb12-9"><a href="#cb12-9"></a></span>
|
||||||
<span id="cb14-10"><a href="#cb14-10"></a><span class="dt">static</span> <span class="dt">int</span></span>
|
<span id="cb12-10"><a href="#cb12-10"></a><span class="dt">static</span> <span class="dt">int</span></span>
|
||||||
<span id="cb14-11"><a href="#cb14-11"></a>close_request_cb <span class="op">(</span>GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb12-11"><a href="#cb12-11"></a>close_request_cb <span class="op">(</span>GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb14-12"><a href="#cb14-12"></a> gtk_expression_watch_unwatch <span class="op">(</span>watch<span class="op">);</span></span>
|
<span id="cb12-12"><a href="#cb12-12"></a> gtk_expression_watch_unwatch <span class="op">(</span>watch<span class="op">);</span></span>
|
||||||
<span id="cb14-13"><a href="#cb14-13"></a> <span class="cf">return</span> false<span class="op">;</span></span>
|
<span id="cb12-13"><a href="#cb12-13"></a> <span class="cf">return</span> false<span class="op">;</span></span>
|
||||||
<span id="cb14-14"><a href="#cb14-14"></a><span class="op">}</span></span>
|
<span id="cb12-14"><a href="#cb12-14"></a><span class="op">}</span></span>
|
||||||
<span id="cb14-15"><a href="#cb14-15"></a></span>
|
<span id="cb12-15"><a href="#cb12-15"></a></span>
|
||||||
<span id="cb14-16"><a href="#cb14-16"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb12-16"><a href="#cb12-16"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb14-17"><a href="#cb14-17"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb12-17"><a href="#cb12-17"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb14-18"><a href="#cb14-18"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
<span id="cb12-18"><a href="#cb12-18"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
||||||
<span id="cb14-19"><a href="#cb14-19"></a> gtk_window_present <span class="op">(</span>gtk_application_get_active_window<span class="op">(</span>app<span class="op">));</span></span>
|
<span id="cb12-19"><a href="#cb12-19"></a> gtk_window_present <span class="op">(</span>gtk_application_get_active_window<span class="op">(</span>app<span class="op">));</span></span>
|
||||||
<span id="cb14-20"><a href="#cb14-20"></a><span class="op">}</span></span>
|
<span id="cb12-20"><a href="#cb12-20"></a><span class="op">}</span></span>
|
||||||
<span id="cb14-21"><a href="#cb14-21"></a></span>
|
<span id="cb12-21"><a href="#cb12-21"></a></span>
|
||||||
<span id="cb14-22"><a href="#cb14-22"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb12-22"><a href="#cb12-22"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb14-23"><a href="#cb14-23"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb12-23"><a href="#cb12-23"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb14-24"><a href="#cb14-24"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
<span id="cb12-24"><a href="#cb12-24"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
||||||
<span id="cb14-25"><a href="#cb14-25"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
|
<span id="cb12-25"><a href="#cb12-25"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
|
||||||
<span id="cb14-26"><a href="#cb14-26"></a> GtkWidget <span class="op">*</span>win<span class="op">,</span> <span class="op">*</span>label<span class="op">;</span></span>
|
<span id="cb12-26"><a href="#cb12-26"></a> GtkWidget <span class="op">*</span>win<span class="op">,</span> <span class="op">*</span>label<span class="op">;</span></span>
|
||||||
<span id="cb14-27"><a href="#cb14-27"></a> GtkAdjustment <span class="op">*</span>adjustment<span class="op">;</span></span>
|
<span id="cb12-27"><a href="#cb12-27"></a> GtkAdjustment <span class="op">*</span>adjustment<span class="op">;</span></span>
|
||||||
<span id="cb14-28"><a href="#cb14-28"></a> GtkExpression <span class="op">*</span>expression<span class="op">,</span> <span class="op">*</span>params<span class="op">[</span><span class="dv">1</span><span class="op">];</span></span>
|
<span id="cb12-28"><a href="#cb12-28"></a> GtkExpression <span class="op">*</span>expression<span class="op">,</span> <span class="op">*</span>params<span class="op">[</span><span class="dv">1</span><span class="op">];</span></span>
|
||||||
<span id="cb14-29"><a href="#cb14-29"></a></span>
|
<span id="cb12-29"><a href="#cb12-29"></a></span>
|
||||||
<span id="cb14-30"><a href="#cb14-30"></a> <span class="co">/* Builds a window with exp.ui resource */</span></span>
|
<span id="cb12-30"><a href="#cb12-30"></a> <span class="co">/* Builds a window with exp.ui resource */</span></span>
|
||||||
<span id="cb14-31"><a href="#cb14-31"></a> build <span class="op">=</span> gtk_builder_new_from_file <span class="op">(</span><span class="st">"exp_bind.ui"</span><span class="op">);</span></span>
|
<span id="cb12-31"><a href="#cb12-31"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">"/com/github/ToshioCP/exp/exp_bind.ui"</span><span class="op">);</span></span>
|
||||||
<span id="cb14-32"><a href="#cb14-32"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"win"</span><span class="op">));</span></span>
|
<span id="cb12-32"><a href="#cb12-32"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"win"</span><span class="op">));</span></span>
|
||||||
<span id="cb14-33"><a href="#cb14-33"></a> label <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"label"</span><span class="op">));</span></span>
|
<span id="cb12-33"><a href="#cb12-33"></a> label <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"label"</span><span class="op">));</span></span>
|
||||||
<span id="cb14-34"><a href="#cb14-34"></a> <span class="co">// scale = GTK_WIDGET (gtk_builder_get_object (build, "scale"));</span></span>
|
<span id="cb12-34"><a href="#cb12-34"></a> <span class="co">// scale = GTK_WIDGET (gtk_builder_get_object (build, "scale"));</span></span>
|
||||||
<span id="cb14-35"><a href="#cb14-35"></a> adjustment <span class="op">=</span> GTK_ADJUSTMENT <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"adjustment"</span><span class="op">));</span></span>
|
<span id="cb12-35"><a href="#cb12-35"></a> adjustment <span class="op">=</span> GTK_ADJUSTMENT <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"adjustment"</span><span class="op">));</span></span>
|
||||||
<span id="cb14-36"><a href="#cb14-36"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> app<span class="op">);</span></span>
|
<span id="cb12-36"><a href="#cb12-36"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> app<span class="op">);</span></span>
|
||||||
<span id="cb14-37"><a href="#cb14-37"></a> g_signal_connect <span class="op">(</span>win<span class="op">,</span> <span class="st">"close-request"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>close_request_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb12-37"><a href="#cb12-37"></a> g_signal_connect <span class="op">(</span>win<span class="op">,</span> <span class="st">"close-request"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>close_request_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb14-38"><a href="#cb14-38"></a> g_object_unref <span class="op">(</span>build<span class="op">);</span></span>
|
<span id="cb12-38"><a href="#cb12-38"></a> g_object_unref <span class="op">(</span>build<span class="op">);</span></span>
|
||||||
<span id="cb14-39"><a href="#cb14-39"></a></span>
|
<span id="cb12-39"><a href="#cb12-39"></a></span>
|
||||||
<span id="cb14-40"><a href="#cb14-40"></a> <span class="co">/* GtkExpressionWatch */</span></span>
|
<span id="cb12-40"><a href="#cb12-40"></a> <span class="co">/* GtkExpressionWatch */</span></span>
|
||||||
<span id="cb14-41"><a href="#cb14-41"></a> params<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">=</span> gtk_property_expression_new <span class="op">(</span>GTK_TYPE_ADJUSTMENT<span class="op">,</span> NULL<span class="op">,</span> <span class="st">"value"</span><span class="op">);</span></span>
|
<span id="cb12-41"><a href="#cb12-41"></a> params<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">=</span> gtk_property_expression_new <span class="op">(</span>GTK_TYPE_ADJUSTMENT<span class="op">,</span> NULL<span class="op">,</span> <span class="st">"value"</span><span class="op">);</span></span>
|
||||||
<span id="cb14-42"><a href="#cb14-42"></a> expression <span class="op">=</span> gtk_cclosure_expression_new <span class="op">(</span>G_TYPE_INT<span class="op">,</span> NULL<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> params<span class="op">,</span> G_CALLBACK <span class="op">(</span>f2i<span class="op">),</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
<span id="cb12-42"><a href="#cb12-42"></a> expression <span class="op">=</span> gtk_cclosure_expression_new <span class="op">(</span>G_TYPE_INT<span class="op">,</span> NULL<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> params<span class="op">,</span> G_CALLBACK <span class="op">(</span>f2i<span class="op">),</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb14-43"><a href="#cb14-43"></a> watch <span class="op">=</span> gtk_expression_bind <span class="op">(</span>expression<span class="op">,</span> label<span class="op">,</span> <span class="st">"label"</span><span class="op">,</span> adjustment<span class="op">);</span> <span class="co">/* watch takes the ownership of the expression. */</span></span>
|
<span id="cb12-43"><a href="#cb12-43"></a> watch <span class="op">=</span> gtk_expression_bind <span class="op">(</span>expression<span class="op">,</span> label<span class="op">,</span> <span class="st">"label"</span><span class="op">,</span> adjustment<span class="op">);</span> <span class="co">/* watch takes the ownership of the expression. */</span></span>
|
||||||
<span id="cb14-44"><a href="#cb14-44"></a><span class="op">}</span></span>
|
<span id="cb12-44"><a href="#cb12-44"></a><span class="op">}</span></span>
|
||||||
<span id="cb14-45"><a href="#cb14-45"></a></span>
|
<span id="cb12-45"><a href="#cb12-45"></a></span>
|
||||||
<span id="cb14-46"><a href="#cb14-46"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.exp_watch"</span></span>
|
<span id="cb12-46"><a href="#cb12-46"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.exp_watch"</span></span>
|
||||||
<span id="cb14-47"><a href="#cb14-47"></a></span>
|
<span id="cb12-47"><a href="#cb12-47"></a></span>
|
||||||
<span id="cb14-48"><a href="#cb14-48"></a><span class="dt">int</span></span>
|
<span id="cb12-48"><a href="#cb12-48"></a><span class="dt">int</span></span>
|
||||||
<span id="cb14-49"><a href="#cb14-49"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb12-49"><a href="#cb12-49"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb14-50"><a href="#cb14-50"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
<span id="cb12-50"><a href="#cb12-50"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||||
<span id="cb14-51"><a href="#cb14-51"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
<span id="cb12-51"><a href="#cb12-51"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||||
<span id="cb14-52"><a href="#cb14-52"></a></span>
|
<span id="cb12-52"><a href="#cb12-52"></a></span>
|
||||||
<span id="cb14-53"><a href="#cb14-53"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
|
<span id="cb12-53"><a href="#cb12-53"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
|
||||||
<span id="cb14-54"><a href="#cb14-54"></a></span>
|
<span id="cb12-54"><a href="#cb12-54"></a></span>
|
||||||
<span id="cb14-55"><a href="#cb14-55"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb12-55"><a href="#cb12-55"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb14-56"><a href="#cb14-56"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb12-56"><a href="#cb12-56"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb14-57"><a href="#cb14-57"></a></span>
|
<span id="cb12-57"><a href="#cb12-57"></a></span>
|
||||||
<span id="cb14-58"><a href="#cb14-58"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
<span id="cb12-58"><a href="#cb12-58"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
||||||
<span id="cb14-59"><a href="#cb14-59"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
<span id="cb12-59"><a href="#cb12-59"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||||
<span id="cb14-60"><a href="#cb14-60"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
<span id="cb12-60"><a href="#cb12-60"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||||
<span id="cb14-61"><a href="#cb14-61"></a><span class="op">}</span></span></code></pre></div>
|
<span id="cb12-61"><a href="#cb12-61"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<p>The point of the program is:</p>
|
<p>The point of the program is:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>41-42: Two expressions are defined. One is a property expression and
|
<li>41-42: Two expressions are defined. One is a property expression and
|
||||||
the other is a closure expression. The property expression look up the
|
the other is a closure expression. The property expression looks up the
|
||||||
“value”property of the adjustment instance. The closure expression just
|
“value” property of the adjustment instance. The closure expression just
|
||||||
converts the double into an integer.</li>
|
converts the double into an integer.</li>
|
||||||
<li>43: <code>gtk_expression_bind</code> binds the label property of the
|
<li>43: <code>gtk_expression_bind</code> binds the label property of the
|
||||||
GtkLabel instance to the integer returned by the closure expression. It
|
GtkLabel instance to the integer returned by the closure expression. It
|
||||||
|
@ -603,24 +570,23 @@ is destroyed.</li>
|
||||||
<code>close_request_cb</code>. This signal is emitted when the close
|
<code>close_request_cb</code>. This signal is emitted when the close
|
||||||
button is clicked. The handler is called just before the window closes.
|
button is clicked. The handler is called just before the window closes.
|
||||||
It is the right moment to make the GtkExpressionWatch unwatched.</li>
|
It is the right moment to make the GtkExpressionWatch unwatched.</li>
|
||||||
<li>10-14: “close-request” signal handler.
|
<li>10-14: “close-request” signal handler. The function
|
||||||
<code>gtk_expression_watch_unwatch (watch)</code> makes the watch stop
|
<code>gtk_expression_watch_unwatch (watch)</code> makes the watch stop
|
||||||
watching the expression. It releases the expression and calls
|
watching the expression. It also releases the expression.</li>
|
||||||
<code>gtk_expression_watch_unref (watch)</code> in it.</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<p>If you want to bind a property to an expression,
|
<p>If you want to bind a property to an expression,
|
||||||
<code>gtk_expression_bind</code> is the best choice. You can do it with
|
<code>gtk_expression_bind</code> is the best choice. You can do it with
|
||||||
<code>gtk_expression_watch</code> function, but it is less suitable.</p>
|
<code>gtk_expression_watch</code> function, but it is less suitable.</p>
|
||||||
<h3 id="gtk_expression_watch-function">gtk_expression_watch
|
<h3 id="gtk_expression_watch-function">gtk_expression_watch
|
||||||
function</h3>
|
function</h3>
|
||||||
<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>GtkExpressionWatch<span class="op">*</span></span>
|
<div class="sourceCode" id="cb13"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>GtkExpressionWatch<span class="op">*</span></span>
|
||||||
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>gtk_expression_watch <span class="op">(</span></span>
|
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>gtk_expression_watch <span class="op">(</span></span>
|
||||||
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a> GtkExpression<span class="op">*</span> self<span class="op">,</span></span>
|
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a> GtkExpression<span class="op">*</span> self<span class="op">,</span></span>
|
||||||
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a> GObject<span class="op">*</span> this_<span class="op">,</span></span>
|
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a> GObject<span class="op">*</span> this_<span class="op">,</span></span>
|
||||||
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a> GtkExpressionNotify notify<span class="op">,</span></span>
|
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a> GtkExpressionNotify notify<span class="op">,</span></span>
|
||||||
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a> gpointer user_data<span class="op">,</span></span>
|
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a> gpointer user_data<span class="op">,</span></span>
|
||||||
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a> GDestroyNotify user_destroy</span>
|
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a> GDestroyNotify user_destroy</span>
|
||||||
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
|
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
|
||||||
<p>The function doesn’t take the ownership of the expression. It differs
|
<p>The function doesn’t take the ownership of the expression. It differs
|
||||||
from <code>gtk_expression_bind</code>. So, you need to release the
|
from <code>gtk_expression_bind</code>. So, you need to release the
|
||||||
expression when it is useless. It creates a GtkExpressionWatch
|
expression when it is useless. It creates a GtkExpressionWatch
|
||||||
|
@ -630,10 +596,10 @@ to give it to the callback. The last parameter is a function to destroy
|
||||||
the <code>user_data</code> when the watch is unwatched. Put NULL if you
|
the <code>user_data</code> when the watch is unwatched. Put NULL if you
|
||||||
don’t need them.</p>
|
don’t need them.</p>
|
||||||
<p>Notify callback has the following format.</p>
|
<p>Notify callback has the following format.</p>
|
||||||
<div class="sourceCode" id="cb16"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span></span>
|
<div class="sourceCode" id="cb14"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span></span>
|
||||||
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>notify <span class="op">(</span></span>
|
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>notify <span class="op">(</span></span>
|
||||||
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a> gpointer user_data</span>
|
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a> gpointer user_data</span>
|
||||||
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
|
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
|
||||||
<p>This function is used to do something when the value of the
|
<p>This function is used to do something when the value of the
|
||||||
expression changes. But if you want to bind a property to the value, use
|
expression changes. But if you want to bind a property to the value, use
|
||||||
<code>gtk_expression_bind</code> instead.</p>
|
<code>gtk_expression_bind</code> instead.</p>
|
||||||
|
@ -646,63 +612,63 @@ window to the standard output.</p>
|
||||||
</figure>
|
</figure>
|
||||||
<p>When you resize the window, the width is displayed in the
|
<p>When you resize the window, the width is displayed in the
|
||||||
terminal.</p>
|
terminal.</p>
|
||||||
<div class="sourceCode" id="cb17"><pre
|
<div class="sourceCode" id="cb15"><pre
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||||
<span id="cb17-2"><a href="#cb17-2"></a></span>
|
<span id="cb15-2"><a href="#cb15-2"></a></span>
|
||||||
<span id="cb17-3"><a href="#cb17-3"></a>GtkExpression <span class="op">*</span>expression<span class="op">;</span></span>
|
<span id="cb15-3"><a href="#cb15-3"></a>GtkExpression <span class="op">*</span>expression<span class="op">;</span></span>
|
||||||
<span id="cb17-4"><a href="#cb17-4"></a>GtkExpressionWatch <span class="op">*</span>watch<span class="op">;</span></span>
|
<span id="cb15-4"><a href="#cb15-4"></a>GtkExpressionWatch <span class="op">*</span>watch<span class="op">;</span></span>
|
||||||
<span id="cb17-5"><a href="#cb17-5"></a></span>
|
<span id="cb15-5"><a href="#cb15-5"></a></span>
|
||||||
<span id="cb17-6"><a href="#cb17-6"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb15-6"><a href="#cb15-6"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb17-7"><a href="#cb17-7"></a>notify <span class="op">(</span>gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb15-7"><a href="#cb15-7"></a>notify <span class="op">(</span>gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb17-8"><a href="#cb17-8"></a> GValue value <span class="op">=</span> G_VALUE_INIT<span class="op">;</span></span>
|
<span id="cb15-8"><a href="#cb15-8"></a> GValue value <span class="op">=</span> G_VALUE_INIT<span class="op">;</span></span>
|
||||||
<span id="cb17-9"><a href="#cb17-9"></a></span>
|
<span id="cb15-9"><a href="#cb15-9"></a></span>
|
||||||
<span id="cb17-10"><a href="#cb17-10"></a> <span class="cf">if</span> <span class="op">(</span>gtk_expression_watch_evaluate <span class="op">(</span>watch<span class="op">,</span> <span class="op">&</span>value<span class="op">))</span></span>
|
<span id="cb15-10"><a href="#cb15-10"></a> <span class="cf">if</span> <span class="op">(</span>gtk_expression_watch_evaluate <span class="op">(</span>watch<span class="op">,</span> <span class="op">&</span>value<span class="op">))</span></span>
|
||||||
<span id="cb17-11"><a href="#cb17-11"></a> g_print <span class="op">(</span><span class="st">"width = %d</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> g_value_get_int <span class="op">(&</span>value<span class="op">));</span></span>
|
<span id="cb15-11"><a href="#cb15-11"></a> g_print <span class="op">(</span><span class="st">"width = %d</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> g_value_get_int <span class="op">(&</span>value<span class="op">));</span></span>
|
||||||
<span id="cb17-12"><a href="#cb17-12"></a> <span class="cf">else</span></span>
|
<span id="cb15-12"><a href="#cb15-12"></a> <span class="cf">else</span></span>
|
||||||
<span id="cb17-13"><a href="#cb17-13"></a> g_print <span class="op">(</span><span class="st">"evaluation failed.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
<span id="cb15-13"><a href="#cb15-13"></a> g_print <span class="op">(</span><span class="st">"evaluation failed.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||||
<span id="cb17-14"><a href="#cb17-14"></a><span class="op">}</span></span>
|
<span id="cb15-14"><a href="#cb15-14"></a><span class="op">}</span></span>
|
||||||
<span id="cb17-15"><a href="#cb17-15"></a></span>
|
<span id="cb15-15"><a href="#cb15-15"></a></span>
|
||||||
<span id="cb17-16"><a href="#cb17-16"></a><span class="dt">static</span> <span class="dt">int</span></span>
|
<span id="cb15-16"><a href="#cb15-16"></a><span class="dt">static</span> <span class="dt">int</span></span>
|
||||||
<span id="cb17-17"><a href="#cb17-17"></a>close_request_cb <span class="op">(</span>GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb15-17"><a href="#cb15-17"></a>close_request_cb <span class="op">(</span>GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb17-18"><a href="#cb17-18"></a> gtk_expression_watch_unwatch <span class="op">(</span>watch<span class="op">);</span></span>
|
<span id="cb15-18"><a href="#cb15-18"></a> gtk_expression_watch_unwatch <span class="op">(</span>watch<span class="op">);</span></span>
|
||||||
<span id="cb17-19"><a href="#cb17-19"></a> gtk_expression_unref <span class="op">(</span>expression<span class="op">);</span></span>
|
<span id="cb15-19"><a href="#cb15-19"></a> gtk_expression_unref <span class="op">(</span>expression<span class="op">);</span></span>
|
||||||
<span id="cb17-20"><a href="#cb17-20"></a> <span class="cf">return</span> false<span class="op">;</span></span>
|
<span id="cb15-20"><a href="#cb15-20"></a> <span class="cf">return</span> false<span class="op">;</span></span>
|
||||||
<span id="cb17-21"><a href="#cb17-21"></a><span class="op">}</span></span>
|
<span id="cb15-21"><a href="#cb15-21"></a><span class="op">}</span></span>
|
||||||
<span id="cb17-22"><a href="#cb17-22"></a></span>
|
<span id="cb15-22"><a href="#cb15-22"></a></span>
|
||||||
<span id="cb17-23"><a href="#cb17-23"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb15-23"><a href="#cb15-23"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb17-24"><a href="#cb17-24"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb15-24"><a href="#cb15-24"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb17-25"><a href="#cb17-25"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
<span id="cb15-25"><a href="#cb15-25"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
||||||
<span id="cb17-26"><a href="#cb17-26"></a> gtk_window_present <span class="op">(</span>gtk_application_get_active_window<span class="op">(</span>app<span class="op">));</span></span>
|
<span id="cb15-26"><a href="#cb15-26"></a> gtk_window_present <span class="op">(</span>gtk_application_get_active_window<span class="op">(</span>app<span class="op">));</span></span>
|
||||||
<span id="cb17-27"><a href="#cb17-27"></a><span class="op">}</span></span>
|
<span id="cb15-27"><a href="#cb15-27"></a><span class="op">}</span></span>
|
||||||
<span id="cb17-28"><a href="#cb17-28"></a></span>
|
<span id="cb15-28"><a href="#cb15-28"></a></span>
|
||||||
<span id="cb17-29"><a href="#cb17-29"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb15-29"><a href="#cb15-29"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb17-30"><a href="#cb17-30"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb15-30"><a href="#cb15-30"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb17-31"><a href="#cb17-31"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
<span id="cb15-31"><a href="#cb15-31"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
||||||
<span id="cb17-32"><a href="#cb17-32"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
<span id="cb15-32"><a href="#cb15-32"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
||||||
<span id="cb17-33"><a href="#cb17-33"></a></span>
|
<span id="cb15-33"><a href="#cb15-33"></a></span>
|
||||||
<span id="cb17-34"><a href="#cb17-34"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_application_window_new <span class="op">(</span>app<span class="op">));</span></span>
|
<span id="cb15-34"><a href="#cb15-34"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_application_window_new <span class="op">(</span>app<span class="op">));</span></span>
|
||||||
<span id="cb17-35"><a href="#cb17-35"></a> g_signal_connect <span class="op">(</span>win<span class="op">,</span> <span class="st">"close-request"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>close_request_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb15-35"><a href="#cb15-35"></a> g_signal_connect <span class="op">(</span>win<span class="op">,</span> <span class="st">"close-request"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>close_request_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb17-36"><a href="#cb17-36"></a></span>
|
<span id="cb15-36"><a href="#cb15-36"></a></span>
|
||||||
<span id="cb17-37"><a href="#cb17-37"></a> expression <span class="op">=</span> gtk_property_expression_new <span class="op">(</span>GTK_TYPE_WINDOW<span class="op">,</span> NULL<span class="op">,</span> <span class="st">"default-width"</span><span class="op">);</span></span>
|
<span id="cb15-37"><a href="#cb15-37"></a> expression <span class="op">=</span> gtk_property_expression_new <span class="op">(</span>GTK_TYPE_WINDOW<span class="op">,</span> NULL<span class="op">,</span> <span class="st">"default-width"</span><span class="op">);</span></span>
|
||||||
<span id="cb17-38"><a href="#cb17-38"></a> watch <span class="op">=</span> gtk_expression_watch <span class="op">(</span>expression<span class="op">,</span> win<span class="op">,</span> notify<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
<span id="cb15-38"><a href="#cb15-38"></a> watch <span class="op">=</span> gtk_expression_watch <span class="op">(</span>expression<span class="op">,</span> win<span class="op">,</span> notify<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb17-39"><a href="#cb17-39"></a><span class="op">}</span></span>
|
<span id="cb15-39"><a href="#cb15-39"></a><span class="op">}</span></span>
|
||||||
<span id="cb17-40"><a href="#cb17-40"></a></span>
|
<span id="cb15-40"><a href="#cb15-40"></a></span>
|
||||||
<span id="cb17-41"><a href="#cb17-41"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.exp_watch"</span></span>
|
<span id="cb15-41"><a href="#cb15-41"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.exp_watch"</span></span>
|
||||||
<span id="cb17-42"><a href="#cb17-42"></a></span>
|
<span id="cb15-42"><a href="#cb15-42"></a></span>
|
||||||
<span id="cb17-43"><a href="#cb17-43"></a><span class="dt">int</span></span>
|
<span id="cb15-43"><a href="#cb15-43"></a><span class="dt">int</span></span>
|
||||||
<span id="cb17-44"><a href="#cb17-44"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb15-44"><a href="#cb15-44"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb17-45"><a href="#cb17-45"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
<span id="cb15-45"><a href="#cb15-45"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||||
<span id="cb17-46"><a href="#cb17-46"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
<span id="cb15-46"><a href="#cb15-46"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||||
<span id="cb17-47"><a href="#cb17-47"></a></span>
|
<span id="cb15-47"><a href="#cb15-47"></a></span>
|
||||||
<span id="cb17-48"><a href="#cb17-48"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
|
<span id="cb15-48"><a href="#cb15-48"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
|
||||||
<span id="cb17-49"><a href="#cb17-49"></a></span>
|
<span id="cb15-49"><a href="#cb15-49"></a></span>
|
||||||
<span id="cb17-50"><a href="#cb17-50"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb15-50"><a href="#cb15-50"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb17-51"><a href="#cb17-51"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb15-51"><a href="#cb15-51"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb17-52"><a href="#cb17-52"></a></span>
|
<span id="cb15-52"><a href="#cb15-52"></a></span>
|
||||||
<span id="cb17-53"><a href="#cb17-53"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
<span id="cb15-53"><a href="#cb15-53"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
||||||
<span id="cb17-54"><a href="#cb17-54"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
<span id="cb15-54"><a href="#cb15-54"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||||
<span id="cb17-55"><a href="#cb17-55"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
<span id="cb15-55"><a href="#cb15-55"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||||
<span id="cb17-56"><a href="#cb17-56"></a><span class="op">}</span></span></code></pre></div>
|
<span id="cb15-56"><a href="#cb15-56"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>37: A property expression looks up the “default-width” property of
|
<li>37: A property expression looks up the “default-width” property of
|
||||||
the window.</li>
|
the window.</li>
|
||||||
|
@ -738,37 +704,36 @@ expressions.</li>
|
||||||
content of an object tag. Name attribute specifies the property name of
|
content of an object tag. Name attribute specifies the property name of
|
||||||
the object. The content is an expression.</li>
|
the object. The content is an expression.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="sourceCode" id="cb18"><pre
|
<div class="sourceCode" id="cb16"><pre
|
||||||
class="sourceCode xml"><code class="sourceCode xml"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><<span class="kw">constant</span><span class="ot"> type=</span><span class="st">"gchararray"</span>>Hello world</<span class="kw">constant</span>></span>
|
class="sourceCode xml"><code class="sourceCode xml"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><<span class="kw">constant</span><span class="ot"> type=</span><span class="st">"gchararray"</span>>Hello world</<span class="kw">constant</span>></span>
|
||||||
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"label"</span><span class="ot"> type=</span><span class="st">"GtkLabel"</span>>label</<span class="kw">lookup</span>></span>
|
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"label"</span><span class="ot"> type=</span><span class="st">"GtkLabel"</span>>label</<span class="kw">lookup</span>></span>
|
||||||
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><<span class="kw">closure</span><span class="ot"> type=</span><span class="st">"gint"</span><span class="ot"> function=</span><span class="st">"callback_function"</span>></<span class="kw">closure</span>></span>
|
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><<span class="kw">closure</span><span class="ot"> type=</span><span class="st">"gint"</span><span class="ot"> function=</span><span class="st">"callback_function"</span>></<span class="kw">closure</span>></span>
|
||||||
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><<span class="kw">bind</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><<span class="kw">bind</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
||||||
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"default-width"</span>>win</<span class="kw">lookup</span>></span>
|
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"default-width"</span>>win</<span class="kw">lookup</span>></span>
|
||||||
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></<span class="kw">bind</span>></span></code></pre></div>
|
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a></<span class="kw">bind</span>></span></code></pre></div>
|
||||||
<p>These tags are usually used for GtkBuilderListItemFactory.</p>
|
<p>These tags are usually used for GtkBuilderListItemFactory.</p>
|
||||||
<div class="sourceCode" id="cb19"><pre
|
<div class="sourceCode" id="cb17"><pre
|
||||||
class="sourceCode xml"><code class="sourceCode xml"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><<span class="kw">interface</span>></span>
|
class="sourceCode xml"><code class="sourceCode xml"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><<span class="kw">interface</span>></span>
|
||||||
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a> <<span class="kw">template</span><span class="ot"> class=</span><span class="st">"GtkListItem"</span>></span>
|
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a> <<span class="kw">template</span><span class="ot"> class=</span><span class="st">"GtkListItem"</span>></span>
|
||||||
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"child"</span>></span>
|
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"child"</span>></span>
|
||||||
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
||||||
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
||||||
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"name"</span><span class="ot"> type=</span><span class="st">"string"</span>></span>
|
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"string"</span><span class="ot"> type=</span><span class="st">"GtkStringObject"</span>></span>
|
||||||
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"item"</span>>GtkListItem</<span class="kw">lookup</span>></span>
|
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"item"</span>>GtkListItem</<span class="kw">lookup</span>></span>
|
||||||
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a> </<span class="kw">lookup</span>></span>
|
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a> </<span class="kw">lookup</span>></span>
|
||||||
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a> </<span class="kw">binding</span>></span>
|
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a> </<span class="kw">binding</span>></span>
|
||||||
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
||||||
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a> </<span class="kw">template</span>></span>
|
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a> </<span class="kw">template</span>></span>
|
||||||
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a></<span class="kw">interface</span>></span></code></pre></div>
|
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||||
|
<p>GtkBuilderListItemFactory uses GtkBuilder to extends the GtkListItem
|
||||||
|
with the XML data.</p>
|
||||||
<p>In the xml file above, “GtkListItem” is an instance of the
|
<p>In the xml file above, “GtkListItem” is an instance of the
|
||||||
GtkListItem template. It is the ‘this’ object given to the expressions.
|
GtkListItem template. It is the ‘this’ object given to the expressions.
|
||||||
(The information is in the <a href="https://blog.gtk.org/2020/09/">GTK
|
(The information is in the <a href="https://blog.gtk.org/2020/09/">GTK
|
||||||
Development Blog</a>).</p>
|
Development Blog</a>).</p>
|
||||||
<p>GtkBuilderListItemFactory uses GtkBuilder to build the XML data. It
|
<p>GtkBuilder calls <code>gtk_expression_bind</code> function when it
|
||||||
sets the current object of the GtkBuilder to the GtkListItem
|
finds a binding tag. The function sets the ‘this’ object like this:</p>
|
||||||
instance.</p>
|
|
||||||
<p>GtkBuilder calls <code>gtk_expression_bind</code> function in the
|
|
||||||
binding tag analysis. The function sets the ‘this’ object like this:</p>
|
|
||||||
<ol type="1">
|
<ol type="1">
|
||||||
<li>If the binding tag has object attribute, the object will be the
|
<li>If the binding tag has object attribute, the object will be the
|
||||||
‘this’ object.</li>
|
‘this’ object.</li>
|
||||||
|
@ -794,41 +759,41 @@ constant tags are not used so often.</p>
|
||||||
window. If you type characters in the entry, the same characters appear
|
window. If you type characters in the entry, the same characters appear
|
||||||
on the label.</p>
|
on the label.</p>
|
||||||
<p>The ui file is as follows.</p>
|
<p>The ui file is as follows.</p>
|
||||||
<div class="sourceCode" id="cb20"><pre
|
<div class="sourceCode" id="cb18"><pre
|
||||||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb20-1"><a href="#cb20-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span>
|
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb18-1"><a href="#cb18-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span>
|
||||||
<span id="cb20-2"><a href="#cb20-2"></a><<span class="kw">interface</span>></span>
|
<span id="cb18-2"><a href="#cb18-2"></a><<span class="kw">interface</span>></span>
|
||||||
<span id="cb20-3"><a href="#cb20-3"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkApplicationWindow"</span><span class="ot"> id=</span><span class="st">"win"</span>></span>
|
<span id="cb18-3"><a href="#cb18-3"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkApplicationWindow"</span><span class="ot"> id=</span><span class="st">"win"</span>></span>
|
||||||
<span id="cb20-4"><a href="#cb20-4"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"title"</span>></span>
|
<span id="cb18-4"><a href="#cb18-4"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"title"</span>></span>
|
||||||
<span id="cb20-5"><a href="#cb20-5"></a> <<span class="kw">closure</span><span class="ot"> type=</span><span class="st">"gchararray"</span><span class="ot"> function=</span><span class="st">"set_title"</span>></span>
|
<span id="cb18-5"><a href="#cb18-5"></a> <<span class="kw">closure</span><span class="ot"> type=</span><span class="st">"gchararray"</span><span class="ot"> function=</span><span class="st">"set_title"</span>></span>
|
||||||
<span id="cb20-6"><a href="#cb20-6"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"default-width"</span><span class="ot"> type=</span><span class="st">"GtkWindow"</span>></<span class="kw">lookup</span>></span>
|
<span id="cb18-6"><a href="#cb18-6"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"default-width"</span><span class="ot"> type=</span><span class="st">"GtkWindow"</span>></<span class="kw">lookup</span>></span>
|
||||||
<span id="cb20-7"><a href="#cb20-7"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"default-height"</span><span class="ot"> type=</span><span class="st">"GtkWindow"</span>></<span class="kw">lookup</span>></span>
|
<span id="cb18-7"><a href="#cb18-7"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"default-height"</span><span class="ot"> type=</span><span class="st">"GtkWindow"</span>></<span class="kw">lookup</span>></span>
|
||||||
<span id="cb20-8"><a href="#cb20-8"></a> </<span class="kw">closure</span>></span>
|
<span id="cb18-8"><a href="#cb18-8"></a> </<span class="kw">closure</span>></span>
|
||||||
<span id="cb20-9"><a href="#cb20-9"></a> </<span class="kw">binding</span>></span>
|
<span id="cb18-9"><a href="#cb18-9"></a> </<span class="kw">binding</span>></span>
|
||||||
<span id="cb20-10"><a href="#cb20-10"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-width"</span>>600</<span class="kw">property</span>></span>
|
<span id="cb18-10"><a href="#cb18-10"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-width"</span>>600</<span class="kw">property</span>></span>
|
||||||
<span id="cb20-11"><a href="#cb20-11"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-height"</span>>400</<span class="kw">property</span>></span>
|
<span id="cb18-11"><a href="#cb18-11"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-height"</span>>400</<span class="kw">property</span>></span>
|
||||||
<span id="cb20-12"><a href="#cb20-12"></a> <<span class="kw">child</span>></span>
|
<span id="cb18-12"><a href="#cb18-12"></a> <<span class="kw">child</span>></span>
|
||||||
<span id="cb20-13"><a href="#cb20-13"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span>></span>
|
<span id="cb18-13"><a href="#cb18-13"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span>></span>
|
||||||
<span id="cb20-14"><a href="#cb20-14"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_VERTICAL</<span class="kw">property</span>></span>
|
<span id="cb18-14"><a href="#cb18-14"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_VERTICAL</<span class="kw">property</span>></span>
|
||||||
<span id="cb20-15"><a href="#cb20-15"></a> <<span class="kw">child</span>></span>
|
<span id="cb18-15"><a href="#cb18-15"></a> <<span class="kw">child</span>></span>
|
||||||
<span id="cb20-16"><a href="#cb20-16"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
<span id="cb18-16"><a href="#cb18-16"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
||||||
<span id="cb20-17"><a href="#cb20-17"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
<span id="cb18-17"><a href="#cb18-17"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
||||||
<span id="cb20-18"><a href="#cb20-18"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"text"</span>></span>
|
<span id="cb18-18"><a href="#cb18-18"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"text"</span>></span>
|
||||||
<span id="cb20-19"><a href="#cb20-19"></a> buffer</span>
|
<span id="cb18-19"><a href="#cb18-19"></a> buffer</span>
|
||||||
<span id="cb20-20"><a href="#cb20-20"></a> </<span class="kw">lookup</span>></span>
|
<span id="cb18-20"><a href="#cb18-20"></a> </<span class="kw">lookup</span>></span>
|
||||||
<span id="cb20-21"><a href="#cb20-21"></a> </<span class="kw">binding</span>></span>
|
<span id="cb18-21"><a href="#cb18-21"></a> </<span class="kw">binding</span>></span>
|
||||||
<span id="cb20-22"><a href="#cb20-22"></a> </<span class="kw">object</span>></span>
|
<span id="cb18-22"><a href="#cb18-22"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb20-23"><a href="#cb20-23"></a> </<span class="kw">child</span>></span>
|
<span id="cb18-23"><a href="#cb18-23"></a> </<span class="kw">child</span>></span>
|
||||||
<span id="cb20-24"><a href="#cb20-24"></a> <<span class="kw">child</span>></span>
|
<span id="cb18-24"><a href="#cb18-24"></a> <<span class="kw">child</span>></span>
|
||||||
<span id="cb20-25"><a href="#cb20-25"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkEntry"</span>></span>
|
<span id="cb18-25"><a href="#cb18-25"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkEntry"</span>></span>
|
||||||
<span id="cb20-26"><a href="#cb20-26"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"buffer"</span>></span>
|
<span id="cb18-26"><a href="#cb18-26"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"buffer"</span>></span>
|
||||||
<span id="cb20-27"><a href="#cb20-27"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkEntryBuffer"</span><span class="ot"> id=</span><span class="st">"buffer"</span>></<span class="kw">object</span>></span>
|
<span id="cb18-27"><a href="#cb18-27"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkEntryBuffer"</span><span class="ot"> id=</span><span class="st">"buffer"</span>></<span class="kw">object</span>></span>
|
||||||
<span id="cb20-28"><a href="#cb20-28"></a> </<span class="kw">property</span>></span>
|
<span id="cb18-28"><a href="#cb18-28"></a> </<span class="kw">property</span>></span>
|
||||||
<span id="cb20-29"><a href="#cb20-29"></a> </<span class="kw">object</span>></span>
|
<span id="cb18-29"><a href="#cb18-29"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb20-30"><a href="#cb20-30"></a> </<span class="kw">child</span>></span>
|
<span id="cb18-30"><a href="#cb18-30"></a> </<span class="kw">child</span>></span>
|
||||||
<span id="cb20-31"><a href="#cb20-31"></a> </<span class="kw">object</span>></span>
|
<span id="cb18-31"><a href="#cb18-31"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb20-32"><a href="#cb20-32"></a> </<span class="kw">child</span>></span>
|
<span id="cb18-32"><a href="#cb18-32"></a> </<span class="kw">child</span>></span>
|
||||||
<span id="cb20-33"><a href="#cb20-33"></a> </<span class="kw">object</span>></span>
|
<span id="cb18-33"><a href="#cb18-33"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb20-34"><a href="#cb20-34"></a></<span class="kw">interface</span>></span></code></pre></div>
|
<span id="cb18-34"><a href="#cb18-34"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>4-9: The title property of the main window is bound to a closure
|
<li>4-9: The title property of the main window is bound to a closure
|
||||||
expression. Its callback function <code>set_title</code> is defined in
|
expression. Its callback function <code>set_title</code> is defined in
|
||||||
|
@ -844,48 +809,48 @@ defined in line 25. If a user types characters in the entry, the same
|
||||||
characters appear on the label.</li>
|
characters appear on the label.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>The C source file is as follows.</p>
|
<p>The C source file is as follows.</p>
|
||||||
<div class="sourceCode" id="cb21"><pre
|
<div class="sourceCode" id="cb19"><pre
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb21-1"><a href="#cb21-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb19-1"><a href="#cb19-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||||
<span id="cb21-2"><a href="#cb21-2"></a></span>
|
<span id="cb19-2"><a href="#cb19-2"></a></span>
|
||||||
<span id="cb21-3"><a href="#cb21-3"></a><span class="dt">char</span> <span class="op">*</span></span>
|
<span id="cb19-3"><a href="#cb19-3"></a><span class="dt">char</span> <span class="op">*</span></span>
|
||||||
<span id="cb21-4"><a href="#cb21-4"></a>set_title <span class="op">(</span>GtkWidget <span class="op">*</span>win<span class="op">,</span> <span class="dt">int</span> width<span class="op">,</span> <span class="dt">int</span> height<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb19-4"><a href="#cb19-4"></a>set_title <span class="op">(</span>GtkWidget <span class="op">*</span>win<span class="op">,</span> <span class="dt">int</span> width<span class="op">,</span> <span class="dt">int</span> height<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb21-5"><a href="#cb21-5"></a> <span class="cf">return</span> g_strdup_printf <span class="op">(</span><span class="st">"%d x %d"</span><span class="op">,</span> width<span class="op">,</span> height<span class="op">);</span></span>
|
<span id="cb19-5"><a href="#cb19-5"></a> <span class="cf">return</span> g_strdup_printf <span class="op">(</span><span class="st">"%d x %d"</span><span class="op">,</span> width<span class="op">,</span> height<span class="op">);</span></span>
|
||||||
<span id="cb21-6"><a href="#cb21-6"></a><span class="op">}</span></span>
|
<span id="cb19-6"><a href="#cb19-6"></a><span class="op">}</span></span>
|
||||||
<span id="cb21-7"><a href="#cb21-7"></a></span>
|
<span id="cb19-7"><a href="#cb19-7"></a></span>
|
||||||
<span id="cb21-8"><a href="#cb21-8"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb19-8"><a href="#cb19-8"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb21-9"><a href="#cb21-9"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb19-9"><a href="#cb19-9"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb21-10"><a href="#cb21-10"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
<span id="cb19-10"><a href="#cb19-10"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
||||||
<span id="cb21-11"><a href="#cb21-11"></a> gtk_window_present <span class="op">(</span>gtk_application_get_active_window<span class="op">(</span>app<span class="op">));</span></span>
|
<span id="cb19-11"><a href="#cb19-11"></a> gtk_window_present <span class="op">(</span>gtk_application_get_active_window<span class="op">(</span>app<span class="op">));</span></span>
|
||||||
<span id="cb21-12"><a href="#cb21-12"></a><span class="op">}</span></span>
|
<span id="cb19-12"><a href="#cb19-12"></a><span class="op">}</span></span>
|
||||||
<span id="cb21-13"><a href="#cb21-13"></a></span>
|
<span id="cb19-13"><a href="#cb19-13"></a></span>
|
||||||
<span id="cb21-14"><a href="#cb21-14"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb19-14"><a href="#cb19-14"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb21-15"><a href="#cb21-15"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb19-15"><a href="#cb19-15"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb21-16"><a href="#cb21-16"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
<span id="cb19-16"><a href="#cb19-16"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
||||||
<span id="cb21-17"><a href="#cb21-17"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
|
<span id="cb19-17"><a href="#cb19-17"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
|
||||||
<span id="cb21-18"><a href="#cb21-18"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
<span id="cb19-18"><a href="#cb19-18"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
||||||
<span id="cb21-19"><a href="#cb21-19"></a></span>
|
<span id="cb19-19"><a href="#cb19-19"></a></span>
|
||||||
<span id="cb21-20"><a href="#cb21-20"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">"/com/github/ToshioCP/exp/exp.ui"</span><span class="op">);</span></span>
|
<span id="cb19-20"><a href="#cb19-20"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">"/com/github/ToshioCP/exp/exp.ui"</span><span class="op">);</span></span>
|
||||||
<span id="cb21-21"><a href="#cb21-21"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"win"</span><span class="op">));</span></span>
|
<span id="cb19-21"><a href="#cb19-21"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"win"</span><span class="op">));</span></span>
|
||||||
<span id="cb21-22"><a href="#cb21-22"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> app<span class="op">);</span></span>
|
<span id="cb19-22"><a href="#cb19-22"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> app<span class="op">);</span></span>
|
||||||
<span id="cb21-23"><a href="#cb21-23"></a> g_object_unref <span class="op">(</span>build<span class="op">);</span></span>
|
<span id="cb19-23"><a href="#cb19-23"></a> g_object_unref <span class="op">(</span>build<span class="op">);</span></span>
|
||||||
<span id="cb21-24"><a href="#cb21-24"></a><span class="op">}</span></span>
|
<span id="cb19-24"><a href="#cb19-24"></a><span class="op">}</span></span>
|
||||||
<span id="cb21-25"><a href="#cb21-25"></a></span>
|
<span id="cb19-25"><a href="#cb19-25"></a></span>
|
||||||
<span id="cb21-26"><a href="#cb21-26"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.exp"</span></span>
|
<span id="cb19-26"><a href="#cb19-26"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.exp"</span></span>
|
||||||
<span id="cb21-27"><a href="#cb21-27"></a></span>
|
<span id="cb19-27"><a href="#cb19-27"></a></span>
|
||||||
<span id="cb21-28"><a href="#cb21-28"></a><span class="dt">int</span></span>
|
<span id="cb19-28"><a href="#cb19-28"></a><span class="dt">int</span></span>
|
||||||
<span id="cb21-29"><a href="#cb21-29"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb19-29"><a href="#cb19-29"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb21-30"><a href="#cb21-30"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
<span id="cb19-30"><a href="#cb19-30"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||||
<span id="cb21-31"><a href="#cb21-31"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
<span id="cb19-31"><a href="#cb19-31"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||||
<span id="cb21-32"><a href="#cb21-32"></a></span>
|
<span id="cb19-32"><a href="#cb19-32"></a></span>
|
||||||
<span id="cb21-33"><a href="#cb21-33"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
|
<span id="cb19-33"><a href="#cb19-33"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
|
||||||
<span id="cb21-34"><a href="#cb21-34"></a></span>
|
<span id="cb19-34"><a href="#cb19-34"></a></span>
|
||||||
<span id="cb21-35"><a href="#cb21-35"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb19-35"><a href="#cb19-35"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb21-36"><a href="#cb21-36"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb19-36"><a href="#cb19-36"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb21-37"><a href="#cb21-37"></a></span>
|
<span id="cb19-37"><a href="#cb19-37"></a></span>
|
||||||
<span id="cb21-38"><a href="#cb21-38"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
<span id="cb19-38"><a href="#cb19-38"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
||||||
<span id="cb21-39"><a href="#cb21-39"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
<span id="cb19-39"><a href="#cb19-39"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||||
<span id="cb21-40"><a href="#cb21-40"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
<span id="cb19-40"><a href="#cb19-40"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||||
<span id="cb21-41"><a href="#cb21-41"></a><span class="op">}</span></span></code></pre></div>
|
<span id="cb19-41"><a href="#cb19-41"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>4-6: The callback function. It returns a string (w)x(h), where the w
|
<li>4-6: The callback function. It returns a string (w)x(h), where the w
|
||||||
and h are the width and height of the window. String duplication is
|
and h are the width and height of the window. String duplication is
|
||||||
|
@ -893,18 +858,18 @@ necessary.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>The C source file is very simple because almost everything is done in
|
<p>The C source file is very simple because almost everything is done in
|
||||||
the ui file.</p>
|
the ui file.</p>
|
||||||
<h3 id="conversion-between-gvalues">Conversion between GValues</h3>
|
<h2 id="conversion-between-gvalues">Conversion between GValues</h2>
|
||||||
<p>If you bind different type properties, type conversion is
|
<p>If you bind different type properties, type conversion is
|
||||||
automatically done. Suppose a label property (string) is bound to
|
automatically done. Suppose a label property (string) is bound to
|
||||||
default-width property (int).</p>
|
default-width property (int).</p>
|
||||||
<div class="sourceCode" id="cb22"><pre
|
<div class="sourceCode" id="cb20"><pre
|
||||||
class="sourceCode xml"><code class="sourceCode xml"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
class="sourceCode xml"><code class="sourceCode xml"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
||||||
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
||||||
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"default-width"</span>></span>
|
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"default-width"</span>></span>
|
||||||
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a> win</span>
|
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a> win</span>
|
||||||
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a> </<span class="kw">lookup</span>></span>
|
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a> </<span class="kw">lookup</span>></span>
|
||||||
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a> </<span class="kw">binding</span>></span>
|
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a> </<span class="kw">binding</span>></span>
|
||||||
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a></<span class="kw">object</span>></span></code></pre></div>
|
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a></<span class="kw">object</span>></span></code></pre></div>
|
||||||
<p>The expression created by the lookup tag returns a int type GValue.
|
<p>The expression created by the lookup tag returns a int type GValue.
|
||||||
On the other hand “label” property holds a string type GValue. When a
|
On the other hand “label” property holds a string type GValue. When a
|
||||||
GValue is copied to another GValue, the type is automatically converted
|
GValue is copied to another GValue, the type is automatically converted
|
||||||
|
@ -912,6 +877,37 @@ if possible. If the current width is 100, an int <code>100</code> is
|
||||||
converted to a string <code>"100"</code>.</p>
|
converted to a string <code>"100"</code>.</p>
|
||||||
<p>If you use <code>g_object_get</code> and <code>g_object_set</code> to
|
<p>If you use <code>g_object_get</code> and <code>g_object_set</code> to
|
||||||
copy properties, the value is automatically converted.</p>
|
copy properties, the value is automatically converted.</p>
|
||||||
|
<h2 id="meson.build">Meson.build</h2>
|
||||||
|
<p>The source files are in <code>src/expression</code> directory. You
|
||||||
|
can build all the files at once.</p>
|
||||||
|
<pre><code>$ cd src/expression
|
||||||
|
$ meson setup _build
|
||||||
|
$ ninja -C _build</code></pre>
|
||||||
|
<p>For example, if you want to run “exp”, which is the executable file
|
||||||
|
from “exp.c”, type <code>_build/exp</code>. You can run other programs
|
||||||
|
as well.</p>
|
||||||
|
<p>The file <code>meson.build</code> is as follows.</p>
|
||||||
|
<div class="sourceCode" id="cb22"><pre
|
||||||
|
class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb22-1"><a href="#cb22-1"></a>project('exp', 'c')</span>
|
||||||
|
<span id="cb22-2"><a href="#cb22-2"></a></span>
|
||||||
|
<span id="cb22-3"><a href="#cb22-3"></a>gtkdep = dependency('gtk4')</span>
|
||||||
|
<span id="cb22-4"><a href="#cb22-4"></a></span>
|
||||||
|
<span id="cb22-5"><a href="#cb22-5"></a>gnome=import('gnome')</span>
|
||||||
|
<span id="cb22-6"><a href="#cb22-6"></a>resources = gnome.compile_resources('resources','exp.gresource.xml')</span>
|
||||||
|
<span id="cb22-7"><a href="#cb22-7"></a></span>
|
||||||
|
<span id="cb22-8"><a href="#cb22-8"></a>sourcefiles=files('exp.c')</span>
|
||||||
|
<span id="cb22-9"><a href="#cb22-9"></a></span>
|
||||||
|
<span id="cb22-10"><a href="#cb22-10"></a>executable('exp', sourcefiles, resources, dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-11"><a href="#cb22-11"></a>executable('exp_constant', 'exp_constant.c', dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-12"><a href="#cb22-12"></a>executable('exp_constant_simple', 'exp_constant_simple.c', dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-13"><a href="#cb22-13"></a>executable('exp_property_simple', 'exp_property_simple.c', dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-14"><a href="#cb22-14"></a>executable('closure', 'closure.c', dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-15"><a href="#cb22-15"></a>executable('closure_each', 'closure_each.c', dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-16"><a href="#cb22-16"></a>executable('exp_closure_simple', 'exp_closure_simple.c', dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-17"><a href="#cb22-17"></a>executable('exp_closure_with_error_report', 'exp_closure_with_error_report.c', dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-18"><a href="#cb22-18"></a>executable('exp_bind', 'exp_bind.c', resources, dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-19"><a href="#cb22-19"></a>executable('exp_watch', 'exp_watch.c', dependencies: gtkdep, export_dynamic: true, install: false)</span>
|
||||||
|
<span id="cb22-20"><a href="#cb22-20"></a>executable('exp_test', 'exp_test.c', resources, dependencies: gtkdep, export_dynamic: true, install: false)</span></code></pre></div>
|
||||||
</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>
|
||||||
|
|
|
@ -328,10 +328,9 @@ header of the column.</li>
|
||||||
as much as possible. (See the image above).</li>
|
as much as possible. (See the image above).</li>
|
||||||
<li>33- 69: Sets the “factory” property to GtkBuilderListItemFactory.
|
<li>33- 69: Sets the “factory” property to GtkBuilderListItemFactory.
|
||||||
The factory has “bytes” property which holds a ui string to define a
|
The factory has “bytes” property which holds a ui string to define a
|
||||||
template to build GtkListItem composite widget. The CDATA section (line
|
template to extend GtkListItem class. The CDATA section (line 36-66) is
|
||||||
36-66) is the ui string to put into the “bytes” property. The contents
|
the ui string to put into the “bytes” property. The contents are the
|
||||||
are the same as the ui file <code>factory_list.ui</code> in the section
|
same as the ui file <code>factory_list.ui</code> in the section 30.</li>
|
||||||
27.</li>
|
|
||||||
<li>70-77: Sets the “sorter” property to GtkStringSorter object. This
|
<li>70-77: Sets the “sorter” property to GtkStringSorter object. This
|
||||||
object provides a sorter that compares strings. It has “expression”
|
object provides a sorter that compares strings. It has “expression”
|
||||||
property. A closure tag with a string type function
|
property. A closure tag with a string type function
|
||||||
|
@ -542,7 +541,8 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
||||||
<h2 id="compilation-and-execution.">Compilation and execution.</h2>
|
<h2 id="compilation-and-execution.">Compilation and execution.</h2>
|
||||||
<p>All the source files are in <code>src/column</code> directory. Change
|
<p>All the source files are in <code>src/column</code> directory. Change
|
||||||
your current directory to the directory and type the following.</p>
|
your current directory to the directory and type the following.</p>
|
||||||
<pre><code>$ meson _build
|
<pre><code>$ cd src/colomn
|
||||||
|
$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/column</code></pre>
|
$ _build/column</code></pre>
|
||||||
<p>Then, a window appears.</p>
|
<p>Then, a window appears.</p>
|
||||||
|
|
393
docs/sec33.html
393
docs/sec33.html
|
@ -116,25 +116,14 @@ and GtkBulderListItemFactory</h2>
|
||||||
the contents of a list. Its binding direction is always from an item of
|
the contents of a list. Its binding direction is always from an item of
|
||||||
a list to a child of GtkListItem.</p>
|
a list to a child of GtkListItem.</p>
|
||||||
<p>When it comes to dynamic connection, it’s not enough. For example,
|
<p>When it comes to dynamic connection, it’s not enough. For example,
|
||||||
you want to edit the contents of a list. You set a child of GtkListItem
|
suppose you want to edit the contents of a list. You set a child of
|
||||||
to a GtkText instance so a user can edit a text with it. You need to
|
GtkListItem to a GtkText instance so a user can edit a text with it. You
|
||||||
bind an item in the list with the buffer of the GtkText. The direction
|
need to bind an item in the list with the buffer of the GtkText. The
|
||||||
is opposite from the one with GtkBuilderListItemFactory. It is from the
|
direction is opposite from the one with GtkBuilderListItemFactory. It is
|
||||||
GtkText instance to the item in the list. You can implement this with
|
from the GtkText instance to the item in the list. You can implement
|
||||||
GtkSignalListItemFactory, which is more flexible than
|
this with GtkSignalListItemFactory, which is more flexible than
|
||||||
GtkBuilderListItemFactory.</p>
|
GtkBuilderListItemFactory.</p>
|
||||||
<p>Two things are shown in this section.</p>
|
<p>This section shows just some parts of the source file
|
||||||
<ul>
|
|
||||||
<li>Binding from a child of a GtkListItem instance to an item of a
|
|
||||||
list.</li>
|
|
||||||
<li>Access a child of GtkListItem dynamically. This direction is the
|
|
||||||
same as the one with GtkBulderListItemFactory. But
|
|
||||||
GtkBulderListItemFactory uses GtkExpression from the item property of
|
|
||||||
the GtkListItem. So, it updates its child widget only when the item
|
|
||||||
property changes. In this example the child reflects the change in the
|
|
||||||
same item in the list dynamically.</li>
|
|
||||||
</ul>
|
|
||||||
<p>This section shows just a part of the source file
|
|
||||||
<code>listeditor.c</code>. If you want to see the whole codes, see
|
<code>listeditor.c</code>. If you want to see the whole codes, see
|
||||||
<code>src/listeditor</code> directory of the <a
|
<code>src/listeditor</code> directory of the <a
|
||||||
href="https://github.com/ToshioCP/Gtk4-tutorial">Gtk4 tutorial
|
href="https://github.com/ToshioCP/Gtk4-tutorial">Gtk4 tutorial
|
||||||
|
@ -143,7 +132,7 @@ repository</a>.</p>
|
||||||
<p>The sample program is a list editor and data of the list are strings.
|
<p>The sample program is a list editor and data of the list are strings.
|
||||||
It’s the same as a line editor. It reads a text file line by line. Each
|
It’s the same as a line editor. It reads a text file line by line. Each
|
||||||
line is an item of the list. The list is displayed with GtkColumnView.
|
line is an item of the list. The list is displayed with GtkColumnView.
|
||||||
There are two columns. The one is a button, which makes the line be a
|
There are two columns. The one is a button, which shows if the line is a
|
||||||
current line. If the line is the current line, the button is colored
|
current line. If the line is the current line, the button is colored
|
||||||
with red. The other is a string which is the contents of the
|
with red. The other is a string which is the contents of the
|
||||||
corresponding item of the list.</p>
|
corresponding item of the list.</p>
|
||||||
|
@ -159,18 +148,19 @@ href="https://github.com/ToshioCP/Gtk4-tutorial">repository</a>.</li>
|
||||||
<li>Change your current directory to <code>src/listeditor</code>.</li>
|
<li>Change your current directory to <code>src/listeditor</code>.</li>
|
||||||
<li>Type the following on your commandline.</li>
|
<li>Type the following on your commandline.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<pre><code>$ meson _build
|
<pre><code>$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/listeditor</code></pre>
|
$ _build/listeditor</code></pre>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Append button: appends a line after the current line, or at the last
|
<li>Append button: appends a line after the current line, or at the last
|
||||||
line if no current line exists.</li>
|
line if no current line exists.</li>
|
||||||
<li>Insert button: inserts a line before the current line.</li>
|
<li>Insert button: inserts a line before the current line, or at the top
|
||||||
|
line if no current line exists.</li>
|
||||||
<li>Remove button: removes a current line.</li>
|
<li>Remove button: removes a current line.</li>
|
||||||
<li>Read button: reads a file.</li>
|
<li>Read button: reads a file.</li>
|
||||||
<li>Write button: writes the contents to a file.</li>
|
<li>Write button: writes the contents to a file.</li>
|
||||||
<li>close button: close the contents.</li>
|
<li>close button: closes the contents.</li>
|
||||||
<li>quit button: quit the application.</li>
|
<li>quit button: quits the application.</li>
|
||||||
<li>Button on the select column: makes the line current.</li>
|
<li>Button on the select column: makes the line current.</li>
|
||||||
<li>String column: GtkText. You can edit a string in the field.</li>
|
<li>String column: GtkText. You can edit a string in the field.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -180,7 +170,7 @@ bar. The file name is shown at the right of the write button.</p>
|
||||||
GtkText instance and an item in the list</h2>
|
GtkText instance and an item in the list</h2>
|
||||||
<p>The second column (GtkColumnViewColumn) sets its factory property to
|
<p>The second column (GtkColumnViewColumn) sets its factory property to
|
||||||
GtkSignalListItemFactory. It uses three signals setup, bind and unbind.
|
GtkSignalListItemFactory. It uses three signals setup, bind and unbind.
|
||||||
The following is their sgnal handlers.</p>
|
The following shows the signal handlers.</p>
|
||||||
<div class="sourceCode" id="cb2"><pre
|
<div class="sourceCode" id="cb2"><pre
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">static</span> <span class="dt">void</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-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>
|
||||||
|
@ -193,7 +183,7 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
||||||
<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-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> 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-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> gtk_text_get_buffer <span class="op">(</span>GTK_TEXT <span class="op">(</span>text<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> 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-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> GBinding <span class="op">*</span>bind<span class="op">;</span></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></span>
|
<span id="cb2-14"><a href="#cb2-14"></a></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-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>
|
||||||
|
@ -207,9 +197,10 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
||||||
<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-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> 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-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></span>
|
<span id="cb2-25"><a href="#cb2-25"></a></span>
|
||||||
<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-26"><a href="#cb2-26"></a> <span class="cf">if</span> <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-27"><a href="#cb2-27"></a> g_binding_unbind<span class="op">(</span>bind<span class="op">);</span></span>
|
||||||
<span id="cb2-28"><a href="#cb2-28"></a><span class="op">}</span></span></code></pre></div>
|
<span id="cb2-28"><a href="#cb2-28"></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-29"><a href="#cb2-29"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>1-6: <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
|
||||||
|
@ -221,22 +212,18 @@ is destroyed. So, teardown signal handler isn’t necessary.</li>
|
||||||
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 string data which is the content of the
|
||||||
<code>listitem</code> which points a first column GtkListItem instance
|
line.
|
||||||
when they are connected. Be careful that the GtkListItem instance is
|
|
||||||
<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>10-11: <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. And <code>buffer</code> is a GtkTextBuffer
|
it is a GtkText instance. And <code>buffer</code> is a GtkEntryBuffer
|
||||||
instance of the <code>text</code>.</li>
|
instance of the <code>text</code>.</li>
|
||||||
<li>12: The LeData instance <code>data</code> is an item pointed by the
|
<li>12: The LeData instance <code>data</code> is an item pointed by the
|
||||||
<code>listitem</code>.</li>
|
<code>listitem</code>.</li>
|
||||||
<li>15-16: Sets the text of <code>text</code> to
|
<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 <code>data</code> and the ownership of the string is still
|
string of the <code>data</code> and the ownership of the string is still
|
||||||
taken by the <code>data</code>. So, the caller don’t need to free the
|
taken by the <code>data</code>. So, the caller doesn’t need to free the
|
||||||
string.</li>
|
string.</li>
|
||||||
<li>18: <code>g_object_bind_property</code> binds a property and another
|
<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
|
||||||
|
@ -254,16 +241,22 @@ value. This line sets the association from “bind” to <code>bind</code>
|
||||||
instance. It makes possible for the “unbind” handler to get the
|
instance. It makes possible for the “unbind” handler to get the
|
||||||
<code>bind</code> instance.</li>
|
<code>bind</code> instance.</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
<li>22-28: <code>unbind2_cb</code> is a unbind signal handler.
|
<li>22-29: <code>unbind2_cb</code> is a unbind signal handler.
|
||||||
<ul>
|
<ul>
|
||||||
<li>24: 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>26: Unbind the binding.</li>
|
<li>26-27: Unbind the binding.</li>
|
||||||
<li>27: Removes the value corresponds to the “bind” key.</li>
|
<li>28: 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
|
||||||
cell editable application.</p>
|
cell editable application.</p>
|
||||||
|
<p>If it is impossible to use <code>g_object_bind_property</code>, use a
|
||||||
|
notify signal on the GtkEntryBuffer instance. You can use “deleted-text”
|
||||||
|
and “inserted-text” signal instead. The handler of the signals above
|
||||||
|
copies the text in the GtkEntryBuffer instance to the LeData string.
|
||||||
|
Connect the notify signal handler in <code>bind2_cb</code> and
|
||||||
|
disconnect it in <code>unbind2_cb</code>.</p>
|
||||||
<h2 id="change-the-cell-of-gtkcolumnview-dynamically">Change the cell of
|
<h2 id="change-the-cell-of-gtkcolumnview-dynamically">Change the cell of
|
||||||
GtkColumnView dynamically</h2>
|
GtkColumnView dynamically</h2>
|
||||||
<p>Next topic is to change the GtkColumnView (or GtkListView) cells
|
<p>Next topic is to change the GtkColumnView (or GtkListView) cells
|
||||||
|
@ -289,164 +282,148 @@ GtkSingleSelection selects a line on the display. The current line
|
||||||
doesn’t need to be on the display. It is possible to be on the line out
|
doesn’t need to be on the display. It is possible to be on the line out
|
||||||
of the Window (GtkScrolledWindow). Actually, the program doesn’t use
|
of the Window (GtkScrolledWindow). Actually, the program doesn’t use
|
||||||
GtkSingleSelection.</p>
|
GtkSingleSelection.</p>
|
||||||
<p>It is necessary to know the corresponding GtkListItem instance from
|
<p>The LeWindow instance has two instance variables for recording the
|
||||||
the item in the list. It is the opposite direction from
|
current line.</p>
|
||||||
<code>gtk_list_item_get_item</code> function. To accomplish this, we set
|
<ul>
|
||||||
a <code>listitem</code> element of LeData to point the corresponding
|
<li><code>win->position</code>: An int type variable. It is the
|
||||||
GtkListItem instance. Therefore, items (LeData) in the list always know
|
position of the current line. It is zero-based. If no current line
|
||||||
the GtkListItem. If there’s no GtkListItem bound to the item, NULL is
|
exists, it is -1.</li>
|
||||||
assigned.</p>
|
<li><code>win->current_button</code>: A variable points the button,
|
||||||
|
located at the first column, on the current line. If no current line
|
||||||
|
exists, it is NULL.</li>
|
||||||
|
</ul>
|
||||||
|
<p>If the current line moves, the following two functions are called.
|
||||||
|
They updates the two varables.</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">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb3-2"><a href="#cb3-2"></a>select_cb <span class="op">(</span>GtkButton <span class="op">*</span>btn<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb3-2"><a href="#cb3-2"></a>update_current_position <span class="op">(</span>LeWindow <span class="op">*</span>win<span class="op">,</span> <span class="dt">int</span> new<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb3-3"><a href="#cb3-3"></a> LeWindow <span class="op">*</span>win <span class="op">=</span> LE_WINDOW <span class="op">(</span>gtk_widget_get_ancestor <span class="op">(</span>GTK_WIDGET <span class="op">(</span>btn<span class="op">),</span> LE_TYPE_WINDOW<span class="op">));</span></span>
|
<span id="cb3-3"><a href="#cb3-3"></a> <span class="dt">char</span> <span class="op">*</span>s<span class="op">;</span></span>
|
||||||
<span id="cb3-4"><a href="#cb3-4"></a></span>
|
<span id="cb3-4"><a href="#cb3-4"></a></span>
|
||||||
<span id="cb3-5"><a href="#cb3-5"></a> update_current <span class="op">(</span>win<span class="op">,</span> gtk_list_item_get_position <span class="op">(</span>listitem<span class="op">));</span></span>
|
<span id="cb3-5"><a href="#cb3-5"></a> win<span class="op">-></span>position <span class="op">=</span> new<span class="op">;</span></span>
|
||||||
<span id="cb3-6"><a href="#cb3-6"></a><span class="op">}</span></span>
|
<span id="cb3-6"><a href="#cb3-6"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">>=</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||||
<span id="cb3-7"><a href="#cb3-7"></a></span>
|
<span id="cb3-7"><a href="#cb3-7"></a> s <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">"%d"</span><span class="op">,</span> win<span class="op">-></span>position<span class="op">);</span></span>
|
||||||
<span id="cb3-8"><a href="#cb3-8"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb3-8"><a href="#cb3-8"></a> <span class="cf">else</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-9"><a href="#cb3-9"></a> s <span class="op">=</span> <span class="st">""</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> gtk_label_set_text <span class="op">(</span>GTK_LABEL <span class="op">(</span>win<span class="op">-></span>position_label<span class="op">),</span> s<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> <span class="cf">if</span> <span class="op">(*</span>s<span class="op">)</span> <span class="co">// s isn't an empty string</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-12"><a href="#cb3-12"></a> g_free <span class="op">(</span>s<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-13"><a href="#cb3-13"></a><span class="op">}</span></span>
|
||||||
<span id="cb3-14"><a href="#cb3-14"></a><span class="op">}</span></span>
|
<span id="cb3-14"><a href="#cb3-14"></a></span>
|
||||||
<span id="cb3-15"><a href="#cb3-15"></a></span>
|
<span id="cb3-15"><a href="#cb3-15"></a><span class="dt">static</span> <span class="dt">void</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-16"><a href="#cb3-16"></a>update_current_button <span class="op">(</span>LeWindow <span class="op">*</span>win<span class="op">,</span> GtkButton <span class="op">*</span>new_button<span class="op">)</span> <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-17"><a href="#cb3-17"></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-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-18"><a href="#cb3-18"></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-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-19"><a href="#cb3-19"></a></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-20"><a href="#cb3-20"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>current_button<span class="op">)</span> <span class="op">{</span></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-21"><a href="#cb3-21"></a> gtk_widget_set_css_classes <span class="op">(</span>GTK_WIDGET <span class="op">(</span>win<span class="op">-></span>current_button<span class="op">),</span> non_current<span class="op">);</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-22"><a href="#cb3-22"></a> g_object_unref <span class="op">(</span>win<span class="op">-></span>current_button<span class="op">);</span></span>
|
||||||
<span id="cb3-23"><a href="#cb3-23"></a></span>
|
<span id="cb3-23"><a href="#cb3-23"></a> <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-24"><a href="#cb3-24"></a> win<span class="op">-></span>current_button <span class="op">=</span> new_button<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-25"><a href="#cb3-25"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>current_button<span class="op">)</span> <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-26"><a href="#cb3-26"></a> g_object_ref <span class="op">(</span>win<span class="op">-></span>current_button<span class="op">);</span></span>
|
||||||
<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-27"><a href="#cb3-27"></a> gtk_widget_set_css_classes <span class="op">(</span>GTK_WIDGET <span class="op">(</span>win<span class="op">-></span>current_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-28"><a href="#cb3-28"></a> <span class="op">}</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-29"><a href="#cb3-29"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<span id="cb3-30"><a href="#cb3-30"></a> <span class="op">}</span></span>
|
<p>The varable <code>win->position_label</code> points a GtkLabel
|
||||||
<span id="cb3-31"><a href="#cb3-31"></a><span class="op">}</span></span>
|
instance. The label shows the current line position.</p>
|
||||||
<span id="cb3-32"><a href="#cb3-32"></a></span>
|
<p>The current button has CSS “current” class. The button is colored red
|
||||||
<span id="cb3-33"><a href="#cb3-33"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
through the CSS “button.current {background: red;}”.</p>
|
||||||
<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>
|
<p>The order of the call for these two functions is important. The first
|
||||||
<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>
|
function, which updates the position, is usually called first. After
|
||||||
<span id="cb3-36"><a href="#cb3-36"></a> <span class="cf">if</span> <span class="op">(</span>data<span class="op">)</span></span>
|
that, a new line is appended or inserted. Then, the second function is
|
||||||
<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>
|
called.</p>
|
||||||
<span id="cb3-38"><a href="#cb3-38"></a><span class="op">}</span></span></code></pre></div>
|
<p>The following functions call the two functions above. Be careful
|
||||||
<ul>
|
about the order of the call.</p>
|
||||||
<li>8-14: <code>setup1_cb</code> is a setup signal handler on the
|
|
||||||
GtkSignalListItemFactory. This factory is inserted to the factory
|
|
||||||
property of the first GtkColumnViewColumn. It sets the child of
|
|
||||||
<code>listitem</code> to a GtkButton instance. The “clicked” signal on
|
|
||||||
the button is connected to the handler <code>select_cb</code>. When the
|
|
||||||
listitem is destroyed, the child (GtkButton) 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.</li>
|
|
||||||
<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
|
|
||||||
GtkApplicationWindow. The handler just calls the
|
|
||||||
<code>update_current</code> function. The function will be explained
|
|
||||||
later.</li>
|
|
||||||
<li>16-31: <code>bind1_cb</code> is a bind signal handler. It sets the
|
|
||||||
“listitem” element of the item (LeData) to point the
|
|
||||||
<code>listitem</code> (GtkListItem instance). It makes the item possible
|
|
||||||
to find the corresponding GtkListItem instance. 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.</li>
|
|
||||||
<li>33-38: <code>unbind1_cb</code> is an unbind signal handler. It
|
|
||||||
removes the <code>listitem</code> instance from the “listitem” element
|
|
||||||
of the item. 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). Otherwise bad
|
|
||||||
things will happen.</li>
|
|
||||||
</ul>
|
|
||||||
<div class="sourceCode" id="cb4"><pre
|
<div class="sourceCode" id="cb4"><pre
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">void</span></span>
|
||||||
<span id="cb4-2"><a href="#cb4-2"></a>update_current <span class="op">(</span>LeWindow <span class="op">*</span>win<span class="op">,</span> <span class="dt">int</span> new<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb4-2"><a href="#cb4-2"></a>select_cb <span class="op">(</span>GtkButton <span class="op">*</span>btn<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb4-3"><a href="#cb4-3"></a> <span class="dt">char</span> <span class="op">*</span>s<span class="op">;</span></span>
|
<span id="cb4-3"><a href="#cb4-3"></a> LeWindow <span class="op">*</span>win <span class="op">=</span> LE_WINDOW <span class="op">(</span>gtk_widget_get_ancestor <span class="op">(</span>GTK_WIDGET <span class="op">(</span>btn<span class="op">),</span> LE_TYPE_WINDOW<span class="op">));</span></span>
|
||||||
<span id="cb4-4"><a href="#cb4-4"></a> LeData <span class="op">*</span>data<span class="op">;</span></span>
|
<span id="cb4-4"><a href="#cb4-4"></a></span>
|
||||||
<span id="cb4-5"><a href="#cb4-5"></a> GtkListItem <span class="op">*</span>listitem<span class="op">;</span></span>
|
<span id="cb4-5"><a href="#cb4-5"></a> update_current_position <span class="op">(</span>win<span class="op">,</span> gtk_list_item_get_position <span class="op">(</span>listitem<span class="op">));</span></span>
|
||||||
<span id="cb4-6"><a href="#cb4-6"></a> GtkButton <span class="op">*</span>button<span class="op">;</span></span>
|
<span id="cb4-6"><a href="#cb4-6"></a> update_current_button <span class="op">(</span>win<span class="op">,</span> btn<span class="op">);</span></span>
|
||||||
<span id="cb4-7"><a href="#cb4-7"></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="cb4-7"><a href="#cb4-7"></a><span class="op">}</span></span>
|
||||||
<span id="cb4-8"><a href="#cb4-8"></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="cb4-8"><a href="#cb4-8"></a></span>
|
||||||
<span id="cb4-9"><a href="#cb4-9"></a></span>
|
<span id="cb4-9"><a href="#cb4-9"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb4-10"><a href="#cb4-10"></a> <span class="cf">if</span> <span class="op">(</span>new <span class="op">>=</span> <span class="dv">0</span><span class="op">)</span></span>
|
<span id="cb4-10"><a href="#cb4-10"></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="cb4-11"><a href="#cb4-11"></a> s <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">"%d"</span><span class="op">,</span> new<span class="op">);</span></span>
|
<span id="cb4-11"><a href="#cb4-11"></a> GtkWidget <span class="op">*</span>button <span class="op">=</span> gtk_button_new <span class="op">();</span></span>
|
||||||
<span id="cb4-12"><a href="#cb4-12"></a> <span class="cf">else</span></span>
|
<span id="cb4-12"><a href="#cb4-12"></a> gtk_list_item_set_child <span class="op">(</span>listitem<span class="op">,</span> button<span class="op">);</span></span>
|
||||||
<span id="cb4-13"><a href="#cb4-13"></a> s <span class="op">=</span> <span class="st">""</span><span class="op">;</span></span>
|
<span id="cb4-13"><a href="#cb4-13"></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="cb4-14"><a href="#cb4-14"></a> gtk_label_set_text <span class="op">(</span>GTK_LABEL <span class="op">(</span>win<span class="op">-></span>position_label<span class="op">),</span> s<span class="op">);</span></span>
|
<span id="cb4-14"><a href="#cb4-14"></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="cb4-15"><a href="#cb4-15"></a> <span class="cf">if</span> <span class="op">(*</span>s<span class="op">)</span> <span class="co">// s isn't an empty string</span></span>
|
<span id="cb4-15"><a href="#cb4-15"></a><span class="op">}</span></span>
|
||||||
<span id="cb4-16"><a href="#cb4-16"></a> g_free <span class="op">(</span>s<span class="op">);</span></span>
|
<span id="cb4-16"><a href="#cb4-16"></a></span>
|
||||||
<span id="cb4-17"><a href="#cb4-17"></a></span>
|
<span id="cb4-17"><a href="#cb4-17"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb4-18"><a href="#cb4-18"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">>=</span><span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb4-18"><a href="#cb4-18"></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="cb4-19"><a href="#cb4-19"></a> data <span class="op">=</span> LE_DATA <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">),</span> win<span class="op">-></span>position<span class="op">));</span></span>
|
<span id="cb4-19"><a href="#cb4-19"></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="cb4-20"><a href="#cb4-20"></a> <span class="cf">if</span> <span class="op">((</span>listitem <span class="op">=</span> le_data_get_listitem <span class="op">(</span>data<span class="op">))</span> <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb4-20"><a href="#cb4-20"></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="cb4-21"><a href="#cb4-21"></a> button <span class="op">=</span> GTK_BUTTON <span class="op">(</span>gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">));</span></span>
|
<span id="cb4-21"><a href="#cb4-21"></a></span>
|
||||||
<span id="cb4-22"><a href="#cb4-22"></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="cb4-22"><a href="#cb4-22"></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="cb4-23"><a href="#cb4-23"></a> g_object_unref <span class="op">(</span>listitem<span class="op">);</span></span>
|
<span id="cb4-23"><a href="#cb4-23"></a> update_current_button <span class="op">(</span>win<span class="op">,</span> GTK_BUTTON <span class="op">(</span>button<span class="op">));</span></span>
|
||||||
<span id="cb4-24"><a href="#cb4-24"></a> <span class="op">}</span></span>
|
<span id="cb4-24"><a href="#cb4-24"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<span id="cb4-25"><a href="#cb4-25"></a> g_object_unref <span class="op">(</span>data<span class="op">);</span></span>
|
|
||||||
<span id="cb4-26"><a href="#cb4-26"></a> <span class="op">}</span></span>
|
|
||||||
<span id="cb4-27"><a href="#cb4-27"></a> win<span class="op">-></span>position <span class="op">=</span> new<span class="op">;</span></span>
|
|
||||||
<span id="cb4-28"><a href="#cb4-28"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">>=</span><span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb4-29"><a href="#cb4-29"></a> data <span class="op">=</span> LE_DATA <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">),</span> win<span class="op">-></span>position<span class="op">));</span></span>
|
|
||||||
<span id="cb4-30"><a href="#cb4-30"></a> <span class="cf">if</span> <span class="op">((</span>listitem <span class="op">=</span> le_data_get_listitem <span class="op">(</span>data<span class="op">))</span> <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb4-31"><a href="#cb4-31"></a> button <span class="op">=</span> GTK_BUTTON <span class="op">(</span>gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">));</span></span>
|
|
||||||
<span id="cb4-32"><a href="#cb4-32"></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="cb4-33"><a href="#cb4-33"></a> g_object_unref <span class="op">(</span>listitem<span class="op">);</span></span>
|
|
||||||
<span id="cb4-34"><a href="#cb4-34"></a> <span class="op">}</span></span>
|
|
||||||
<span id="cb4-35"><a href="#cb4-35"></a> g_object_unref <span class="op">(</span>data<span class="op">);</span></span>
|
|
||||||
<span id="cb4-36"><a href="#cb4-36"></a> <span class="op">}</span></span>
|
|
||||||
<span id="cb4-37"><a href="#cb4-37"></a><span class="op">}</span></span></code></pre></div>
|
|
||||||
<p>The function <code>update_current</code> does several things.</p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>It has two parameters. The first one is <code>win</code>, which is
|
<li>1-7: <code>select_cb</code> is a “clicked” signal handler. The
|
||||||
an instance of LeWindow class. It has some elements.
|
handler just calls the two functions and update the position and
|
||||||
<ul>
|
|
||||||
<li>win->position: an Integer. it is the current position. If no
|
|
||||||
current line exists, it is -1.</li>
|
|
||||||
<li>win->position_label: GtkLabel. It shows the current
|
|
||||||
position.</li>
|
|
||||||
</ul></li>
|
|
||||||
<li>The second parameter is <code>new</code>, which is the new current
|
|
||||||
position. At the beginning of the function, win->position points the
|
|
||||||
old position.</li>
|
|
||||||
<li>10-16: Update the text of GtkLabel.</li>
|
|
||||||
<li>18-26: If the old position (win->position) is not negative, the
|
|
||||||
current line exists. It gets a GtkListItem instance via the item
|
|
||||||
(LeData) of the list. And it gets the GtkButton instance which is the
|
|
||||||
child of the GtkListItem. It clears the “css-classes” property of the
|
|
||||||
button.</li>
|
button.</li>
|
||||||
<li>27: Updates win->position.</li>
|
<li>9-15: <code>setup1_cb</code> is a setup signal handler on the
|
||||||
<li>28-36: If the new position is not negative (It’s possible to be
|
GtkSignalListItemFactory. It sets the child of <code>listitem</code> to
|
||||||
negative when the current line has been removed), the current line
|
a GtkButton instance. The “clicked” signal on the button is connected to
|
||||||
exists. It sets the “css-classes” property of the button to
|
the handler <code>select_cb</code>. When the listitem is destroyed, the
|
||||||
<code>{"current", NULL}</code>. It is a NULL-terminated array of
|
child (GtkButton) is also destroyed. At the same time, the connection of
|
||||||
strings. Each string is a CSS class. Now the button has “current” style
|
the signal and the handler is also destroyed. So, you don’t need
|
||||||
class.</li>
|
teardown signal handler.</li>
|
||||||
|
<li>17-24: <code>bind1_cb</code> is a bind signal handler. Usually, the
|
||||||
|
position moves before this handler is called. If the item is on the
|
||||||
|
current line, the button is updated. No unbind handler is
|
||||||
|
necessary.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>The color of buttons are determined by the “background” CSS style.
|
<p>When a line is added, the current position is updated in advance.</p>
|
||||||
The following CSS is applied to the default GdkDisplay in advance (in
|
|
||||||
the startup handler of the application).</p>
|
|
||||||
<div class="sourceCode" id="cb5"><pre
|
<div class="sourceCode" id="cb5"><pre
|
||||||
class="sourceCode css"><code class="sourceCode css"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>columnview listview row button<span class="fu">.current</span> {<span class="kw">background</span>: <span class="cn">red</span><span class="op">;</span>}</span></code></pre></div>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<p>The selectors “columnview listview row” is needed before “button”
|
<span id="cb5-2"><a href="#cb5-2"></a>app_cb <span class="op">(</span>GtkButton <span class="op">*</span>btn<span class="op">,</span> LeWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||||||
selector. Otherwise the buttons in the GtkColumnview won’t be found. The
|
<span id="cb5-3"><a href="#cb5-3"></a> LeData <span class="op">*</span>data <span class="op">=</span> le_data_new_with_data <span class="op">(</span><span class="st">""</span><span class="op">);</span></span>
|
||||||
button selector has “current” class. So, the only “current” class button
|
<span id="cb5-4"><a href="#cb5-4"></a></span>
|
||||||
is colored with red. Other buttons are not colored, which means they are
|
<span id="cb5-5"><a href="#cb5-5"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">>=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
|
||||||
white.</p>
|
<span id="cb5-6"><a href="#cb5-6"></a> update_current_position <span class="op">(</span>win<span class="op">,</span> win<span class="op">-></span>position <span class="op">+</span> <span class="dv">1</span><span class="op">);</span></span>
|
||||||
<h2
|
<span id="cb5-7"><a href="#cb5-7"></a> g_list_store_insert <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">,</span> win<span class="op">-></span>position<span class="op">,</span> data<span class="op">);</span></span>
|
||||||
id="gtk_widget_dispose_template-function">Gtk_widget_dispose_template
|
<span id="cb5-8"><a href="#cb5-8"></a> <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
|
||||||
function</h2>
|
<span id="cb5-9"><a href="#cb5-9"></a> update_current_position <span class="op">(</span>win<span class="op">,</span> g_list_model_get_n_items <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">)));</span></span>
|
||||||
<p>The function <code>gtk_widget_dispose_template</code> clears the
|
<span id="cb5-10"><a href="#cb5-10"></a> g_list_store_append <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">,</span> data<span class="op">);</span></span>
|
||||||
template children for the given widget. This is the opposite of
|
<span id="cb5-11"><a href="#cb5-11"></a> <span class="op">}</span></span>
|
||||||
<code>gtk_widget_init_template()</code>. It is a new function of GTK 4.8
|
<span id="cb5-12"><a href="#cb5-12"></a> g_object_unref <span class="op">(</span>data<span class="op">);</span></span>
|
||||||
version. If your GTK version is lower than 4.8, you need to modify the
|
<span id="cb5-13"><a href="#cb5-13"></a><span class="op">}</span></span>
|
||||||
program.</p>
|
<span id="cb5-14"><a href="#cb5-14"></a></span>
|
||||||
|
<span id="cb5-15"><a href="#cb5-15"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
|
<span id="cb5-16"><a href="#cb5-16"></a>ins_cb <span class="op">(</span>GtkButton <span class="op">*</span>btn<span class="op">,</span> LeWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||||||
|
<span id="cb5-17"><a href="#cb5-17"></a> LeData <span class="op">*</span>data <span class="op">=</span> le_data_new_with_data <span class="op">(</span><span class="st">""</span><span class="op">);</span></span>
|
||||||
|
<span id="cb5-18"><a href="#cb5-18"></a></span>
|
||||||
|
<span id="cb5-19"><a href="#cb5-19"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">>=</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||||
|
<span id="cb5-20"><a href="#cb5-20"></a> g_list_store_insert <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">,</span> win<span class="op">-></span>position<span class="op">,</span> data<span class="op">);</span></span>
|
||||||
|
<span id="cb5-21"><a href="#cb5-21"></a> <span class="cf">else</span> <span class="op">{</span></span>
|
||||||
|
<span id="cb5-22"><a href="#cb5-22"></a> update_current_position <span class="op">(</span>win<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||||
|
<span id="cb5-23"><a href="#cb5-23"></a> g_list_store_insert <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> data<span class="op">);</span></span>
|
||||||
|
<span id="cb5-24"><a href="#cb5-24"></a> <span class="op">}</span></span>
|
||||||
|
<span id="cb5-25"><a href="#cb5-25"></a> g_object_unref <span class="op">(</span>data<span class="op">);</span></span>
|
||||||
|
<span id="cb5-26"><a href="#cb5-26"></a><span class="op">}</span></span></code></pre></div>
|
||||||
|
<p>When a line is removed, the current position becomes -1 and no button
|
||||||
|
is current.</p>
|
||||||
|
<div class="sourceCode" id="cb6"><pre
|
||||||
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
|
<span id="cb6-2"><a href="#cb6-2"></a>rm_cb <span class="op">(</span>GtkButton <span class="op">*</span>btn<span class="op">,</span> LeWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||||||
|
<span id="cb6-3"><a href="#cb6-3"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">>=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
|
||||||
|
<span id="cb6-4"><a href="#cb6-4"></a> g_list_store_remove <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">,</span> win<span class="op">-></span>position<span class="op">);</span></span>
|
||||||
|
<span id="cb6-5"><a href="#cb6-5"></a> update_current_position <span class="op">(</span>win<span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
||||||
|
<span id="cb6-6"><a href="#cb6-6"></a> update_current_button <span class="op">(</span>win<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||||
|
<span id="cb6-7"><a href="#cb6-7"></a> <span class="op">}</span></span>
|
||||||
|
<span id="cb6-8"><a href="#cb6-8"></a><span class="op">}</span></span></code></pre></div>
|
||||||
|
<p>The color of buttons are determined by the “background” CSS style.
|
||||||
|
The following CSS node is a bit complicated. CSS node
|
||||||
|
<code>column view</code> has <code>listview</code> child node. It covers
|
||||||
|
the rows in the GtkColumnView. The <code>listview</code> node is the
|
||||||
|
same as the one for GtkListView. It has <code>row</code> child node,
|
||||||
|
which is for each child widget. Therefore, the following node
|
||||||
|
corresponds buttons on the GtkColumnView widget. In addition, it is
|
||||||
|
applied to the “current” class.</p>
|
||||||
|
<div class="sourceCode" id="cb7"><pre
|
||||||
|
class="sourceCode css"><code class="sourceCode css"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>columnview listview row button<span class="fu">.current</span> {<span class="kw">background</span>: <span class="cn">red</span><span class="op">;</span>}</span></code></pre></div>
|
||||||
<h2 id="a-waring-from-gtktext">A waring from GtkText</h2>
|
<h2 id="a-waring-from-gtktext">A waring from GtkText</h2>
|
||||||
<p>If your program has the following two, a warning message can be
|
<p>If your program has the following two, a warning message can be
|
||||||
issued.</p>
|
issued.</p>
|
||||||
|
@ -462,24 +439,24 @@ probably comes from focus and scroll.</p>
|
||||||
window. When scroll begins, the “value-changed” signal on the vertical
|
window. When scroll begins, the “value-changed” signal on the vertical
|
||||||
adjustment of the scrolled window is emitted.</p>
|
adjustment of the scrolled window is emitted.</p>
|
||||||
<p>The following is extracted from the ui file and C source file.</p>
|
<p>The following is extracted from the ui file and C source file.</p>
|
||||||
<div class="sourceCode" id="cb7"><pre
|
<div class="sourceCode" id="cb9"><pre
|
||||||
class="sourceCode xml"><code class="sourceCode xml"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>... ... ...</span>
|
class="sourceCode xml"><code class="sourceCode xml"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>... ... ...</span>
|
||||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkScrolledWindow"</span>></span>
|
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkScrolledWindow"</span>></span>
|
||||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
||||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
||||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vadjustment"</span>></span>
|
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vadjustment"</span>></span>
|
||||||
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkAdjustment"</span>></span>
|
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkAdjustment"</span>></span>
|
||||||
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"value-changed"</span><span class="ot"> handler=</span><span class="st">"adjustment_value_changed_cb"</span><span class="ot"> swapped=</span><span class="st">"no"</span><span class="ot"> object=</span><span class="st">"LeWindow"</span>/></span>
|
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"value-changed"</span><span class="ot"> handler=</span><span class="st">"adjustment_value_changed_cb"</span><span class="ot"> swapped=</span><span class="st">"no"</span><span class="ot"> object=</span><span class="st">"LeWindow"</span>/></span>
|
||||||
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
||||||
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
||||||
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>... ... ... </span></code></pre></div>
|
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>... ... ... </span></code></pre></div>
|
||||||
<div class="sourceCode" id="cb8"><pre
|
<div class="sourceCode" id="cb10"><pre
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb8-2"><a href="#cb8-2"></a>adjustment_value_changed_cb <span class="op">(</span>GtkAdjustment <span class="op">*</span>adjustment<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb10-2"><a href="#cb10-2"></a>adjustment_value_changed_cb <span class="op">(</span>GtkAdjustment <span class="op">*</span>adjustment<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb8-3"><a href="#cb8-3"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>user_data<span class="op">);</span></span>
|
<span id="cb10-3"><a href="#cb10-3"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>user_data<span class="op">);</span></span>
|
||||||
<span id="cb8-4"><a href="#cb8-4"></a></span>
|
<span id="cb10-4"><a href="#cb10-4"></a></span>
|
||||||
<span id="cb8-5"><a href="#cb8-5"></a> gtk_window_set_focus <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> NULL<span class="op">);</span></span>
|
<span id="cb10-5"><a href="#cb10-5"></a> gtk_window_set_focus <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||||
<span id="cb8-6"><a href="#cb8-6"></a><span class="op">}</span></span></code></pre></div>
|
<span id="cb10-6"><a href="#cb10-6"></a><span class="op">}</span></span></code></pre></div>
|
||||||
</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>
|
||||||
|
|
486
docs/sec34.html
486
docs/sec34.html
|
@ -1,486 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="generator" content="pandoc" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
|
||||||
<title>GTK 4 tutorial</title>
|
|
||||||
<style>
|
|
||||||
code{white-space: pre-wrap;}
|
|
||||||
span.smallcaps{font-variant: small-caps;}
|
|
||||||
span.underline{text-decoration: underline;}
|
|
||||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
|
||||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
|
||||||
ul.task-list{list-style: none;}
|
|
||||||
pre{overflow: visible;}
|
|
||||||
pre > code.sourceCode { white-space: pre; position: relative; }
|
|
||||||
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
|
||||||
pre > code.sourceCode > span:empty { height: 1.2em; }
|
|
||||||
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
|
||||||
div.sourceCode { margin: 1em 0; }
|
|
||||||
pre.sourceCode { margin: 0; }
|
|
||||||
@media screen {
|
|
||||||
div.sourceCode { overflow: auto; }
|
|
||||||
}
|
|
||||||
@media print {
|
|
||||||
pre > code.sourceCode { white-space: pre-wrap; }
|
|
||||||
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
|
||||||
}
|
|
||||||
pre.numberSource code
|
|
||||||
{ counter-reset: source-line 0; }
|
|
||||||
pre.numberSource code > span
|
|
||||||
{ position: relative; left: -4em; counter-increment: source-line; }
|
|
||||||
pre.numberSource code > span > a:first-child::after
|
|
||||||
{ content: counter(source-line);
|
|
||||||
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
|
||||||
border: none; display: inline-block;
|
|
||||||
-webkit-touch-callout: none; -webkit-user-select: none;
|
|
||||||
-khtml-user-select: none; -moz-user-select: none;
|
|
||||||
-ms-user-select: none; user-select: none;
|
|
||||||
padding: 0 4px; width: 4em;
|
|
||||||
color: #aaaaaa;
|
|
||||||
}
|
|
||||||
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
|
|
||||||
div.sourceCode
|
|
||||||
{ }
|
|
||||||
@media screen {
|
|
||||||
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
|
||||||
}
|
|
||||||
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
|
|
||||||
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
|
||||||
code span.at { color: #7d9029; } /* Attribute */
|
|
||||||
code span.bn { color: #40a070; } /* BaseN */
|
|
||||||
code span.bu { } /* BuiltIn */
|
|
||||||
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
|
|
||||||
code span.ch { color: #4070a0; } /* Char */
|
|
||||||
code span.cn { color: #880000; } /* Constant */
|
|
||||||
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
|
|
||||||
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
|
||||||
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
|
||||||
code span.dt { color: #902000; } /* DataType */
|
|
||||||
code span.dv { color: #40a070; } /* DecVal */
|
|
||||||
code span.er { color: #ff0000; font-weight: bold; } /* Error */
|
|
||||||
code span.ex { } /* Extension */
|
|
||||||
code span.fl { color: #40a070; } /* Float */
|
|
||||||
code span.fu { color: #06287e; } /* Function */
|
|
||||||
code span.im { } /* Import */
|
|
||||||
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
|
||||||
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
|
|
||||||
code span.op { color: #666666; } /* Operator */
|
|
||||||
code span.ot { color: #007020; } /* Other */
|
|
||||||
code span.pp { color: #bc7a00; } /* Preprocessor */
|
|
||||||
code span.sc { color: #4070a0; } /* SpecialChar */
|
|
||||||
code span.ss { color: #bb6688; } /* SpecialString */
|
|
||||||
code span.st { color: #4070a0; } /* String */
|
|
||||||
code span.va { color: #19177c; } /* Variable */
|
|
||||||
code span.vs { color: #4070a0; } /* VerbatimString */
|
|
||||||
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
|
||||||
div.sourceCode { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
|
|
||||||
pre:not(.sourceCode) { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
|
|
||||||
table {margin-left: auto; margin-right: auto; border-collapse: collapse; border: 1px solid;}
|
|
||||||
th {padding: 2px 6px; border: 1px solid; background-color: ghostwhite;}
|
|
||||||
td {padding: 2px 6px; border: 1px solid;}
|
|
||||||
img {display: block; margin-left: auto; margin-right: auto;}
|
|
||||||
figcaption {text-align: center;}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body style="padding-top: 70px;">
|
|
||||||
<div class="container">
|
|
||||||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<span class="navbar-brand">Gtk4 tutorial</span>
|
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
|
||||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">Home</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="sec33.html">Prev: section33</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<h1 id="gtksignallistitemfactory">GtkSignalListItemFactory</h1>
|
|
||||||
<h2
|
|
||||||
id="gtksignallistitemfactory-and-gtkbulderlistitemfactory">GtkSignalListItemFactory
|
|
||||||
and GtkBulderListItemFactory</h2>
|
|
||||||
<p>GtkBuilderlistItemFactory is convenient when GtkListView just shows
|
|
||||||
the contents of a list. Its binding direction is always from an item of
|
|
||||||
a list to a child of GtkListItem.</p>
|
|
||||||
<p>When it comes to dynamic connection, it’s not enough. For example,
|
|
||||||
you want to edit the contents of a list. You set a child of GtkListItem
|
|
||||||
to a GtkText instance so a user can edit a text with it. You need to
|
|
||||||
bind an item in the list with the buffer of the GtkText. The direction
|
|
||||||
is opposite from the one with GtkBuilderListItemFactory. It is from the
|
|
||||||
GtkText instance to the item in the list. You can implement this with
|
|
||||||
GtkSignalListItemFactory, which is more flexible than
|
|
||||||
GtkBuilderListItemFactory.</p>
|
|
||||||
<p>Two things are shown in this section.</p>
|
|
||||||
<ul>
|
|
||||||
<li>Binding from a child of a GtkListItem instance to an item of a
|
|
||||||
list.</li>
|
|
||||||
<li>Access a child of GtkListItem dynamically. This direction is the
|
|
||||||
same as the one with GtkBulderListItemFactory. But
|
|
||||||
GtkBulderListItemFactory uses GtkExpression from the item property of
|
|
||||||
the GtkListItem. So, it updates its child widget only when the item
|
|
||||||
property changes. In this example the child reflects the change in the
|
|
||||||
same item in the list dynamically.</li>
|
|
||||||
</ul>
|
|
||||||
<p>This section shows just a part of the source file
|
|
||||||
<code>listeditor.c</code>. If you want to see the whole codes, see
|
|
||||||
<code>src/listeditor</code> directory of the <a
|
|
||||||
href="https://github.com/ToshioCP/Gtk4-tutorial">Gtk4 tutorial
|
|
||||||
repository</a>.</p>
|
|
||||||
<h2 id="a-list-editor">A list editor</h2>
|
|
||||||
<p>The sample program is a list editor and data of the list are strings.
|
|
||||||
It’s the same as a line editor. It reads a text file line by line. Each
|
|
||||||
line is an item of the list. The list is displayed with GtkColumnView.
|
|
||||||
There are two columns. The one is a button, which makes the line be a
|
|
||||||
current line. If the line is the current line, the button is colored
|
|
||||||
with red. The other is a string which is the contents of the
|
|
||||||
corresponding item of the list.</p>
|
|
||||||
<figure>
|
|
||||||
<img src="image/listeditor.png" alt="List editor" />
|
|
||||||
<figcaption aria-hidden="true">List editor</figcaption>
|
|
||||||
</figure>
|
|
||||||
<p>The source files are located at <code>src/listeditor</code>
|
|
||||||
directory. You can compile end execute it as follows.</p>
|
|
||||||
<ul>
|
|
||||||
<li>Download the program from the <a
|
|
||||||
href="https://github.com/ToshioCP/Gtk4-tutorial">repository</a>.</li>
|
|
||||||
<li>Change your current directory to <code>src/listeditor</code>.</li>
|
|
||||||
<li>Type the following on your commandline.</li>
|
|
||||||
</ul>
|
|
||||||
<pre><code>$ meson _build
|
|
||||||
$ ninja -C _build
|
|
||||||
$ _build/listeditor</code></pre>
|
|
||||||
<ul>
|
|
||||||
<li>Append button: appends a line after the current line, or at the last
|
|
||||||
line if no current line exists.</li>
|
|
||||||
<li>Insert button: inserts a line before the current line.</li>
|
|
||||||
<li>Remove button: removes a current line.</li>
|
|
||||||
<li>Read button: reads a file.</li>
|
|
||||||
<li>Write button: writes the contents to a file.</li>
|
|
||||||
<li>close button: close the contents.</li>
|
|
||||||
<li>quit button: quit the application.</li>
|
|
||||||
<li>Button on the select column: makes the line current.</li>
|
|
||||||
<li>String column: GtkText. You can edit a string in the field.</li>
|
|
||||||
</ul>
|
|
||||||
<p>The current line number (zero-based) is shown at the left of the tool
|
|
||||||
bar. The file name is shown at the right of the write button.</p>
|
|
||||||
<h2 id="connect-a-gtktext-instance-and-an-item-in-the-list">Connect a
|
|
||||||
GtkText instance and an item in the list</h2>
|
|
||||||
<p>The second column (GtkColumnViewColumn) sets its factory property to
|
|
||||||
GtkSignalListItemFactory. It uses three signals setup, bind and unbind.
|
|
||||||
The following is their sgnal handlers.</p>
|
|
||||||
<div class="sourceCode" id="cb2"><pre
|
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">static</span> <span class="dt">void</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-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> 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 class="op">}</span></span>
|
|
||||||
<span id="cb2-7"><a href="#cb2-7"></a></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>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> 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> 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> 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> GBinding <span class="op">*</span>bind<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_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> 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></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> 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="op">}</span></span>
|
|
||||||
<span id="cb2-21"><a href="#cb2-21"></a></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>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> 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></span>
|
|
||||||
<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>
|
|
||||||
<li>1-6: <code>setup2_cb</code> is a setup signal handler on the
|
|
||||||
GtkSignalListItemFactory. This factory is inserted to the factory
|
|
||||||
property of the second GtkColumnViewColumn. The handler just creates a
|
|
||||||
GtkText instance and sets the child of <code>listitem</code> to it. The
|
|
||||||
instance will be destroyed automatically when the <code>listitem</code>
|
|
||||||
is destroyed. So, teardown signal handler isn’t necessary.</li>
|
|
||||||
<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
|
|
||||||
items are LeData instances. LeData is defined in the file
|
|
||||||
<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
|
|
||||||
<code>listitem</code> which points a first column GtkListItem instance
|
|
||||||
when they are connected. Be careful that the GtkListItem instance is
|
|
||||||
<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>
|
|
||||||
<li>10-11: <code>text</code> is a child of the <code>listitem</code> and
|
|
||||||
it is a GtkText instance. And <code>buffer</code> is a GtkTextBuffer
|
|
||||||
instance of the <code>text</code>.</li>
|
|
||||||
<li>12: The LeData instance <code>data</code> is an item pointed by the
|
|
||||||
<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
|
|
||||||
string of the <code>data</code> and the ownership of the string is still
|
|
||||||
taken by the <code>data</code>. So, the caller don’t need to free the
|
|
||||||
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
|
|
||||||
<code>buffer</code> (source) and the “string” property of the
|
|
||||||
<code>data</code> (destination). It is a uni-directional binding
|
|
||||||
(<code>G_BINDING_DEFAULT</code>). When a user changes the GtkText text,
|
|
||||||
the same string is immediately put into the <code>data</code>. The
|
|
||||||
function returns a GBinding instance. This binding is different from
|
|
||||||
bindings of GtkExpression. This binding needs the existence of the two
|
|
||||||
properties.</li>
|
|
||||||
<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
|
|
||||||
<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>
|
|
||||||
instance. It makes possible for the “unbind” handler to get the
|
|
||||||
<code>bind</code> instance.</li>
|
|
||||||
</ul></li>
|
|
||||||
<li>22-28: <code>unbind2_cb</code> is a unbind signal handler.
|
|
||||||
<ul>
|
|
||||||
<li>24: Retrieves the <code>bind</code> instance from the table in the
|
|
||||||
<code>listitem</code> instance.</li>
|
|
||||||
<li>26: Unbind the binding.</li>
|
|
||||||
<li>27: Removes the value corresponds to the “bind” key.</li>
|
|
||||||
</ul></li>
|
|
||||||
</ul>
|
|
||||||
<p>This technique is not so complicated. You can use it when you make a
|
|
||||||
cell editable application.</p>
|
|
||||||
<h2 id="change-the-cell-of-gtkcolumnview-dynamically">Change the cell of
|
|
||||||
GtkColumnView dynamically</h2>
|
|
||||||
<p>Next topic is to change the GtkColumnView (or GtkListView) cells
|
|
||||||
dynamically. The example changes the color of the buttons, which are
|
|
||||||
children of GtkListItem instances, as the current line position
|
|
||||||
moves.</p>
|
|
||||||
<p>The line editor has the current position of the list.</p>
|
|
||||||
<ul>
|
|
||||||
<li>At first, no line is current.</li>
|
|
||||||
<li>When a line is appended or inserted, the line is 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
|
|
||||||
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>
|
|
||||||
<p>The button of the current line is colored with red and otherwise
|
|
||||||
white.</p>
|
|
||||||
<p>The current line has no relationship to GtkSingleSelection object.
|
|
||||||
GtkSingleSelection selects a line on the display. The current line
|
|
||||||
doesn’t need to be on the display. It is possible to be on the line out
|
|
||||||
of the Window (GtkScrolledWindow). Actually, the program doesn’t use
|
|
||||||
GtkSingleSelection.</p>
|
|
||||||
<p>It is necessary to know the corresponding GtkListItem instance from
|
|
||||||
the item in the list. It is the opposite direction from
|
|
||||||
<code>gtk_list_item_get_item</code> function. To accomplish this, we set
|
|
||||||
a <code>listitem</code> element of LeData to point the corresponding
|
|
||||||
GtkListItem instance. Therefore, items (LeData) in the list always know
|
|
||||||
the GtkListItem. If there’s no GtkListItem bound to the item, NULL is
|
|
||||||
assigned.</p>
|
|
||||||
<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>
|
|
||||||
<span id="cb3-2"><a href="#cb3-2"></a>select_cb <span class="op">(</span>GtkButton <span class="op">*</span>btn<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb3-3"><a href="#cb3-3"></a> LeWindow <span class="op">*</span>win <span class="op">=</span> LE_WINDOW <span class="op">(</span>gtk_widget_get_ancestor <span class="op">(</span>GTK_WIDGET <span class="op">(</span>btn<span class="op">),</span> LE_TYPE_WINDOW<span class="op">));</span></span>
|
|
||||||
<span id="cb3-4"><a href="#cb3-4"></a></span>
|
|
||||||
<span id="cb3-5"><a href="#cb3-5"></a> update_current <span class="op">(</span>win<span class="op">,</span> gtk_list_item_get_position <span class="op">(</span>listitem<span class="op">));</span></span>
|
|
||||||
<span id="cb3-6"><a href="#cb3-6"></a><span class="op">}</span></span>
|
|
||||||
<span id="cb3-7"><a href="#cb3-7"></a></span>
|
|
||||||
<span id="cb3-8"><a href="#cb3-8"></a><span class="dt">static</span> <span class="dt">void</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-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> 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> 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 class="op">}</span></span>
|
|
||||||
<span id="cb3-15"><a href="#cb3-15"></a></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>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> 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> 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="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 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> 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></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> 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> <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> 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>
|
|
||||||
<li>8-14: <code>setup1_cb</code> is a setup signal handler on the
|
|
||||||
GtkSignalListItemFactory. This factory is inserted to the factory
|
|
||||||
property of the first GtkColumnViewColumn. It sets the child of
|
|
||||||
<code>listitem</code> to a GtkButton instance. The “clicked” signal on
|
|
||||||
the button is connected to the handler <code>select_cb</code>. When the
|
|
||||||
listitem is destroyed, the child (GtkButton) 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.</li>
|
|
||||||
<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
|
|
||||||
GtkApplicationWindow. The handler just calls the
|
|
||||||
<code>update_current</code> function. The function will be explained
|
|
||||||
later.</li>
|
|
||||||
<li>16-31: <code>bind1_cb</code> is a bind signal handler. It sets the
|
|
||||||
“listitem” element of the item (LeData) to point the
|
|
||||||
<code>listitem</code> (GtkListItem instance). It makes the item possible
|
|
||||||
to find the corresponding GtkListItem instance. 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.</li>
|
|
||||||
<li>33-38: <code>unbind1_cb</code> is an unbind signal handler. It
|
|
||||||
removes the <code>listitem</code> instance from the “listitem” element
|
|
||||||
of the item. 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). Otherwise bad
|
|
||||||
things will happen.</li>
|
|
||||||
</ul>
|
|
||||||
<div class="sourceCode" id="cb4"><pre
|
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
|
||||||
<span id="cb4-2"><a href="#cb4-2"></a>update_current <span class="op">(</span>LeWindow <span class="op">*</span>win<span class="op">,</span> <span class="dt">int</span> new<span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb4-3"><a href="#cb4-3"></a> <span class="dt">char</span> <span class="op">*</span>s<span class="op">;</span></span>
|
|
||||||
<span id="cb4-4"><a href="#cb4-4"></a> LeData <span class="op">*</span>data<span class="op">;</span></span>
|
|
||||||
<span id="cb4-5"><a href="#cb4-5"></a> GtkListItem <span class="op">*</span>listitem<span class="op">;</span></span>
|
|
||||||
<span id="cb4-6"><a href="#cb4-6"></a> GtkButton <span class="op">*</span>button<span class="op">;</span></span>
|
|
||||||
<span id="cb4-7"><a href="#cb4-7"></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="cb4-8"><a href="#cb4-8"></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="cb4-9"><a href="#cb4-9"></a></span>
|
|
||||||
<span id="cb4-10"><a href="#cb4-10"></a> <span class="cf">if</span> <span class="op">(</span>new <span class="op">>=</span> <span class="dv">0</span><span class="op">)</span></span>
|
|
||||||
<span id="cb4-11"><a href="#cb4-11"></a> s <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">"%d"</span><span class="op">,</span> new<span class="op">);</span></span>
|
|
||||||
<span id="cb4-12"><a href="#cb4-12"></a> <span class="cf">else</span></span>
|
|
||||||
<span id="cb4-13"><a href="#cb4-13"></a> s <span class="op">=</span> <span class="st">""</span><span class="op">;</span></span>
|
|
||||||
<span id="cb4-14"><a href="#cb4-14"></a> gtk_label_set_text <span class="op">(</span>GTK_LABEL <span class="op">(</span>win<span class="op">-></span>position_label<span class="op">),</span> s<span class="op">);</span></span>
|
|
||||||
<span id="cb4-15"><a href="#cb4-15"></a> <span class="cf">if</span> <span class="op">(*</span>s<span class="op">)</span> <span class="co">// s isn't an empty string</span></span>
|
|
||||||
<span id="cb4-16"><a href="#cb4-16"></a> g_free <span class="op">(</span>s<span class="op">);</span></span>
|
|
||||||
<span id="cb4-17"><a href="#cb4-17"></a></span>
|
|
||||||
<span id="cb4-18"><a href="#cb4-18"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">>=</span><span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb4-19"><a href="#cb4-19"></a> data <span class="op">=</span> LE_DATA <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">),</span> win<span class="op">-></span>position<span class="op">));</span></span>
|
|
||||||
<span id="cb4-20"><a href="#cb4-20"></a> <span class="cf">if</span> <span class="op">((</span>listitem <span class="op">=</span> le_data_get_listitem <span class="op">(</span>data<span class="op">))</span> <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb4-21"><a href="#cb4-21"></a> button <span class="op">=</span> GTK_BUTTON <span class="op">(</span>gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">));</span></span>
|
|
||||||
<span id="cb4-22"><a href="#cb4-22"></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="cb4-23"><a href="#cb4-23"></a> g_object_unref <span class="op">(</span>listitem<span class="op">);</span></span>
|
|
||||||
<span id="cb4-24"><a href="#cb4-24"></a> <span class="op">}</span></span>
|
|
||||||
<span id="cb4-25"><a href="#cb4-25"></a> g_object_unref <span class="op">(</span>data<span class="op">);</span></span>
|
|
||||||
<span id="cb4-26"><a href="#cb4-26"></a> <span class="op">}</span></span>
|
|
||||||
<span id="cb4-27"><a href="#cb4-27"></a> win<span class="op">-></span>position <span class="op">=</span> new<span class="op">;</span></span>
|
|
||||||
<span id="cb4-28"><a href="#cb4-28"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">>=</span><span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb4-29"><a href="#cb4-29"></a> data <span class="op">=</span> LE_DATA <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>win<span class="op">-></span>liststore<span class="op">),</span> win<span class="op">-></span>position<span class="op">));</span></span>
|
|
||||||
<span id="cb4-30"><a href="#cb4-30"></a> <span class="cf">if</span> <span class="op">((</span>listitem <span class="op">=</span> le_data_get_listitem <span class="op">(</span>data<span class="op">))</span> <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb4-31"><a href="#cb4-31"></a> button <span class="op">=</span> GTK_BUTTON <span class="op">(</span>gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">));</span></span>
|
|
||||||
<span id="cb4-32"><a href="#cb4-32"></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="cb4-33"><a href="#cb4-33"></a> g_object_unref <span class="op">(</span>listitem<span class="op">);</span></span>
|
|
||||||
<span id="cb4-34"><a href="#cb4-34"></a> <span class="op">}</span></span>
|
|
||||||
<span id="cb4-35"><a href="#cb4-35"></a> g_object_unref <span class="op">(</span>data<span class="op">);</span></span>
|
|
||||||
<span id="cb4-36"><a href="#cb4-36"></a> <span class="op">}</span></span>
|
|
||||||
<span id="cb4-37"><a href="#cb4-37"></a><span class="op">}</span></span></code></pre></div>
|
|
||||||
<p>The function <code>update_current</code> does several things.</p>
|
|
||||||
<ul>
|
|
||||||
<li>It has two parameters. The first one is <code>win</code>, which is
|
|
||||||
an instance of LeWindow class. It has some elements.
|
|
||||||
<ul>
|
|
||||||
<li>win->position: an Integer. it is the current position. If no
|
|
||||||
current line exists, it is -1.</li>
|
|
||||||
<li>win->position_label: GtkLabel. It shows the current
|
|
||||||
position.</li>
|
|
||||||
</ul></li>
|
|
||||||
<li>The second parameter is <code>new</code>, which is the new current
|
|
||||||
position. At the beginning of the function, win->position points the
|
|
||||||
old position.</li>
|
|
||||||
<li>10-16: Update the text of GtkLabel.</li>
|
|
||||||
<li>18-26: If the old position (win->position) is not negative, the
|
|
||||||
current line exists. It gets a GtkListItem instance via the item
|
|
||||||
(LeData) of the list. And it gets the GtkButton instance which is the
|
|
||||||
child of the GtkListItem. It clears the “css-classes” property of the
|
|
||||||
button.</li>
|
|
||||||
<li>27: Updates win->position.</li>
|
|
||||||
<li>28-36: If the new position is not negative (It’s possible to be
|
|
||||||
negative when the current line has been removed), the current line
|
|
||||||
exists. It sets the “css-classes” property of the button to
|
|
||||||
<code>{"current", NULL}</code>. It is a NULL-terminated array of
|
|
||||||
strings. Each string is a CSS class. Now the button has “current” style
|
|
||||||
class.</li>
|
|
||||||
</ul>
|
|
||||||
<p>The color of buttons are determined by the “background” CSS style.
|
|
||||||
The following CSS is applied to the default GdkDisplay in advance (in
|
|
||||||
the startup handler of the application).</p>
|
|
||||||
<div class="sourceCode" id="cb5"><pre
|
|
||||||
class="sourceCode css"><code class="sourceCode css"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>columnview listview row button<span class="fu">.current</span> {<span class="kw">background</span>: <span class="cn">red</span><span class="op">;</span>}</span></code></pre></div>
|
|
||||||
<p>The selectors “columnview listview row” is needed before “button”
|
|
||||||
selector. Otherwise the buttons in the GtkColumnview won’t be found. The
|
|
||||||
button selector has “current” class. So, the only “current” class button
|
|
||||||
is colored with red. Other buttons are not colored, which means they are
|
|
||||||
white.</p>
|
|
||||||
<h2
|
|
||||||
id="gtk_widget_dispose_template-function">Gtk_widget_dispose_template
|
|
||||||
function</h2>
|
|
||||||
<p>The function <code>gtk_widget_dispose_template</code> clears the
|
|
||||||
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
|
|
||||||
version. If your GTK version is lower than 4.8, you need to modify the
|
|
||||||
program.</p>
|
|
||||||
<h2 id="a-waring-from-gtktext">A waring from GtkText</h2>
|
|
||||||
<p>If your program has the following two, a warning message can be
|
|
||||||
issued.</p>
|
|
||||||
<ul>
|
|
||||||
<li>The list has many items and it needs to be scrolled.</li>
|
|
||||||
<li>A GtkText instance is the focus widget.</li>
|
|
||||||
</ul>
|
|
||||||
<pre><code>GtkText - unexpected blinking selection. Removing</code></pre>
|
|
||||||
<p>I don’t have an exact idea why this happens. But if GtkText
|
|
||||||
“focusable” property is FALSE, the warning doesn’t happen. So it
|
|
||||||
probably comes from focus and scroll.</p>
|
|
||||||
<p>You can avoid this by unsetting any focus widget under the main
|
|
||||||
window. When scroll begins, the “value-changed” signal on the vertical
|
|
||||||
adjustment of the scrolled window is emitted.</p>
|
|
||||||
<p>The following is extracted from the ui file and C source file.</p>
|
|
||||||
<div class="sourceCode" id="cb7"><pre
|
|
||||||
class="sourceCode xml"><code class="sourceCode xml"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>... ... ...</span>
|
|
||||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkScrolledWindow"</span>></span>
|
|
||||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
|
||||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
|
||||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vadjustment"</span>></span>
|
|
||||||
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkAdjustment"</span>></span>
|
|
||||||
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"value-changed"</span><span class="ot"> handler=</span><span class="st">"adjustment_value_changed_cb"</span><span class="ot"> swapped=</span><span class="st">"no"</span><span class="ot"> object=</span><span class="st">"LeWindow"</span>/></span>
|
|
||||||
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
|
||||||
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
|
||||||
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>... ... ... </span></code></pre></div>
|
|
||||||
<div class="sourceCode" id="cb8"><pre
|
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
|
||||||
<span id="cb8-2"><a href="#cb8-2"></a>adjustment_value_changed_cb <span class="op">(</span>GtkAdjustment <span class="op">*</span>adjustment<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
|
||||||
<span id="cb8-3"><a href="#cb8-3"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>user_data<span class="op">);</span></span>
|
|
||||||
<span id="cb8-4"><a href="#cb8-4"></a></span>
|
|
||||||
<span id="cb8-5"><a href="#cb8-5"></a> gtk_window_set_focus <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> NULL<span class="op">);</span></span>
|
|
||||||
<span id="cb8-6"><a href="#cb8-6"></a><span class="op">}</span></span></code></pre></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>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
18
gfm/sec29.md
18
gfm/sec29.md
|
@ -8,9 +8,10 @@ The new feature is described in [Gtk API Reference -- List Widget Overview](http
|
||||||
GTK 4 has other means to implement lists.
|
GTK 4 has other means to implement lists.
|
||||||
They are GtkListBox and GtkTreeView which are took over from GTK 3.
|
They are GtkListBox and GtkTreeView which are took over from GTK 3.
|
||||||
There's an article in [Gtk Development blog](https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/) about list widgets by Matthias Clasen.
|
There's an article in [Gtk Development blog](https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/) about list widgets by Matthias Clasen.
|
||||||
He described why GtkListView are developed to replace GtkListBox and GtkTreeView.
|
He described why GtkListView are developed to replace GtkTreeView.
|
||||||
|
GtkTreeView is deprecated since version 4.10.
|
||||||
|
|
||||||
GtkListView, GtkGridView, GtkColumnView and related objects are described in Section 26 to 29.
|
GtkListView, GtkGridView, GtkColumnView and related objects are described in Section 29 to 33.
|
||||||
|
|
||||||
## Outline
|
## Outline
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ A list is like an array, but in many cases it is implemented with pointers which
|
||||||
And it has a start point.
|
And it has a start point.
|
||||||
So, each item can be referred by the index of the item (first item, second item, ..., nth item, ...).
|
So, each item can be referred by the index of the item (first item, second item, ..., nth item, ...).
|
||||||
There are two cases.
|
There are two cases.
|
||||||
One is the index starts from one (one-based) and the other is from zero (zero-based).
|
The one is the index starts from one (one-based) and the other is from zero (zero-based).
|
||||||
|
|
||||||
Gio provides GListModel interface.
|
Gio provides GListModel interface.
|
||||||
It is a zero-based list and its items are the same type of GObject descendants, or objects that implement the same interface.
|
It is a zero-based list and its items are the same type of GObject descendants, or objects that implement the same interface.
|
||||||
|
@ -29,11 +30,11 @@ An object implements GListModel is not a widget.
|
||||||
So, the list is not displayed on the screen directly.
|
So, the list is not displayed on the screen directly.
|
||||||
There's another object GtkListView which is a widget to display the list.
|
There's another object GtkListView which is a widget to display the list.
|
||||||
The items in the list need to be connected to the items in GtkListView.
|
The items in the list need to be connected to the items in GtkListView.
|
||||||
GtkListItemFactory instance maps items in the list to GListView.
|
GtkListItemFactory instance maps items in the list to GtkListView.
|
||||||
|
|
||||||
![List](../image/list.png)
|
![List](../image/list.png)
|
||||||
|
|
||||||
## GListModel
|
## GListModel and GtkStringList
|
||||||
|
|
||||||
If you want to make a list of strings with GListModel, for example, "one", "two", "three", "four", note that strings can't be items of the list.
|
If you want to make a list of strings with GListModel, for example, "one", "two", "three", "four", note that strings can't be items of the list.
|
||||||
Because GListModel is a list of GObject objects and strings aren't GObject objects.
|
Because GListModel is a list of GObject objects and strings aren't GObject objects.
|
||||||
|
@ -253,7 +254,7 @@ There is an explanation in the [GTK Development Blog](https://blog.gtk.org/2020/
|
||||||
> Remember that the classname (GtkListItem) in a ui template is used as the “this” pointer referring to the object that is being instantiated.
|
> Remember that the classname (GtkListItem) in a ui template is used as the “this” pointer referring to the object that is being instantiated.
|
||||||
|
|
||||||
Therefore, GtkListItem instance is used as the `this` object of the lookup tag when it is evaluated.
|
Therefore, GtkListItem instance is used as the `this` object of the lookup tag when it is evaluated.
|
||||||
`this` object will be explained in [section 30](../src/sec30).
|
`this` object will be explained in [section 31](../src/sec31).
|
||||||
|
|
||||||
The C source code is as follows.
|
The C source code is as follows.
|
||||||
Its name is `list2.c` and located under [src/misc](../src/misc) directory.
|
Its name is `list2.c` and located under [src/misc](../src/misc) directory.
|
||||||
|
@ -370,7 +371,7 @@ Instead, closure tag is appropriate in this case.
|
||||||
Closure tag specifies a function and the type of the return value of the function.
|
Closure tag specifies a function and the type of the return value of the function.
|
||||||
|
|
||||||
~~~C
|
~~~C
|
||||||
const char *
|
char *
|
||||||
get_file_name (GtkListItem *item, GFileInfo *info) {
|
get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||||
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||||
}
|
}
|
||||||
|
@ -406,7 +407,7 @@ The contents of closure tag (it is between \<closure...\> and\</closure\>) is pa
|
||||||
`<lookup name="item">GtkListItem</lookup>` gives the value of the item property of the GtkListItem.
|
`<lookup name="item">GtkListItem</lookup>` gives the value of the item property of the GtkListItem.
|
||||||
This will be the second argument of the function.
|
This will be the second argument of the function.
|
||||||
The first parameter is always the GListItem instance, which is a 'this' object.
|
The first parameter is always the GListItem instance, which is a 'this' object.
|
||||||
The 'this' object is explained in section 28.
|
The 'this' object is explained in section 31.
|
||||||
- `gtk_file_name` function is the callback function for the closure tag.
|
- `gtk_file_name` function is the callback function for the closure tag.
|
||||||
It first checks the `info` parameter.
|
It first checks the `info` parameter.
|
||||||
Because it can be NULL when GListItem `item` is unbounded.
|
Because it can be NULL when GListItem `item` is unbounded.
|
||||||
|
@ -531,5 +532,4 @@ $ ./a.out
|
||||||
|
|
||||||
![screenshot list3](../image/list3.png)
|
![screenshot list3](../image/list3.png)
|
||||||
|
|
||||||
|
|
||||||
Up: [README.md](../README.md), Prev: [Section 28](sec28.md), Next: [Section 30](sec30.md)
|
Up: [README.md](../README.md), Prev: [Section 28](sec28.md), Next: [Section 30](sec30.md)
|
||||||
|
|
|
@ -64,7 +64,7 @@ Such "x-" subtype is not a standard mime type.)
|
||||||
Content type is also used by desktop systems.
|
Content type is also used by desktop systems.
|
||||||
|
|
||||||
GtkGridView uses the same GtkSingleSelection instance (`singleselection`).
|
GtkGridView uses the same GtkSingleSelection instance (`singleselection`).
|
||||||
So, its model property is set with it.
|
So, its model property is set to it.
|
||||||
|
|
||||||
## Ui file of the window
|
## Ui file of the window
|
||||||
|
|
||||||
|
@ -467,7 +467,7 @@ The last parameter is the pointer to the pointer to a GError.
|
||||||
|
|
||||||
If your distribution supports GTK 4, using `g_app_info_launch_default_for_uri` is convenient.
|
If your distribution supports GTK 4, using `g_app_info_launch_default_for_uri` is convenient.
|
||||||
The function automatically determines the default application from the file and launches it.
|
The function automatically determines the default application from the file and launches it.
|
||||||
For example, if the file is text, then it launches gedit with the file.
|
For example, if the file is text, then it launches GNOME text editor with the file.
|
||||||
Such feature comes from desktop.
|
Such feature comes from desktop.
|
||||||
|
|
||||||
## Compilation and execution
|
## Compilation and execution
|
||||||
|
@ -477,7 +477,7 @@ To compile and execute list4, type as follows.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ cd list4 # or cd src/list4. It depends your current directory.
|
$ cd list4 # or cd src/list4. It depends your current directory.
|
||||||
$ meson _build
|
$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/list4
|
$ _build/list4
|
||||||
~~~
|
~~~
|
||||||
|
|
90
gfm/sec31.md
90
gfm/sec31.md
|
@ -58,8 +58,8 @@ The type of the value is int.
|
||||||
|G\_TYPE\_INT |int |gint | |
|
|G\_TYPE\_INT |int |gint | |
|
||||||
|G\_TYPE\_FLOAT |float |gfloat | |
|
|G\_TYPE\_FLOAT |float |gfloat | |
|
||||||
|G\_TYPE\_DOUBLE |double|gdouble | |
|
|G\_TYPE\_DOUBLE |double|gdouble | |
|
||||||
|G\_TYPE\_POINTER | |gpointer | |
|
|G\_TYPE\_POINTER |void *|gpointer |general pointer |
|
||||||
|G\_TYPE\_STRING | |gchararray|null-terminated Cstring|
|
|G\_TYPE\_STRING |char *|gchararray|null-terminated Cstring|
|
||||||
|G\_TYPE\_OBJECT | |GObject | |
|
|G\_TYPE\_OBJECT | |GObject | |
|
||||||
|GTK\_TYPE\_WINDOW| |GtkWindow | |
|
|GTK\_TYPE\_WINDOW| |GtkWindow | |
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ expression = gtk_property_expression_new (GTK_TYPE_LABEL, another_expression, "l
|
||||||
|
|
||||||
If `expression` is evaluated, the second parameter `another_expression` is evaluated in advance.
|
If `expression` is evaluated, the second parameter `another_expression` is evaluated in advance.
|
||||||
The value of `another_expression` is the `label` (GtkLabel instance).
|
The value of `another_expression` is the `label` (GtkLabel instance).
|
||||||
Then, `expression` looks up "label" property of the label and the evaluation results "Hello".
|
Then, `expression` looks up "label" property of the label and the evaluation results in "Hello".
|
||||||
|
|
||||||
In the example above, the second argument of `gtk_property_expression_new` is another expression.
|
In the example above, the second argument of `gtk_property_expression_new` is another expression.
|
||||||
But the second argument can be NULL.
|
But the second argument can be NULL.
|
||||||
|
@ -145,7 +145,7 @@ There's a simple program `exp_property_simple.c` in `src/expression` directory.
|
||||||
14 if (gtk_expression_evaluate (expression, label, &value))
|
14 if (gtk_expression_evaluate (expression, label, &value))
|
||||||
15 g_print ("The value is %s.\n", g_value_get_string (&value));
|
15 g_print ("The value is %s.\n", g_value_get_string (&value));
|
||||||
16 else
|
16 else
|
||||||
17 g_print ("The constant expression wasn't evaluated correctly.\n");
|
17 g_print ("The property expression wasn't evaluated correctly.\n");
|
||||||
18 gtk_expression_unref (expression);
|
18 gtk_expression_unref (expression);
|
||||||
19 g_value_unset (&value);
|
19 g_value_unset (&value);
|
||||||
20
|
20
|
||||||
|
@ -164,7 +164,7 @@ The expression just knows how to take the property from a future-given GtkLabel
|
||||||
The result is stored in the GValue `value`.
|
The result is stored in the GValue `value`.
|
||||||
The function `g_value_get_string` gets a string from the GValue.
|
The function `g_value_get_string` gets a string from the GValue.
|
||||||
But the string is owned by the GValue so you must not free the string.
|
But the string is owned by the GValue so you must not free the string.
|
||||||
- 18-19: Release the expression and unset the GValue.
|
- 18-19: Releases the expression and unset the GValue.
|
||||||
At the same time the string in the GValue is freed.
|
At the same time the string in the GValue is freed.
|
||||||
|
|
||||||
If the second argument of `gtk_property_expression_new` isn't NULL, it is another expression.
|
If the second argument of `gtk_property_expression_new` isn't NULL, it is another expression.
|
||||||
|
@ -195,6 +195,18 @@ gtk_cclosure_expression_new (GType value_type,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GClosureNotify user_destroy);
|
GClosureNotify user_destroy);
|
||||||
~~~
|
~~~
|
||||||
|
@else
|
||||||
|
~~~{.C}
|
||||||
|
GtkExpression *
|
||||||
|
gtk_cclosure_expression_new (GType value_type,
|
||||||
|
GClosureMarshal marshal,
|
||||||
|
guint n_params,
|
||||||
|
GtkExpression **params,
|
||||||
|
GCallback callback_func,
|
||||||
|
gpointer user_data,
|
||||||
|
GClosureNotify user_destroy);
|
||||||
|
~~~
|
||||||
|
@end
|
||||||
|
|
||||||
- `value_type` is the type of the value when it is evaluated.
|
- `value_type` is the type of the value when it is evaluated.
|
||||||
- `marshal` is a marshaller.
|
- `marshal` is a marshaller.
|
||||||
|
@ -224,6 +236,7 @@ callback (this, param1, param2, ...)
|
||||||
|
|
||||||
For example,
|
For example,
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
int
|
int
|
||||||
callback (GObject *object, int x, const char *s)
|
callback (GObject *object, int x, const char *s)
|
||||||
|
@ -276,13 +289,13 @@ If you want to return error report, change the return value type to be a pointer
|
||||||
One for error and the other for the sum.
|
One for error and the other for the sum.
|
||||||
The first argument of `gtk_cclosure_expression_new` is `G_TYPE_POINTER`.
|
The first argument of `gtk_cclosure_expression_new` is `G_TYPE_POINTER`.
|
||||||
There is a sample program `exp_closure_with_error_report` in `src/expression` directory.
|
There is a sample program `exp_closure_with_error_report` in `src/expression` directory.
|
||||||
- 19: gtk\_init initializes GTK. It is necessary for GtkLabel.
|
- 19: The function `gtk_init`` initializes GTK. It is necessary for GtkLabel.
|
||||||
- 20: A GtkLabel instance is created with "123+456".
|
- 20: A GtkLabel instance is created with "123+456".
|
||||||
- 21: The instance has floating reference. It is changed to an ordinary reference count.
|
- 21: The instance has floating reference. It is changed to an ordinary reference count.
|
||||||
- 22-23: Create a closure expression. Its return value type is `G_TYPE_INT` and no parameters or 'this' object.
|
- 22-23: Creates a closure expression. Its return value type is `G_TYPE_INT` and no parameters or 'this' object.
|
||||||
- 24: Evaluates the expression with the label as a 'this' object.
|
- 24: Evaluates the expression with the label as a 'this' object.
|
||||||
- 25: If the evaluation successes, show the sum of "123+456". It's 579.
|
- 25: If the evaluation successes, the sum of "123+456", which is 579, is shown.
|
||||||
- 27: If it fails, show an error message.
|
- 27: If it fails, an error message appears.
|
||||||
- 28-30: Releases the expression and the label. Unsets the value.
|
- 28-30: Releases the expression and the label. Unsets the value.
|
||||||
|
|
||||||
Closure expression is flexible than other type of expression because you can specify your own callback function.
|
Closure expression is flexible than other type of expression because you can specify your own callback function.
|
||||||
|
@ -292,6 +305,7 @@ Closure expression is flexible than other type of expression because you can spe
|
||||||
GtkExpressionWatch is a structure, not an object.
|
GtkExpressionWatch is a structure, not an object.
|
||||||
It represents a watched GtkExpression.
|
It represents a watched GtkExpression.
|
||||||
Two functions create GtkExpressionWatch structure.
|
Two functions create GtkExpressionWatch structure.
|
||||||
|
They are `gtk_expression_bind` and `gtk_expression_watch`.
|
||||||
|
|
||||||
### gtk\_expression\_bind function
|
### gtk\_expression\_bind function
|
||||||
|
|
||||||
|
@ -411,7 +425,7 @@ For example, if it is zero, the slider moves to an integer point.
|
||||||
28 GtkExpression *expression, *params[1];
|
28 GtkExpression *expression, *params[1];
|
||||||
29
|
29
|
||||||
30 /* Builds a window with exp.ui resource */
|
30 /* Builds a window with exp.ui resource */
|
||||||
31 build = gtk_builder_new_from_file ("exp_bind.ui");
|
31 build = gtk_builder_new_from_resource ("/com/github/ToshioCP/exp/exp_bind.ui");
|
||||||
32 win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
|
32 win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
|
||||||
33 label = GTK_WIDGET (gtk_builder_get_object (build, "label"));
|
33 label = GTK_WIDGET (gtk_builder_get_object (build, "label"));
|
||||||
34 // scale = GTK_WIDGET (gtk_builder_get_object (build, "scale"));
|
34 // scale = GTK_WIDGET (gtk_builder_get_object (build, "scale"));
|
||||||
|
@ -448,7 +462,7 @@ The point of the program is:
|
||||||
|
|
||||||
- 41-42: Two expressions are defined.
|
- 41-42: Two expressions are defined.
|
||||||
One is a property expression and the other is a closure expression.
|
One is a property expression and the other is a closure expression.
|
||||||
The property expression look up the "value"property of the adjustment instance.
|
The property expression looks up the "value" property of the adjustment instance.
|
||||||
The closure expression just converts the double into an integer.
|
The closure expression just converts the double into an integer.
|
||||||
- 43: `gtk_expression_bind` binds the label property of the GtkLabel instance to the integer returned by the closure expression.
|
- 43: `gtk_expression_bind` binds the label property of the GtkLabel instance to the integer returned by the closure expression.
|
||||||
It creates a GtkExpressionWatch structure.
|
It creates a GtkExpressionWatch structure.
|
||||||
|
@ -462,8 +476,8 @@ This signal is emitted when the close button is clicked.
|
||||||
The handler is called just before the window closes.
|
The handler is called just before the window closes.
|
||||||
It is the right moment to make the GtkExpressionWatch unwatched.
|
It is the right moment to make the GtkExpressionWatch unwatched.
|
||||||
- 10-14: "close-request" signal handler.
|
- 10-14: "close-request" signal handler.
|
||||||
`gtk_expression_watch_unwatch (watch)` makes the watch stop watching the expression.
|
The function `gtk_expression_watch_unwatch (watch)` makes the watch stop watching the expression.
|
||||||
It releases the expression and calls `gtk_expression_watch_unref (watch)` in it.
|
It also releases the expression.
|
||||||
|
|
||||||
If you want to bind a property to an expression, `gtk_expression_bind` is the best choice.
|
If you want to bind a property to an expression, `gtk_expression_bind` is the best choice.
|
||||||
You can do it with `gtk_expression_watch` function, but it is less suitable.
|
You can do it with `gtk_expression_watch` function, but it is less suitable.
|
||||||
|
@ -619,7 +633,7 @@ These tags are usually used for GtkBuilderListItemFactory.
|
||||||
<property name="child">
|
<property name="child">
|
||||||
<object class="GtkLabel">
|
<object class="GtkLabel">
|
||||||
<binding name="label">
|
<binding name="label">
|
||||||
<lookup name="name" type="string">
|
<lookup name="string" type="GtkStringObject">
|
||||||
<lookup name="item">GtkListItem</lookup>
|
<lookup name="item">GtkListItem</lookup>
|
||||||
</lookup>
|
</lookup>
|
||||||
</binding>
|
</binding>
|
||||||
|
@ -629,14 +643,13 @@ These tags are usually used for GtkBuilderListItemFactory.
|
||||||
</interface>
|
</interface>
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
GtkBuilderListItemFactory uses GtkBuilder to extends the GtkListItem with the XML data.
|
||||||
|
|
||||||
In the xml file above, "GtkListItem" is an instance of the GtkListItem template.
|
In the xml file above, "GtkListItem" is an instance of the GtkListItem template.
|
||||||
It is the 'this' object given to the expressions.
|
It is the 'this' object given to the expressions.
|
||||||
(The information is in the [GTK Development Blog](https://blog.gtk.org/2020/09/)).
|
(The information is in the [GTK Development Blog](https://blog.gtk.org/2020/09/)).
|
||||||
|
|
||||||
GtkBuilderListItemFactory uses GtkBuilder to build the XML data.
|
GtkBuilder calls `gtk_expression_bind` function when it finds a binding tag.
|
||||||
It sets the current object of the GtkBuilder to the GtkListItem instance.
|
|
||||||
|
|
||||||
GtkBuilder calls `gtk_expression_bind` function in the binding tag analysis.
|
|
||||||
The function sets the 'this' object like this:
|
The function sets the 'this' object like this:
|
||||||
|
|
||||||
1. If the binding tag has object attribute, the object will be the 'this' object.
|
1. If the binding tag has object attribute, the object will be the 'this' object.
|
||||||
|
@ -760,7 +773,7 @@ String duplication is necessary.
|
||||||
|
|
||||||
The C source file is very simple because almost everything is done in the ui file.
|
The C source file is very simple because almost everything is done in the ui file.
|
||||||
|
|
||||||
### Conversion between GValues
|
## Conversion between GValues
|
||||||
|
|
||||||
If you bind different type properties, type conversion is automatically done.
|
If you bind different type properties, type conversion is automatically done.
|
||||||
Suppose a label property (string) is bound to default-width property (int).
|
Suppose a label property (string) is bound to default-width property (int).
|
||||||
|
@ -782,4 +795,43 @@ If the current width is 100, an int `100` is converted to a string `"100"`.
|
||||||
|
|
||||||
If you use `g_object_get` and `g_object_set` to copy properties, the value is automatically converted.
|
If you use `g_object_get` and `g_object_set` to copy properties, the value is automatically converted.
|
||||||
|
|
||||||
|
## Meson.build
|
||||||
|
|
||||||
|
The source files are in `src/expression` directory.
|
||||||
|
You can build all the files at once.
|
||||||
|
|
||||||
|
~~~
|
||||||
|
$ cd src/expression
|
||||||
|
$ meson setup _build
|
||||||
|
$ ninja -C _build
|
||||||
|
~~~
|
||||||
|
|
||||||
|
For example, if you want to run "exp", which is the executable file from "exp.c", type `_build/exp`.
|
||||||
|
You can run other programs as well.
|
||||||
|
|
||||||
|
The file `meson.build` is as follows.
|
||||||
|
|
||||||
|
~~~meson
|
||||||
|
1 project('exp', 'c')
|
||||||
|
2
|
||||||
|
3 gtkdep = dependency('gtk4')
|
||||||
|
4
|
||||||
|
5 gnome=import('gnome')
|
||||||
|
6 resources = gnome.compile_resources('resources','exp.gresource.xml')
|
||||||
|
7
|
||||||
|
8 sourcefiles=files('exp.c')
|
||||||
|
9
|
||||||
|
10 executable('exp', sourcefiles, resources, dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
11 executable('exp_constant', 'exp_constant.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
12 executable('exp_constant_simple', 'exp_constant_simple.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
13 executable('exp_property_simple', 'exp_property_simple.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
14 executable('closure', 'closure.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
15 executable('closure_each', 'closure_each.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
16 executable('exp_closure_simple', 'exp_closure_simple.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
17 executable('exp_closure_with_error_report', 'exp_closure_with_error_report.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
18 executable('exp_bind', 'exp_bind.c', resources, dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
19 executable('exp_watch', 'exp_watch.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
20 executable('exp_test', 'exp_test.c', resources, dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
~~~
|
||||||
|
|
||||||
Up: [README.md](../README.md), Prev: [Section 30](sec30.md), Next: [Section 32](sec32.md)
|
Up: [README.md](../README.md), Prev: [Section 30](sec30.md), Next: [Section 32](sec32.md)
|
||||||
|
|
|
@ -218,9 +218,9 @@ This is the title on the header of the column.
|
||||||
- 32: Sets the "expand" property to TRUE to allow the column to expand as much as possible.
|
- 32: Sets the "expand" property to TRUE to allow the column to expand as much as possible.
|
||||||
(See the image above).
|
(See the image above).
|
||||||
- 33- 69: Sets the "factory" property to GtkBuilderListItemFactory.
|
- 33- 69: Sets the "factory" property to GtkBuilderListItemFactory.
|
||||||
The factory has "bytes" property which holds a ui string to define a template to build GtkListItem composite widget.
|
The factory has "bytes" property which holds a ui string to define a template to extend GtkListItem class.
|
||||||
The CDATA section (line 36-66) is the ui string to put into the "bytes" property.
|
The CDATA section (line 36-66) is the ui string to put into the "bytes" property.
|
||||||
The contents are the same as the ui file `factory_list.ui` in the section 27.
|
The contents are the same as the ui file `factory_list.ui` in the section 30.
|
||||||
- 70-77: Sets the "sorter" property to GtkStringSorter object.
|
- 70-77: Sets the "sorter" property to GtkStringSorter object.
|
||||||
This object provides a sorter that compares strings.
|
This object provides a sorter that compares strings.
|
||||||
It has "expression" property.
|
It has "expression" property.
|
||||||
|
@ -456,7 +456,8 @@ All the source files are in [`src/column`](../src/column) directory.
|
||||||
Change your current directory to the directory and type the following.
|
Change your current directory to the directory and type the following.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ meson _build
|
$ cd src/colomn
|
||||||
|
$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/column
|
$ _build/column
|
||||||
~~~
|
~~~
|
||||||
|
|
307
gfm/sec33.md
307
gfm/sec33.md
|
@ -8,23 +8,14 @@ GtkBuilderlistItemFactory is convenient when GtkListView just shows the contents
|
||||||
Its binding direction is always from an item of a list to a child of GtkListItem.
|
Its binding direction is always from an item of a list to a child of GtkListItem.
|
||||||
|
|
||||||
When it comes to dynamic connection, it's not enough.
|
When it comes to dynamic connection, it's not enough.
|
||||||
For example, you want to edit the contents of a list.
|
For example, suppose you want to edit the contents of a list.
|
||||||
You set a child of GtkListItem to a GtkText instance so a user can edit a text with it.
|
You set a child of GtkListItem to a GtkText instance so a user can edit a text with it.
|
||||||
You need to bind an item in the list with the buffer of the GtkText.
|
You need to bind an item in the list with the buffer of the GtkText.
|
||||||
The direction is opposite from the one with GtkBuilderListItemFactory.
|
The direction is opposite from the one with GtkBuilderListItemFactory.
|
||||||
It is from the GtkText instance to the item in the list.
|
It is from the GtkText instance to the item in the list.
|
||||||
You can implement this with GtkSignalListItemFactory, which is more flexible than GtkBuilderListItemFactory.
|
You can implement this with GtkSignalListItemFactory, which is more flexible than GtkBuilderListItemFactory.
|
||||||
|
|
||||||
Two things are shown in this section.
|
This section shows just some parts of the source file `listeditor.c`.
|
||||||
|
|
||||||
- Binding from a child of a GtkListItem instance to an item of a list.
|
|
||||||
- Access a child of GtkListItem dynamically.
|
|
||||||
This direction is the same as the one with GtkBulderListItemFactory.
|
|
||||||
But GtkBulderListItemFactory uses GtkExpression from the item property of the GtkListItem.
|
|
||||||
So, it updates its child widget only when the item property changes.
|
|
||||||
In this example the child reflects the change in the same item in the list dynamically.
|
|
||||||
|
|
||||||
This section shows just a part of the source file `listeditor.c`.
|
|
||||||
If you want to see the whole codes, see `src/listeditor` directory of the [Gtk4 tutorial repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
If you want to see the whole codes, see `src/listeditor` directory of the [Gtk4 tutorial repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
||||||
|
|
||||||
## A list editor
|
## A list editor
|
||||||
|
@ -35,7 +26,7 @@ It reads a text file line by line.
|
||||||
Each line is an item of the list.
|
Each line is an item of the list.
|
||||||
The list is displayed with GtkColumnView.
|
The list is displayed with GtkColumnView.
|
||||||
There are two columns.
|
There are two columns.
|
||||||
The one is a button, which makes the line be a current line.
|
The one is a button, which shows if the line is a current line.
|
||||||
If the line is the current line, the button is colored with red.
|
If the line is the current line, the button is colored with red.
|
||||||
The other is a string which is the contents of the corresponding item of the list.
|
The other is a string which is the contents of the corresponding item of the list.
|
||||||
|
|
||||||
|
@ -49,18 +40,18 @@ You can compile end execute it as follows.
|
||||||
- Type the following on your commandline.
|
- Type the following on your commandline.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ meson _build
|
$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/listeditor
|
$ _build/listeditor
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- Append button: appends a line after the current line, or at the last line if no current line exists.
|
- Append button: appends a line after the current line, or at the last line if no current line exists.
|
||||||
- Insert button: inserts a line before the current line.
|
- Insert button: inserts a line before the current line, or at the top line if no current line exists.
|
||||||
- Remove button: removes a current line.
|
- Remove button: removes a current line.
|
||||||
- Read button: reads a file.
|
- Read button: reads a file.
|
||||||
- Write button: writes the contents to a file.
|
- Write button: writes the contents to a file.
|
||||||
- close button: close the contents.
|
- close button: closes the contents.
|
||||||
- quit button: quit the application.
|
- quit button: quits the application.
|
||||||
- Button on the select column: makes the line current.
|
- Button on the select column: makes the line current.
|
||||||
- String column: GtkText. You can edit a string in the field.
|
- String column: GtkText. You can edit a string in the field.
|
||||||
|
|
||||||
|
@ -71,7 +62,7 @@ The file name is shown at the right of the write button.
|
||||||
|
|
||||||
The second column (GtkColumnViewColumn) sets its factory property to GtkSignalListItemFactory.
|
The second column (GtkColumnViewColumn) sets its factory property to GtkSignalListItemFactory.
|
||||||
It uses three signals setup, bind and unbind.
|
It uses three signals setup, bind and unbind.
|
||||||
The following is their sgnal handlers.
|
The following shows the signal handlers.
|
||||||
|
|
||||||
~~~C
|
~~~C
|
||||||
1 static void
|
1 static void
|
||||||
|
@ -85,7 +76,7 @@ The following is their sgnal handlers.
|
||||||
9 bind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
9 bind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
10 GtkWidget *text = gtk_list_item_get_child (listitem);
|
10 GtkWidget *text = gtk_list_item_get_child (listitem);
|
||||||
11 GtkEntryBuffer *buffer = gtk_text_get_buffer (GTK_TEXT (text));
|
11 GtkEntryBuffer *buffer = gtk_text_get_buffer (GTK_TEXT (text));
|
||||||
12 LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
12 LeData *data = LE_DATA (gtk_list_item_get_item(listitem));
|
||||||
13 GBinding *bind;
|
13 GBinding *bind;
|
||||||
14
|
14
|
||||||
15 gtk_editable_set_text (GTK_EDITABLE (text), le_data_look_string (data));
|
15 gtk_editable_set_text (GTK_EDITABLE (text), le_data_look_string (data));
|
||||||
|
@ -99,9 +90,10 @@ The following is their sgnal handlers.
|
||||||
23 unbind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
23 unbind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
24 GBinding *bind = G_BINDING (g_object_get_data (G_OBJECT (listitem), "bind"));
|
24 GBinding *bind = G_BINDING (g_object_get_data (G_OBJECT (listitem), "bind"));
|
||||||
25
|
25
|
||||||
26 g_binding_unbind(bind);
|
26 if (bind)
|
||||||
27 g_object_set_data (G_OBJECT (listitem), "bind", NULL);
|
27 g_binding_unbind(bind);
|
||||||
28 }
|
28 g_object_set_data (G_OBJECT (listitem), "bind", NULL);
|
||||||
|
29 }
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- 1-6: `setup2_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
- 1-6: `setup2_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
||||||
|
@ -113,17 +105,13 @@ So, teardown signal handler isn't necessary.
|
||||||
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 string data which is the content of the line.
|
||||||
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.
|
|
||||||
The other is `string` which is a content of the line.
|
|
||||||
- 10-11: `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.
|
||||||
And `buffer` is a GtkTextBuffer instance of the `text`.
|
And `buffer` is a GtkEntryBuffer instance of the `text`.
|
||||||
- 12: The LeData instance `data` is an item pointed by the `listitem`.
|
- 12: The LeData instance `data` is an item pointed by the `listitem`.
|
||||||
- 15-16: Sets the text of `text` 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 still 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 doesn't need to free the string.
|
||||||
- 18: `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`).
|
||||||
|
@ -136,14 +124,19 @@ 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.
|
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.
|
||||||
- 22-28: `unbind2_cb` is a unbind signal handler.
|
- 22-29: `unbind2_cb` is a unbind signal handler.
|
||||||
- 24: Retrieves the `bind` instance from the table in the `listitem` instance.
|
- 24: Retrieves the `bind` instance from the table in the `listitem` instance.
|
||||||
- 26: Unbind the binding.
|
- 26-27: Unbind the binding.
|
||||||
- 27: Removes the value corresponds to the "bind" key.
|
- 28: 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.
|
||||||
|
|
||||||
|
If it is impossible to use `g_object_bind_property`, use a notify signal on the GtkEntryBuffer instance.
|
||||||
|
You can use "deleted-text" and "inserted-text" signal instead.
|
||||||
|
The handler of the signals above copies the text in the GtkEntryBuffer instance to the LeData string.
|
||||||
|
Connect the notify signal handler in `bind2_cb` and disconnect it in `unbind2_cb`.
|
||||||
|
|
||||||
## Change the cell of GtkColumnView dynamically
|
## Change the cell of GtkColumnView dynamically
|
||||||
|
|
||||||
Next topic is to change the GtkColumnView (or GtkListView) cells dynamically.
|
Next topic is to change the GtkColumnView (or GtkListView) cells dynamically.
|
||||||
|
@ -168,159 +161,157 @@ The current line doesn't need to be on the display.
|
||||||
It is possible to be on the line out of the Window (GtkScrolledWindow).
|
It is possible to be on the line out of the Window (GtkScrolledWindow).
|
||||||
Actually, the program doesn't use GtkSingleSelection.
|
Actually, the program doesn't use GtkSingleSelection.
|
||||||
|
|
||||||
It is necessary to know the corresponding GtkListItem instance from the item in the list.
|
The LeWindow instance has two instance variables for recording the current line.
|
||||||
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.
|
- `win->position`: An int type variable. It is the position of the current line. It is zero-based. If no current line exists, it is -1.
|
||||||
Therefore, items (LeData) in the list always know the GtkListItem.
|
- `win->current_button`: A variable points the button, located at the first column, on the current line. If no current line exists, it is NULL.
|
||||||
If there's no GtkListItem bound to the item, NULL is assigned.
|
|
||||||
|
If the current line moves, the following two functions are called.
|
||||||
|
They updates the two varables.
|
||||||
|
|
||||||
|
~~~C
|
||||||
|
1 static void
|
||||||
|
2 update_current_position (LeWindow *win, int new) {
|
||||||
|
3 char *s;
|
||||||
|
4
|
||||||
|
5 win->position = new;
|
||||||
|
6 if (win->position >= 0)
|
||||||
|
7 s = g_strdup_printf ("%d", win->position);
|
||||||
|
8 else
|
||||||
|
9 s = "";
|
||||||
|
10 gtk_label_set_text (GTK_LABEL (win->position_label), s);
|
||||||
|
11 if (*s) // s isn't an empty string
|
||||||
|
12 g_free (s);
|
||||||
|
13 }
|
||||||
|
14
|
||||||
|
15 static void
|
||||||
|
16 update_current_button (LeWindow *win, GtkButton *new_button) {
|
||||||
|
17 const char *non_current[1] = {NULL};
|
||||||
|
18 const char *current[2] = {"current", NULL};
|
||||||
|
19
|
||||||
|
20 if (win->current_button) {
|
||||||
|
21 gtk_widget_set_css_classes (GTK_WIDGET (win->current_button), non_current);
|
||||||
|
22 g_object_unref (win->current_button);
|
||||||
|
23 }
|
||||||
|
24 win->current_button = new_button;
|
||||||
|
25 if (win->current_button) {
|
||||||
|
26 g_object_ref (win->current_button);
|
||||||
|
27 gtk_widget_set_css_classes (GTK_WIDGET (win->current_button), current);
|
||||||
|
28 }
|
||||||
|
29 }
|
||||||
|
~~~
|
||||||
|
|
||||||
|
The varable `win->position_label` points a GtkLabel instance.
|
||||||
|
The label shows the current line position.
|
||||||
|
|
||||||
|
The current button has CSS "current" class.
|
||||||
|
The button is colored red through the CSS "button.current {background: red;}".
|
||||||
|
|
||||||
|
The order of the call for these two functions is important.
|
||||||
|
The first function, which updates the position, is usually called first.
|
||||||
|
After that, a new line is appended or inserted.
|
||||||
|
Then, the second function is called.
|
||||||
|
|
||||||
|
The following functions call the two functions above.
|
||||||
|
Be careful about the order of the call.
|
||||||
|
|
||||||
~~~C
|
~~~C
|
||||||
1 void
|
1 void
|
||||||
2 select_cb (GtkButton *btn, GtkListItem *listitem) {
|
2 select_cb (GtkButton *btn, GtkListItem *listitem) {
|
||||||
3 LeWindow *win = LE_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (btn), LE_TYPE_WINDOW));
|
3 LeWindow *win = LE_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (btn), LE_TYPE_WINDOW));
|
||||||
4
|
4
|
||||||
5 update_current (win, gtk_list_item_get_position (listitem));
|
5 update_current_position (win, gtk_list_item_get_position (listitem));
|
||||||
6 }
|
6 update_current_button (win, btn);
|
||||||
7
|
7 }
|
||||||
8 static void
|
8
|
||||||
9 setup1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
9 static void
|
||||||
10 GtkWidget *button = gtk_button_new ();
|
10 setup1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
11 gtk_list_item_set_child (listitem, button);
|
11 GtkWidget *button = gtk_button_new ();
|
||||||
12 gtk_widget_set_focusable (GTK_WIDGET (button), FALSE);
|
12 gtk_list_item_set_child (listitem, button);
|
||||||
13 g_signal_connect (button, "clicked", G_CALLBACK (select_cb), listitem);
|
13 gtk_widget_set_focusable (GTK_WIDGET (button), FALSE);
|
||||||
14 }
|
14 g_signal_connect (button, "clicked", G_CALLBACK (select_cb), listitem);
|
||||||
15
|
15 }
|
||||||
16 static void
|
16
|
||||||
17 bind1_cb (GtkListItemFactory *factory, GtkListItem *listitem, gpointer user_data) {
|
17 static void
|
||||||
18 LeWindow *win = LE_WINDOW (user_data);
|
18 bind1_cb (GtkListItemFactory *factory, GtkListItem *listitem, gpointer user_data) {
|
||||||
19 GtkWidget *button = gtk_list_item_get_child (listitem);
|
19 LeWindow *win = LE_WINDOW (user_data);
|
||||||
20 const char *non_current[1] = {NULL};
|
20 GtkWidget *button = gtk_list_item_get_child (listitem);
|
||||||
21 const char *current[2] = {"current", NULL};
|
21
|
||||||
22 LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
22 if (win->position == gtk_list_item_get_position (listitem))
|
||||||
23
|
23 update_current_button (win, GTK_BUTTON (button));
|
||||||
24 if (data) {
|
24 }
|
||||||
25 le_data_set_listitem (data, listitem);
|
|
||||||
26 if (win->position == gtk_list_item_get_position (listitem))
|
|
||||||
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-14: `setup1_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
- 1-7: `select_cb` is a "clicked" signal handler.
|
||||||
This factory is inserted to the factory property of the first GtkColumnViewColumn.
|
The handler just calls the two functions and update the position and button.
|
||||||
|
- 9-15: `setup1_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
||||||
It sets the child of `listitem` to a 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 the 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.
|
- 17-24: `bind1_cb` is a bind signal handler.
|
||||||
LeWindow is defined in `listeditor.c`.
|
Usually, the position moves before this handler is called.
|
||||||
It's a child class of GtkApplicationWindow.
|
If the item is on the current line, the button is updated.
|
||||||
The handler just calls the `update_current` function.
|
No unbind handler is necessary.
|
||||||
The function will be explained later.
|
|
||||||
- 16-31: `bind1_cb` is a bind signal handler.
|
When a line is added, the current position is updated in advance.
|
||||||
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.
|
|
||||||
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.
|
|
||||||
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).
|
|
||||||
Otherwise bad things will happen.
|
|
||||||
|
|
||||||
~~~C
|
~~~C
|
||||||
1 static void
|
1 static void
|
||||||
2 update_current (LeWindow *win, int new) {
|
2 app_cb (GtkButton *btn, LeWindow *win) {
|
||||||
3 char *s;
|
3 LeData *data = le_data_new_with_data ("");
|
||||||
4 LeData *data;
|
4
|
||||||
5 GtkListItem *listitem;
|
5 if (win->position >= 0) {
|
||||||
6 GtkButton *button;
|
6 update_current_position (win, win->position + 1);
|
||||||
7 const char *non_current[1] = {NULL};
|
7 g_list_store_insert (win->liststore, win->position, data);
|
||||||
8 const char *current[2] = {"current", NULL};
|
8 } else {
|
||||||
9
|
9 update_current_position (win, g_list_model_get_n_items (G_LIST_MODEL (win->liststore)));
|
||||||
10 if (new >= 0)
|
10 g_list_store_append (win->liststore, data);
|
||||||
11 s = g_strdup_printf ("%d", new);
|
11 }
|
||||||
12 else
|
12 g_object_unref (data);
|
||||||
13 s = "";
|
13 }
|
||||||
14 gtk_label_set_text (GTK_LABEL (win->position_label), s);
|
14
|
||||||
15 if (*s) // s isn't an empty string
|
15 static void
|
||||||
16 g_free (s);
|
16 ins_cb (GtkButton *btn, LeWindow *win) {
|
||||||
17
|
17 LeData *data = le_data_new_with_data ("");
|
||||||
18 if (win->position >=0) {
|
18
|
||||||
19 data = LE_DATA (g_list_model_get_item (G_LIST_MODEL (win->liststore), win->position));
|
19 if (win->position >= 0)
|
||||||
20 if ((listitem = le_data_get_listitem (data)) != NULL) {
|
20 g_list_store_insert (win->liststore, win->position, data);
|
||||||
21 button = GTK_BUTTON (gtk_list_item_get_child (listitem));
|
21 else {
|
||||||
22 gtk_widget_set_css_classes (GTK_WIDGET (button), non_current);
|
22 update_current_position (win, 0);
|
||||||
23 g_object_unref (listitem);
|
23 g_list_store_insert (win->liststore, 0, data);
|
||||||
24 }
|
24 }
|
||||||
25 g_object_unref (data);
|
25 g_object_unref (data);
|
||||||
26 }
|
26 }
|
||||||
27 win->position = new;
|
|
||||||
28 if (win->position >=0) {
|
|
||||||
29 data = LE_DATA (g_list_model_get_item (G_LIST_MODEL (win->liststore), win->position));
|
|
||||||
30 if ((listitem = le_data_get_listitem (data)) != NULL) {
|
|
||||||
31 button = GTK_BUTTON (gtk_list_item_get_child (listitem));
|
|
||||||
32 gtk_widget_set_css_classes (GTK_WIDGET (button), current);
|
|
||||||
33 g_object_unref (listitem);
|
|
||||||
34 }
|
|
||||||
35 g_object_unref (data);
|
|
||||||
36 }
|
|
||||||
37 }
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
The function `update_current` does several things.
|
When a line is removed, the current position becomes -1 and no button is current.
|
||||||
|
|
||||||
- It has two parameters.
|
~~~C
|
||||||
The first one is `win`, which is an instance of LeWindow class.
|
1 static void
|
||||||
It has some elements.
|
2 rm_cb (GtkButton *btn, LeWindow *win) {
|
||||||
- win->position: an Integer. it is the current position. If no current line exists, it is -1.
|
3 if (win->position >= 0) {
|
||||||
- win->position_label: GtkLabel. It shows the current position.
|
4 g_list_store_remove (win->liststore, win->position);
|
||||||
- The second parameter is `new`, which is the new current position.
|
5 update_current_position (win, -1);
|
||||||
At the beginning of the function, win->position points the old position.
|
6 update_current_button (win, NULL);
|
||||||
- 10-16: Update the text of GtkLabel.
|
7 }
|
||||||
- 18-26: If the old position (win->position) is not negative, the current line exists.
|
8 }
|
||||||
It gets a GtkListItem instance via the item (LeData) of the list.
|
~~~
|
||||||
And it gets the GtkButton instance which is the child of the GtkListItem.
|
|
||||||
It clears the "css-classes" property of the button.
|
|
||||||
- 27: Updates win->position.
|
|
||||||
- 28-36: If the new position is not negative (It's possible to be negative when the current line has been removed), the current line exists.
|
|
||||||
It sets the "css-classes" property of the button to `{"current", NULL}`.
|
|
||||||
It is a NULL-terminated array of strings.
|
|
||||||
Each string is a CSS class.
|
|
||||||
Now the button has "current" style class.
|
|
||||||
|
|
||||||
The color of buttons are determined by the "background" CSS style.
|
The color of buttons are determined by the "background" CSS style.
|
||||||
The following CSS is applied to the default GdkDisplay in advance (in the startup handler of the application).
|
The following CSS node is a bit complicated.
|
||||||
|
CSS node `column view` has `listview` child node.
|
||||||
|
It covers the rows in the GtkColumnView.
|
||||||
|
The `listview` node is the same as the one for GtkListView.
|
||||||
|
It has `row` child node, which is for each child widget.
|
||||||
|
Therefore, the following node corresponds buttons on the GtkColumnView widget.
|
||||||
|
In addition, it is applied to the "current" class.
|
||||||
|
|
||||||
~~~css
|
~~~css
|
||||||
columnview listview row button.current {background: red;}
|
columnview listview row button.current {background: red;}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
The selectors "columnview listview row" is needed before "button" selector.
|
|
||||||
Otherwise the buttons in the GtkColumnview won't be found.
|
|
||||||
The button selector has "current" class.
|
|
||||||
So, the only "current" class button is colored with red.
|
|
||||||
Other buttons are not colored, which means they are white.
|
|
||||||
|
|
||||||
## Gtk\_widget\_dispose\_template function
|
|
||||||
|
|
||||||
The function `gtk_widget_dispose_template` clears the template children for the given widget.
|
|
||||||
This is the opposite of `gtk_widget_init_template()`.
|
|
||||||
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.
|
|
||||||
|
|
||||||
## A waring from GtkText
|
## A waring from GtkText
|
||||||
|
|
||||||
If your program has the following two, a warning message can be issued.
|
If your program has the following two, a warning message can be issued.
|
||||||
|
|
|
@ -6,7 +6,8 @@ The table of contents is at the end of this abstract.
|
||||||
|
|
||||||
- Section 3 to 23 describes the basics, with the example of a simple editor `tfe` (Text File Editor).
|
- Section 3 to 23 describes the basics, with the example of a simple editor `tfe` (Text File Editor).
|
||||||
- Section 24 to 27 describes GtkDrawingArea.
|
- Section 24 to 27 describes GtkDrawingArea.
|
||||||
- Section 28 to 32 describes the list model and the list view (GtkListView, GtkGridView and GtkColumnView).
|
- Section 28 describes Drag and Drop.
|
||||||
|
- Section 29 to 33 describes the list model and the list view (GtkListView, GtkGridView and GtkColumnView).
|
||||||
It also describes GtkExpression.
|
It also describes GtkExpression.
|
||||||
|
|
||||||
The latest version of the tutorial is located at [GTK4-tutorial GitHub repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
The latest version of the tutorial is located at [GTK4-tutorial GitHub repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
||||||
|
|
|
@ -2,5 +2,7 @@
|
||||||
<gresources>
|
<gresources>
|
||||||
<gresource prefix="/com/github/ToshioCP/exp">
|
<gresource prefix="/com/github/ToshioCP/exp">
|
||||||
<file>exp.ui</file>
|
<file>exp.ui</file>
|
||||||
|
<file>exp_bind.ui</file>
|
||||||
|
<file>exp_test.ui</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
|
|
@ -28,7 +28,7 @@ app_startup (GApplication *application) {
|
||||||
GtkExpression *expression, *params[1];
|
GtkExpression *expression, *params[1];
|
||||||
|
|
||||||
/* Builds a window with exp.ui resource */
|
/* Builds a window with exp.ui resource */
|
||||||
build = gtk_builder_new_from_file ("exp_bind.ui");
|
build = gtk_builder_new_from_resource ("/com/github/ToshioCP/exp/exp_bind.ui");
|
||||||
win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
|
win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
|
||||||
label = GTK_WIDGET (gtk_builder_get_object (build, "label"));
|
label = GTK_WIDGET (gtk_builder_get_object (build, "label"));
|
||||||
// scale = GTK_WIDGET (gtk_builder_get_object (build, "scale"));
|
// scale = GTK_WIDGET (gtk_builder_get_object (build, "scale"));
|
||||||
|
|
|
@ -14,7 +14,7 @@ main (int argc, char **argv) {
|
||||||
if (gtk_expression_evaluate (expression, label, &value))
|
if (gtk_expression_evaluate (expression, label, &value))
|
||||||
g_print ("The value is %s.\n", g_value_get_string (&value));
|
g_print ("The value is %s.\n", g_value_get_string (&value));
|
||||||
else
|
else
|
||||||
g_print ("The constant expression wasn't evaluated correctly.\n");
|
g_print ("The property expression wasn't evaluated correctly.\n");
|
||||||
gtk_expression_unref (expression);
|
gtk_expression_unref (expression);
|
||||||
g_value_unset (&value);
|
g_value_unset (&value);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ app_startup (GApplication *application) {
|
||||||
GtkBuilder *build;
|
GtkBuilder *build;
|
||||||
GtkWidget *win;
|
GtkWidget *win;
|
||||||
|
|
||||||
build = gtk_builder_new_from_file ("exp_test.ui");
|
build = gtk_builder_new_from_resource ("/com/github/ToshioCP/exp/exp_test.ui");
|
||||||
win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
|
win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
|
||||||
gtk_window_set_application (GTK_WINDOW (win), app);
|
gtk_window_set_application (GTK_WINDOW (win), app);
|
||||||
g_object_unref (build);
|
g_object_unref (build);
|
||||||
|
|
|
@ -15,6 +15,6 @@ executable('closure', 'closure.c', dependencies: gtkdep, export_dynamic: true, i
|
||||||
executable('closure_each', 'closure_each.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
executable('closure_each', 'closure_each.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
executable('exp_closure_simple', 'exp_closure_simple.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
executable('exp_closure_simple', 'exp_closure_simple.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
executable('exp_closure_with_error_report', 'exp_closure_with_error_report.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
executable('exp_closure_with_error_report', 'exp_closure_with_error_report.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
executable('exp_bind', 'exp_bind.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
executable('exp_bind', 'exp_bind.c', resources, dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
executable('exp_watch', 'exp_watch.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
executable('exp_watch', 'exp_watch.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
executable('exp_test', 'exp_test.c', dependencies: gtkdep, export_dynamic: true, install: false)
|
executable('exp_test', 'exp_test.c', resources, dependencies: gtkdep, export_dynamic: true, install: false)
|
||||||
|
|
|
@ -13,7 +13,6 @@ static GParamSpec *ledata_properties[N_PROPERTIES] = {NULL, };
|
||||||
|
|
||||||
typedef struct _LeData {
|
typedef struct _LeData {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
GtkListItem *listitem;
|
|
||||||
char *string;
|
char *string;
|
||||||
} LeData;
|
} LeData;
|
||||||
|
|
||||||
|
@ -41,19 +40,9 @@ le_data_get_property (GObject *object, guint property_id, GValue *value, GParamS
|
||||||
|
|
||||||
static void
|
static void
|
||||||
le_data_init (LeData *self) {
|
le_data_init (LeData *self) {
|
||||||
self->listitem = NULL;
|
|
||||||
self->string = NULL;
|
self->string = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
le_data_dispose (GObject *object) {
|
|
||||||
LeData *self = LE_DATA (object);
|
|
||||||
|
|
||||||
if (self->listitem)
|
|
||||||
g_clear_object (&self->listitem);
|
|
||||||
G_OBJECT_CLASS (le_data_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
le_data_finalize (GObject *object) {
|
le_data_finalize (GObject *object) {
|
||||||
LeData *self = LE_DATA (object);
|
LeData *self = LE_DATA (object);
|
||||||
|
@ -67,7 +56,6 @@ static void
|
||||||
le_data_class_init (LeDataClass *class) {
|
le_data_class_init (LeDataClass *class) {
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
|
||||||
gobject_class->finalize = le_data_dispose;
|
|
||||||
gobject_class->finalize = le_data_finalize;
|
gobject_class->finalize = le_data_finalize;
|
||||||
gobject_class->set_property = le_data_set_property;
|
gobject_class->set_property = le_data_set_property;
|
||||||
gobject_class->get_property = le_data_get_property;
|
gobject_class->get_property = le_data_get_property;
|
||||||
|
@ -75,14 +63,16 @@ le_data_class_init (LeDataClass *class) {
|
||||||
g_object_class_install_properties (gobject_class,N_PROPERTIES, ledata_properties);
|
g_object_class_install_properties (gobject_class,N_PROPERTIES, ledata_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setter and getter */
|
/* getter and setter */
|
||||||
void
|
|
||||||
le_data_set_listitem (LeData *self, GtkListItem *listitem) {
|
|
||||||
g_return_if_fail (GTK_IS_LIST_ITEM (listitem) || listitem == NULL);
|
|
||||||
|
|
||||||
if (self->listitem)
|
char *
|
||||||
g_object_unref (self->listitem);
|
le_data_get_string (LeData *self) {
|
||||||
self->listitem = listitem ? g_object_ref (listitem) : NULL;
|
return g_strdup (self->string);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
le_data_look_string (LeData *self) {
|
||||||
|
return self->string;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -99,35 +89,9 @@ le_data_take_string (LeData *self, char *string) {
|
||||||
self->string = string;
|
self->string = string;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkListItem *
|
|
||||||
le_data_get_listitem (LeData *self) {
|
|
||||||
return self->listitem ? g_object_ref (self->listitem) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkListItem *
|
|
||||||
le_data_look_listitem (LeData *self) {
|
|
||||||
return self->listitem ? self->listitem : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
le_data_get_string (LeData *self) {
|
|
||||||
return g_strdup (self->string);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
le_data_look_string (LeData *self) {
|
|
||||||
return self->string;
|
|
||||||
}
|
|
||||||
|
|
||||||
LeData *
|
LeData *
|
||||||
le_data_new_with_data (GtkListItem *listitem, const char *string) {
|
le_data_new_with_data (const char *string) {
|
||||||
g_return_val_if_fail (GTK_IS_LIST_ITEM (listitem) || listitem == NULL, NULL);
|
return LE_DATA (g_object_new (LE_TYPE_DATA, "string", string, NULL));
|
||||||
LeData *data;
|
|
||||||
|
|
||||||
data = LE_DATA (g_object_new (LE_TYPE_DATA, NULL));
|
|
||||||
data->listitem = listitem ? g_object_ref (listitem) : NULL;
|
|
||||||
data->string = g_strdup (string);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LeData *
|
LeData *
|
||||||
|
@ -141,151 +105,149 @@ G_DECLARE_FINAL_TYPE (LeWindow, le_window, LE, WINDOW, GtkApplicationWindow)
|
||||||
typedef struct _LeWindow {
|
typedef struct _LeWindow {
|
||||||
GtkApplicationWindow parent;
|
GtkApplicationWindow parent;
|
||||||
int position; /* current position */
|
int position; /* current position */
|
||||||
|
GtkButton *current_button;
|
||||||
GFile *file;
|
GFile *file;
|
||||||
GtkWidget *position_label;
|
GtkWidget *position_label;
|
||||||
GtkWidget *filename;
|
GtkWidget *filename;
|
||||||
GtkWidget *columnview;
|
GtkWidget *columnview;
|
||||||
|
GtkNoSelection *noselection;
|
||||||
GListStore *liststore;
|
GListStore *liststore;
|
||||||
} LeWindow;
|
} LeWindow;
|
||||||
G_DEFINE_TYPE (LeWindow, le_window, GTK_TYPE_APPLICATION_WINDOW)
|
G_DEFINE_FINAL_TYPE (LeWindow, le_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_current (LeWindow *win, int new) {
|
update_current_position (LeWindow *win, int new) {
|
||||||
char *s;
|
char *s;
|
||||||
LeData *data;
|
|
||||||
GtkListItem *listitem;
|
|
||||||
GtkButton *button;
|
|
||||||
const char *non_current[1] = {NULL};
|
|
||||||
const char *current[2] = {"current", NULL};
|
|
||||||
|
|
||||||
if (new >= 0)
|
win->position = new;
|
||||||
s = g_strdup_printf ("%d", new);
|
if (win->position >= 0)
|
||||||
|
s = g_strdup_printf ("%d", win->position);
|
||||||
else
|
else
|
||||||
s = "";
|
s = "";
|
||||||
gtk_label_set_text (GTK_LABEL (win->position_label), s);
|
gtk_label_set_text (GTK_LABEL (win->position_label), s);
|
||||||
if (*s) // s isn't an empty string
|
if (*s) // s isn't an empty string
|
||||||
g_free (s);
|
g_free (s);
|
||||||
|
}
|
||||||
|
|
||||||
if (win->position >=0) {
|
static void
|
||||||
data = LE_DATA (g_list_model_get_item (G_LIST_MODEL (win->liststore), win->position));
|
update_current_button (LeWindow *win, GtkButton *new_button) {
|
||||||
if ((listitem = le_data_get_listitem (data)) != NULL) {
|
const char *non_current[1] = {NULL};
|
||||||
button = GTK_BUTTON (gtk_list_item_get_child (listitem));
|
const char *current[2] = {"current", NULL};
|
||||||
gtk_widget_set_css_classes (GTK_WIDGET (button), non_current);
|
|
||||||
g_object_unref (listitem);
|
if (win->current_button) {
|
||||||
}
|
gtk_widget_set_css_classes (GTK_WIDGET (win->current_button), non_current);
|
||||||
g_object_unref (data);
|
g_object_unref (win->current_button);
|
||||||
}
|
}
|
||||||
win->position = new;
|
win->current_button = new_button;
|
||||||
if (win->position >=0) {
|
if (win->current_button) {
|
||||||
data = LE_DATA (g_list_model_get_item (G_LIST_MODEL (win->liststore), win->position));
|
g_object_ref (win->current_button);
|
||||||
if ((listitem = le_data_get_listitem (data)) != NULL) {
|
gtk_widget_set_css_classes (GTK_WIDGET (win->current_button), current);
|
||||||
button = GTK_BUTTON (gtk_list_item_get_child (listitem));
|
|
||||||
gtk_widget_set_css_classes (GTK_WIDGET (button), current);
|
|
||||||
g_object_unref (listitem);
|
|
||||||
}
|
|
||||||
g_object_unref (data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----- Button "clicled" signal handlers ----- */
|
/* ----- Button "clicled" signal handlers ----- */
|
||||||
static void
|
static void
|
||||||
app_cb (GtkButton *btn, LeWindow *win) {
|
app_cb (GtkButton *btn, LeWindow *win) {
|
||||||
LeData *data;
|
LeData *data = le_data_new_with_data ("");
|
||||||
|
|
||||||
data = le_data_new_with_data (NULL, "");
|
|
||||||
if (win->position >= 0) {
|
if (win->position >= 0) {
|
||||||
g_list_store_insert (win->liststore, win->position + 1, data);
|
update_current_position (win, win->position + 1);
|
||||||
update_current (win, win->position + 1);
|
g_list_store_insert (win->liststore, win->position, data);
|
||||||
} else {
|
} else {
|
||||||
|
update_current_position (win, g_list_model_get_n_items (G_LIST_MODEL (win->liststore)));
|
||||||
g_list_store_append (win->liststore, data);
|
g_list_store_append (win->liststore, data);
|
||||||
update_current (win, g_list_model_get_n_items (G_LIST_MODEL (win->liststore)) - 1);
|
|
||||||
}
|
}
|
||||||
g_object_unref (data);
|
g_object_unref (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ins_cb (GtkButton *btn, LeWindow *win) {
|
ins_cb (GtkButton *btn, LeWindow *win) {
|
||||||
LeData *data;
|
LeData *data = le_data_new_with_data ("");
|
||||||
|
|
||||||
data = le_data_new_with_data (NULL, "");
|
if (win->position >= 0)
|
||||||
if (win->position >= 0) {
|
|
||||||
g_list_store_insert (win->liststore, win->position, data);
|
g_list_store_insert (win->liststore, win->position, data);
|
||||||
win->position += 1;
|
else {
|
||||||
update_current (win, win->position - 1);
|
update_current_position (win, 0);
|
||||||
|
g_list_store_insert (win->liststore, 0, data);
|
||||||
}
|
}
|
||||||
g_object_unref (data);
|
g_object_unref (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rm_cb (GtkButton *btn, LeWindow *win) {
|
rm_cb (GtkButton *btn, LeWindow *win) {
|
||||||
int position;
|
|
||||||
|
|
||||||
if (win->position >= 0) {
|
if (win->position >= 0) {
|
||||||
position = win->position;
|
g_list_store_remove (win->liststore, win->position);
|
||||||
win->position = -1;
|
update_current_position (win, -1);
|
||||||
g_list_store_remove (win->liststore, position);
|
update_current_button (win, NULL);
|
||||||
update_current (win, -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
open_dialog_response(GtkWidget *dialog, gint response, LeWindow *win) {
|
open_dialog_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) {
|
||||||
|
GtkFileDialog *dialog = GTK_FILE_DIALOG (source_object);
|
||||||
|
LeWindow *win = LE_WINDOW (user_data);
|
||||||
GFile *file;
|
GFile *file;
|
||||||
char *contents;
|
char *contents;
|
||||||
|
GListStore *liststore;
|
||||||
|
GListStore *liststore_old;
|
||||||
|
LeData *data;
|
||||||
char *s;
|
char *s;
|
||||||
gsize length;
|
|
||||||
GFileInputStream *stream;
|
GFileInputStream *stream;
|
||||||
GDataInputStream *dstream;
|
GDataInputStream *dstream;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
LeData *data;
|
|
||||||
|
|
||||||
if (response == GTK_RESPONSE_ACCEPT
|
if ((file = gtk_file_dialog_open_finish (dialog, res, &err)) == NULL) {
|
||||||
&& G_IS_FILE (file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)))
|
g_warning ("%s\n", err->message);
|
||||||
&& g_file_load_contents (file, NULL, &contents, &length, NULL, &err)) {
|
g_error_free (err);
|
||||||
if (! (stream = g_file_read (file, NULL, &err))) {
|
return;
|
||||||
g_warning ("%s\n", err->message);
|
|
||||||
g_error_free (err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dstream = g_data_input_stream_new (G_INPUT_STREAM (stream));
|
|
||||||
g_object_unref (stream);
|
|
||||||
while ((contents = g_data_input_stream_read_line_utf8 (dstream, &length, NULL, &err)) != NULL) {
|
|
||||||
data = le_data_new_with_data (NULL, contents);
|
|
||||||
g_free (contents);
|
|
||||||
g_list_store_append (win->liststore, data);
|
|
||||||
g_object_unref (data);
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
g_warning ("%s\n", err->message);
|
|
||||||
if (g_list_model_get_n_items(G_LIST_MODEL (win->liststore)) > 0)
|
|
||||||
g_list_store_remove_all (win->liststore);
|
|
||||||
return;
|
|
||||||
} else if (! g_input_stream_close (G_INPUT_STREAM (dstream), NULL, &err)) { /* EOF */
|
|
||||||
g_warning ("%s\n", err->message);
|
|
||||||
g_error_free (err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
win->file = file; /* win->file is NULL (has already checked) and it take the ownership of 'file' */
|
|
||||||
s = g_file_get_basename (file);
|
|
||||||
gtk_label_set_text (GTK_LABEL (win->filename), s);
|
|
||||||
g_free (s);
|
|
||||||
update_current (win, -1);
|
|
||||||
}
|
}
|
||||||
gtk_window_destroy (GTK_WINDOW (dialog));
|
if ((stream = g_file_read (file, NULL, &err)) == NULL) {
|
||||||
|
g_warning ("%s\n", err->message);
|
||||||
|
g_error_free (err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dstream = g_data_input_stream_new (G_INPUT_STREAM (stream));
|
||||||
|
g_object_unref (stream);
|
||||||
|
liststore = g_list_store_new (LE_TYPE_DATA);
|
||||||
|
while ((contents = g_data_input_stream_read_line_utf8 (dstream, NULL, NULL, &err)) != NULL) {
|
||||||
|
data = le_data_new_with_data (contents);
|
||||||
|
g_list_store_append (liststore, data);
|
||||||
|
g_free (contents);
|
||||||
|
g_object_unref (data);
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
g_warning ("%s\n", err->message);
|
||||||
|
g_error_free (err);
|
||||||
|
g_object_unref (liststore);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (! g_input_stream_close (G_INPUT_STREAM (dstream), NULL, &err)) {
|
||||||
|
g_warning ("%s\n", err->message);
|
||||||
|
g_error_free (err);
|
||||||
|
g_object_unref (liststore);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Now the file has successfully read. */
|
||||||
|
if (win->file)
|
||||||
|
g_object_unref (file);
|
||||||
|
win->file = file; /* The ownership of the GFile moves to the window. */
|
||||||
|
s = g_file_get_basename (file);
|
||||||
|
gtk_label_set_text (GTK_LABEL (win->filename), s);
|
||||||
|
g_free (s);
|
||||||
|
liststore_old = win->liststore;
|
||||||
|
gtk_no_selection_set_model (win->noselection, G_LIST_MODEL (liststore));
|
||||||
|
win->liststore = liststore; /* The ownership of the stringlist moves to the window. */
|
||||||
|
g_object_unref (liststore_old);
|
||||||
|
update_current_position (win, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_cb (GtkButton *btn, LeWindow *win) {
|
read_cb (GtkButton *btn, LeWindow *win) {
|
||||||
GtkWidget *dialog;
|
GtkFileDialog *dialog;
|
||||||
|
|
||||||
if (win->file || g_list_model_get_n_items (G_LIST_MODEL (win->liststore)) > 0)
|
dialog = gtk_file_dialog_new ();
|
||||||
return;
|
gtk_file_dialog_open (dialog, GTK_WINDOW (win), NULL, open_dialog_cb, win);
|
||||||
dialog = gtk_file_chooser_dialog_new ("Open file", GTK_WINDOW (win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
g_object_unref (dialog);
|
||||||
"Cancel", GTK_RESPONSE_CANCEL,
|
|
||||||
"Open", GTK_RESPONSE_ACCEPT,
|
|
||||||
NULL);
|
|
||||||
g_signal_connect (dialog, "response", G_CALLBACK (open_dialog_response), win);
|
|
||||||
gtk_window_present (GTK_WINDOW (dialog));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -293,8 +255,9 @@ write_data (LeWindow *win) {
|
||||||
GFileOutputStream *ostream;
|
GFileOutputStream *ostream;
|
||||||
gssize size;
|
gssize size;
|
||||||
gsize length;
|
gsize length;
|
||||||
LeData *data;
|
|
||||||
int i, n_items;
|
int i, n_items;
|
||||||
|
LeData *data;
|
||||||
|
const char *s;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
|
|
||||||
if (! (ostream = g_file_replace (win->file, NULL, TRUE, G_FILE_CREATE_NONE, NULL, &err))) {
|
if (! (ostream = g_file_replace (win->file, NULL, TRUE, G_FILE_CREATE_NONE, NULL, &err))) {
|
||||||
|
@ -305,18 +268,19 @@ write_data (LeWindow *win) {
|
||||||
n_items = g_list_model_get_n_items (G_LIST_MODEL (win->liststore));
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (win->liststore));
|
||||||
for (i=0; i<n_items; ++i) {
|
for (i=0; i<n_items; ++i) {
|
||||||
data = LE_DATA (g_list_model_get_item (G_LIST_MODEL (win->liststore), i));
|
data = LE_DATA (g_list_model_get_item (G_LIST_MODEL (win->liststore), i));
|
||||||
length = (gsize) strlen (le_data_look_string (data));
|
s = le_data_look_string (data);
|
||||||
size = g_output_stream_write (G_OUTPUT_STREAM (ostream), le_data_look_string (data), length, NULL, &err);
|
length = (gsize) strlen (s);
|
||||||
|
size = g_output_stream_write (G_OUTPUT_STREAM (ostream), s, length, NULL, &err);
|
||||||
g_object_unref (data);
|
g_object_unref (data);
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
g_warning ("%s\n", err->message);
|
g_warning ("%s\n", err->message);
|
||||||
g_error_free (err);
|
g_clear_error (&err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
size = g_output_stream_write (G_OUTPUT_STREAM (ostream), "\n", 1, NULL, &err);
|
size = g_output_stream_write (G_OUTPUT_STREAM (ostream), "\n", 1, NULL, &err);
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
g_warning ("%s\n", err->message);
|
g_warning ("%s\n", err->message);
|
||||||
g_error_free (err);
|
g_clear_error (&err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,36 +291,34 @@ write_data (LeWindow *win) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
saveas_dialog_response (GtkWidget *dialog, gint response, LeWindow *win) {
|
saveas_dialog_cb (GObject* source_object, GAsyncResult* res, gpointer user_data) {
|
||||||
|
GtkFileDialog *dialog = GTK_FILE_DIALOG (source_object);
|
||||||
|
LeWindow *win = LE_WINDOW (user_data);
|
||||||
GFile *file;
|
GFile *file;
|
||||||
|
GError *err = NULL;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
if (response == GTK_RESPONSE_ACCEPT) {
|
if ((file = gtk_file_dialog_save_finish (dialog, res, &err)) == NULL) {
|
||||||
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
g_warning ("%s\n", err->message);
|
||||||
if (G_IS_FILE (file)) {
|
g_error_free (err);
|
||||||
win->file = file; /* the ownership is taken by win */
|
return;
|
||||||
s = g_file_get_basename (file);
|
|
||||||
gtk_label_set_text (GTK_LABEL (win->filename), s);
|
|
||||||
g_free (s);
|
|
||||||
write_data (win);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g_warning ("gtk_file_chooser_get_file returns non GFile.\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
gtk_window_destroy (GTK_WINDOW (dialog));
|
if (win->file)
|
||||||
|
g_object_unref (win->file);
|
||||||
|
win->file = file; /* the ownership is taken by win */
|
||||||
|
s = g_file_get_basename (file);
|
||||||
|
gtk_label_set_text (GTK_LABEL (win->filename), s);
|
||||||
|
g_free (s);
|
||||||
|
write_data (win);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
show_saveas_dialog (LeWindow *win) {
|
show_saveas_dialog (LeWindow *win) {
|
||||||
GtkWidget *dialog;
|
GtkFileDialog *dialog;
|
||||||
|
|
||||||
dialog = gtk_file_chooser_dialog_new ("Save file", GTK_WINDOW (win), GTK_FILE_CHOOSER_ACTION_SAVE,
|
dialog = gtk_file_dialog_new ();
|
||||||
"Cancel", GTK_RESPONSE_CANCEL,
|
gtk_file_dialog_save (dialog, GTK_WINDOW (win), NULL, saveas_dialog_cb, win);
|
||||||
"Save", GTK_RESPONSE_ACCEPT,
|
g_object_unref (dialog);
|
||||||
NULL);
|
|
||||||
g_signal_connect (dialog, "response", G_CALLBACK (saveas_dialog_response), win);
|
|
||||||
gtk_widget_show (dialog);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -371,14 +333,15 @@ write_cb (GtkButton *btn, LeWindow *win) {
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_cb (GtkButton *btn, LeWindow *win) {
|
close_cb (GtkButton *btn, LeWindow *win) {
|
||||||
if (g_list_model_get_n_items (G_LIST_MODEL (win->liststore)) > 0)
|
guint n_items;
|
||||||
|
|
||||||
|
if ((n_items = g_list_model_get_n_items (G_LIST_MODEL (win->liststore))) > 0)
|
||||||
g_list_store_remove_all (win->liststore);
|
g_list_store_remove_all (win->liststore);
|
||||||
if (win->file) {
|
if (win->file) {
|
||||||
g_clear_object (&win->file);
|
g_clear_object (&win->file);
|
||||||
gtk_label_set_text (GTK_LABEL (win->filename), "");
|
gtk_label_set_text (GTK_LABEL (win->filename), "");
|
||||||
}
|
}
|
||||||
win->position = -1;
|
update_current_position (win, -1);
|
||||||
gtk_label_set_text (GTK_LABEL (win->position_label), "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -391,7 +354,8 @@ void
|
||||||
select_cb (GtkButton *btn, GtkListItem *listitem) {
|
select_cb (GtkButton *btn, GtkListItem *listitem) {
|
||||||
LeWindow *win = LE_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (btn), LE_TYPE_WINDOW));
|
LeWindow *win = LE_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (btn), LE_TYPE_WINDOW));
|
||||||
|
|
||||||
update_current (win, gtk_list_item_get_position (listitem));
|
update_current_position (win, gtk_list_item_get_position (listitem));
|
||||||
|
update_current_button (win, btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----- Handlers on GtkSignalListItemFacory ----- */
|
/* ----- Handlers on GtkSignalListItemFacory ----- */
|
||||||
|
@ -407,24 +371,9 @@ static void
|
||||||
bind1_cb (GtkListItemFactory *factory, GtkListItem *listitem, gpointer user_data) {
|
bind1_cb (GtkListItemFactory *factory, GtkListItem *listitem, gpointer user_data) {
|
||||||
LeWindow *win = LE_WINDOW (user_data);
|
LeWindow *win = LE_WINDOW (user_data);
|
||||||
GtkWidget *button = gtk_list_item_get_child (listitem);
|
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));
|
|
||||||
|
|
||||||
if (data) {
|
if (win->position == gtk_list_item_get_position (listitem))
|
||||||
le_data_set_listitem (data, listitem);
|
update_current_button (win, GTK_BUTTON (button));
|
||||||
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
|
|
||||||
unbind1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
|
||||||
LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
|
||||||
if (data)
|
|
||||||
le_data_set_listitem (data, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -438,7 +387,7 @@ 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));
|
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));
|
||||||
GBinding *bind;
|
GBinding *bind;
|
||||||
|
|
||||||
gtk_editable_set_text (GTK_EDITABLE (text), le_data_look_string (data));
|
gtk_editable_set_text (GTK_EDITABLE (text), le_data_look_string (data));
|
||||||
|
@ -452,7 +401,8 @@ static void
|
||||||
unbind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
unbind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
GBinding *bind = G_BINDING (g_object_get_data (G_OBJECT (listitem), "bind"));
|
GBinding *bind = G_BINDING (g_object_get_data (G_OBJECT (listitem), "bind"));
|
||||||
|
|
||||||
g_binding_unbind(bind);
|
if (bind)
|
||||||
|
g_binding_unbind(bind);
|
||||||
g_object_set_data (G_OBJECT (listitem), "bind", NULL);
|
g_object_set_data (G_OBJECT (listitem), "bind", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,24 +413,29 @@ adjustment_value_changed_cb (GtkAdjustment *adjustment, gpointer user_data) {
|
||||||
gtk_window_set_focus (GTK_WINDOW (win), NULL);
|
gtk_window_set_focus (GTK_WINDOW (win), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
le_window_init (LeWindow *win) {
|
|
||||||
gtk_widget_init_template (GTK_WIDGET (win));
|
|
||||||
|
|
||||||
win->position = -1;
|
|
||||||
win->file =NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
le_window_dispose (GObject *object) {
|
le_window_dispose (GObject *object) {
|
||||||
LeWindow *win = LE_WINDOW (object);
|
LeWindow *win = LE_WINDOW (object);
|
||||||
|
|
||||||
|
if (win->current_button)
|
||||||
|
g_clear_object (&win->current_button);
|
||||||
|
if (win->file)
|
||||||
|
g_clear_object (&win->file);
|
||||||
/* this function is available since GTK 4.8 */
|
/* this function is available since GTK 4.8 */
|
||||||
gtk_widget_dispose_template (GTK_WIDGET (win), LE_TYPE_WINDOW);
|
gtk_widget_dispose_template (GTK_WIDGET (win), LE_TYPE_WINDOW);
|
||||||
/* chain to the parent */
|
/* chain to the parent */
|
||||||
G_OBJECT_CLASS (le_window_parent_class)->dispose (object);
|
G_OBJECT_CLASS (le_window_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
le_window_init (LeWindow *win) {
|
||||||
|
gtk_widget_init_template (GTK_WIDGET (win));
|
||||||
|
|
||||||
|
win->position = -1;
|
||||||
|
win->current_button = NULL;
|
||||||
|
win->file =NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
le_window_class_init (LeWindowClass *class) {
|
le_window_class_init (LeWindowClass *class) {
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
@ -491,6 +446,7 @@ le_window_class_init (LeWindowClass *class) {
|
||||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, position_label);
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, position_label);
|
||||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, filename);
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, filename);
|
||||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, columnview);
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, columnview);
|
||||||
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, noselection);
|
||||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, liststore);
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), LeWindow, liststore);
|
||||||
/* The followint macros are available since GTK 4.8 */
|
/* The followint macros are available since GTK 4.8 */
|
||||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), app_cb);
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), app_cb);
|
||||||
|
@ -502,7 +458,6 @@ le_window_class_init (LeWindowClass *class) {
|
||||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), quit_cb);
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), quit_cb);
|
||||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), setup1_cb);
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), setup1_cb);
|
||||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), bind1_cb);
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), bind1_cb);
|
||||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), unbind1_cb);
|
|
||||||
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);
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<interface>
|
<interface>
|
||||||
<template class="LeWindow" parent="GtkApplicationWindow">
|
<template class="LeWindow" parent="GtkApplicationWindow">
|
||||||
<property name="title">list editor</property>
|
<property name="title">list editor</property>
|
||||||
<property name="default-width">600</property>
|
<property name="default-width">1000</property>
|
||||||
<property name="default-height">400</property>
|
<property name="default-height">600</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="orientation">GTK_ORIENTATION_VERTICAL</property>
|
<property name="orientation">GTK_ORIENTATION_VERTICAL</property>
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
<property name="vexpand">TRUE</property>
|
<property name="vexpand">TRUE</property>
|
||||||
<property name="focusable">FALSE</property>
|
<property name="focusable">FALSE</property>
|
||||||
<property name="model">
|
<property name="model">
|
||||||
<object class="GtkNoSelection">
|
<object class="GtkNoSelection" id = "noselection">
|
||||||
<property name="model">
|
<property name="model">
|
||||||
<object class="GListStore" id="liststore">
|
<object class="GListStore" id="liststore">
|
||||||
<property name="item-type">LeData</property>
|
<property name="item-type">LeData</property>
|
||||||
|
@ -110,7 +110,6 @@
|
||||||
<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" swapped="no" object="LeWindow"></signal>
|
<signal name="bind" handler="bind1_cb" swapped="no" object="LeWindow"></signal>
|
||||||
<signal name="unbind" handler="unbind1_cb"></signal>
|
|
||||||
</object>
|
</object>
|
||||||
</property>
|
</property>
|
||||||
</object>
|
</object>
|
||||||
|
@ -118,6 +117,7 @@
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkColumnViewColumn">
|
<object class="GtkColumnViewColumn">
|
||||||
<property name="title">String</property>
|
<property name="title">String</property>
|
||||||
|
<property name="expand">TRUE</property>
|
||||||
<property name="factory">
|
<property name="factory">
|
||||||
<object class="GtkSignalListItemFactory">
|
<object class="GtkSignalListItemFactory">
|
||||||
<signal name="setup" handler="setup2_cb"></signal>
|
<signal name="setup" handler="setup2_cb"></signal>
|
||||||
|
|
|
@ -6,9 +6,10 @@ The new feature is described in [Gtk API Reference -- List Widget Overview](http
|
||||||
GTK 4 has other means to implement lists.
|
GTK 4 has other means to implement lists.
|
||||||
They are GtkListBox and GtkTreeView which are took over from GTK 3.
|
They are GtkListBox and GtkTreeView which are took over from GTK 3.
|
||||||
There's an article in [Gtk Development blog](https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/) about list widgets by Matthias Clasen.
|
There's an article in [Gtk Development blog](https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/) about list widgets by Matthias Clasen.
|
||||||
He described why GtkListView are developed to replace GtkListBox and GtkTreeView.
|
He described why GtkListView are developed to replace GtkTreeView.
|
||||||
|
GtkTreeView is deprecated since version 4.10.
|
||||||
|
|
||||||
GtkListView, GtkGridView, GtkColumnView and related objects are described in Section 26 to 29.
|
GtkListView, GtkGridView, GtkColumnView and related objects are described in Section 29 to 33.
|
||||||
|
|
||||||
## Outline
|
## Outline
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ A list is like an array, but in many cases it is implemented with pointers which
|
||||||
And it has a start point.
|
And it has a start point.
|
||||||
So, each item can be referred by the index of the item (first item, second item, ..., nth item, ...).
|
So, each item can be referred by the index of the item (first item, second item, ..., nth item, ...).
|
||||||
There are two cases.
|
There are two cases.
|
||||||
One is the index starts from one (one-based) and the other is from zero (zero-based).
|
The one is the index starts from one (one-based) and the other is from zero (zero-based).
|
||||||
|
|
||||||
Gio provides GListModel interface.
|
Gio provides GListModel interface.
|
||||||
It is a zero-based list and its items are the same type of GObject descendants, or objects that implement the same interface.
|
It is a zero-based list and its items are the same type of GObject descendants, or objects that implement the same interface.
|
||||||
|
@ -27,11 +28,11 @@ An object implements GListModel is not a widget.
|
||||||
So, the list is not displayed on the screen directly.
|
So, the list is not displayed on the screen directly.
|
||||||
There's another object GtkListView which is a widget to display the list.
|
There's another object GtkListView which is a widget to display the list.
|
||||||
The items in the list need to be connected to the items in GtkListView.
|
The items in the list need to be connected to the items in GtkListView.
|
||||||
GtkListItemFactory instance maps items in the list to GListView.
|
GtkListItemFactory instance maps items in the list to GtkListView.
|
||||||
|
|
||||||
![List](../image/list.png){width=10cm height=7.5cm}
|
![List](../image/list.png){width=10cm height=7.5cm}
|
||||||
|
|
||||||
## GListModel
|
## GListModel and GtkStringList
|
||||||
|
|
||||||
If you want to make a list of strings with GListModel, for example, "one", "two", "three", "four", note that strings can't be items of the list.
|
If you want to make a list of strings with GListModel, for example, "one", "two", "three", "four", note that strings can't be items of the list.
|
||||||
Because GListModel is a list of GObject objects and strings aren't GObject objects.
|
Because GListModel is a list of GObject objects and strings aren't GObject objects.
|
||||||
|
@ -172,6 +173,7 @@ If you feel some difficulty, read this section again, especially GtkSignalListIt
|
||||||
GtkBuilderListItemFactory is another GtkListItemFactory.
|
GtkBuilderListItemFactory is another GtkListItemFactory.
|
||||||
Its behavior is defined with ui file.
|
Its behavior is defined with ui file.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~xml
|
~~~xml
|
||||||
<interface>
|
<interface>
|
||||||
<template class="GtkListItem">
|
<template class="GtkListItem">
|
||||||
|
@ -187,6 +189,23 @@ Its behavior is defined with ui file.
|
||||||
</template>
|
</template>
|
||||||
</interface>
|
</interface>
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.xml}
|
||||||
|
<interface>
|
||||||
|
<template class="GtkListItem">
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<binding name="label">
|
||||||
|
<lookup name="string" type="GtkStringObject">
|
||||||
|
<lookup name="item">GtkListItem</lookup>
|
||||||
|
</lookup>
|
||||||
|
</binding>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
Template tag is used to define GtkListItem.
|
Template tag is used to define GtkListItem.
|
||||||
And its child property is GtkLabel object.
|
And its child property is GtkLabel object.
|
||||||
|
@ -209,7 +228,7 @@ There is an explanation in the [GTK Development Blog](https://blog.gtk.org/2020/
|
||||||
> Remember that the classname (GtkListItem) in a ui template is used as the “this” pointer referring to the object that is being instantiated.
|
> Remember that the classname (GtkListItem) in a ui template is used as the “this” pointer referring to the object that is being instantiated.
|
||||||
|
|
||||||
Therefore, GtkListItem instance is used as the `this` object of the lookup tag when it is evaluated.
|
Therefore, GtkListItem instance is used as the `this` object of the lookup tag when it is evaluated.
|
||||||
`this` object will be explained in [section 30](sec30).
|
`this` object will be explained in [section 31](sec31).
|
||||||
|
|
||||||
The C source code is as follows.
|
The C source code is as follows.
|
||||||
Its name is `list2.c` and located under [src/misc](misc) directory.
|
Its name is `list2.c` and located under [src/misc](misc) directory.
|
||||||
|
@ -229,9 +248,15 @@ GtkDirectoryList is a list model containing GFileInfo objects which are informat
|
||||||
It uses `g_file_enumerate_children_async()` to get the GFileInfo objects.
|
It uses `g_file_enumerate_children_async()` to get the GFileInfo objects.
|
||||||
The list model is created by `gtk_directory_list_new` function.
|
The list model is created by `gtk_directory_list_new` function.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
GtkDirectoryList *gtk_directory_list_new (const char *attributes, GFile *file);
|
GtkDirectoryList *gtk_directory_list_new (const char *attributes, GFile *file);
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
GtkDirectoryList *gtk_directory_list_new (const char *attributes, GFile *file);
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
`attributes` is a comma separated list of file attributes.
|
`attributes` is a comma separated list of file attributes.
|
||||||
File attributes are key-value pairs.
|
File attributes are key-value pairs.
|
||||||
|
@ -252,11 +277,19 @@ The following table shows some example.
|
||||||
The current directory is ".".
|
The current directory is ".".
|
||||||
The following program makes GtkDirectoryList `dl` and its contents are GFileInfo objects under the current directory.
|
The following program makes GtkDirectoryList `dl` and its contents are GFileInfo objects under the current directory.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
GFile *file = g_file_new_for_path (".");
|
GFile *file = g_file_new_for_path (".");
|
||||||
GtkDirectoryList *dl = gtk_directory_list_new ("standard::name", file);
|
GtkDirectoryList *dl = gtk_directory_list_new ("standard::name", file);
|
||||||
g_object_unref (file);
|
g_object_unref (file);
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
GFile *file = g_file_new_for_path (".");
|
||||||
|
GtkDirectoryList *dl = gtk_directory_list_new ("standard::name", file);
|
||||||
|
g_object_unref (file);
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
It is not so difficult to make file listing program by changing `list2.c` in the previous subsection.
|
It is not so difficult to make file listing program by changing `list2.c` in the previous subsection.
|
||||||
One problem is that GInfoFile doesn't have properties.
|
One problem is that GInfoFile doesn't have properties.
|
||||||
|
@ -264,8 +297,9 @@ Lookup tag look for a property, so it is useless for looking for a filename from
|
||||||
Instead, closure tag is appropriate in this case.
|
Instead, closure tag is appropriate in this case.
|
||||||
Closure tag specifies a function and the type of the return value of the function.
|
Closure tag specifies a function and the type of the return value of the function.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
const char *
|
char *
|
||||||
get_file_name (GtkListItem *item, GFileInfo *info) {
|
get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||||
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||||
}
|
}
|
||||||
|
@ -286,6 +320,30 @@ get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||||
"</template>"
|
"</template>"
|
||||||
"</interface>"
|
"</interface>"
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
char *
|
||||||
|
get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||||
|
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||||
|
}
|
||||||
|
... ...
|
||||||
|
... ...
|
||||||
|
|
||||||
|
"<interface>"
|
||||||
|
"<template class=\"GtkListItem\">"
|
||||||
|
"<property name=\"child\">"
|
||||||
|
"<object class=\"GtkLabel\">"
|
||||||
|
"<binding name=\"label\">"
|
||||||
|
"<closure type=\"gchararray\" function=\"get_file_name\">"
|
||||||
|
"<lookup name=\"item\">GtkListItem</lookup>"
|
||||||
|
"</closure>"
|
||||||
|
"</binding>"
|
||||||
|
"</object>"
|
||||||
|
"</property>"
|
||||||
|
"</template>"
|
||||||
|
"</interface>"
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
- The string "gchararray" is a type name.
|
- The string "gchararray" is a type name.
|
||||||
The type "gchar" is a type name and it is the same as C type "char".
|
The type "gchar" is a type name and it is the same as C type "char".
|
||||||
|
@ -301,7 +359,7 @@ The contents of closure tag (it is between \<closure...\> and\</closure\>) is pa
|
||||||
`<lookup name="item">GtkListItem</lookup>` gives the value of the item property of the GtkListItem.
|
`<lookup name="item">GtkListItem</lookup>` gives the value of the item property of the GtkListItem.
|
||||||
This will be the second argument of the function.
|
This will be the second argument of the function.
|
||||||
The first parameter is always the GListItem instance, which is a 'this' object.
|
The first parameter is always the GListItem instance, which is a 'this' object.
|
||||||
The 'this' object is explained in section 28.
|
The 'this' object is explained in section 31.
|
||||||
- `gtk_file_name` function is the callback function for the closure tag.
|
- `gtk_file_name` function is the callback function for the closure tag.
|
||||||
It first checks the `info` parameter.
|
It first checks the `info` parameter.
|
||||||
Because it can be NULL when GListItem `item` is unbounded.
|
Because it can be NULL when GListItem `item` is unbounded.
|
||||||
|
@ -341,9 +399,15 @@ $ gcc -Wl,--export-dynamic `pkg-config --cflags gtk4` list3.c `pkg-config --libs
|
||||||
|
|
||||||
You can also make a shell script to compile `list3.c`
|
You can also make a shell script to compile `list3.c`
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~bash
|
~~~bash
|
||||||
gcc -Wl,--export-dynamic `pkg-config --cflags gtk4` $1.c `pkg-config --libs gtk4`
|
gcc -Wl,--export-dynamic `pkg-config --cflags gtk4` $1.c `pkg-config --libs gtk4`
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.bash}
|
||||||
|
gcc -Wl,--export-dynamic `pkg-config --cflags gtk4` $1.c `pkg-config --libs gtk4`
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
Save this one liner to a file `comp`.
|
Save this one liner to a file `comp`.
|
||||||
Then, copy it to `$HOME/bin` and give it executable permission.
|
Then, copy it to `$HOME/bin` and give it executable permission.
|
||||||
|
@ -361,4 +425,3 @@ $ ./a.out
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
![screenshot list3](../image/list3.png){width=10cm height=7.3cm}
|
![screenshot list3](../image/list3.png){width=10cm height=7.3cm}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ GtkGridView (model property) => GtkSingleSelection (model property) => GtkDirect
|
||||||
|
|
||||||
The following is a part of the ui file `list4.ui`.
|
The following is a part of the ui file `list4.ui`.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~xml
|
~~~xml
|
||||||
<object class="GtkListView" id="list">
|
<object class="GtkListView" id="list">
|
||||||
<property name="model">
|
<property name="model">
|
||||||
|
@ -48,6 +49,24 @@ The following is a part of the ui file `list4.ui`.
|
||||||
<property name="model">singleselection</property>
|
<property name="model">singleselection</property>
|
||||||
</object>
|
</object>
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.xml}
|
||||||
|
<object class="GtkListView" id="list">
|
||||||
|
<property name="model">
|
||||||
|
<object class="GtkSingleSelection" id="singleselection">
|
||||||
|
<property name="model">
|
||||||
|
<object class="GtkDirectoryList" id="directorylist">
|
||||||
|
<property name="attributes">standard::name,standard::icon,standard::content-type</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
<object class="GtkGridView" id="grid">
|
||||||
|
<property name="model">singleselection</property>
|
||||||
|
</object>
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
GtkDirectoryList has an "attributes" property.
|
GtkDirectoryList has an "attributes" property.
|
||||||
It is attributes of GFileInfo such as "standard::name", "standard::icon" and "standard::content-type".
|
It is attributes of GFileInfo such as "standard::name", "standard::icon" and "standard::content-type".
|
||||||
|
@ -62,7 +81,7 @@ Such "x-" subtype is not a standard mime type.)
|
||||||
Content type is also used by desktop systems.
|
Content type is also used by desktop systems.
|
||||||
|
|
||||||
GtkGridView uses the same GtkSingleSelection instance (`singleselection`).
|
GtkGridView uses the same GtkSingleSelection instance (`singleselection`).
|
||||||
So, its model property is set with it.
|
So, its model property is set to it.
|
||||||
|
|
||||||
## Ui file of the window
|
## Ui file of the window
|
||||||
|
|
||||||
|
@ -112,11 +131,19 @@ Its child widget will be set with GtkListView or GtkGridView.
|
||||||
|
|
||||||
The action `view` is created, connected to the "activate" signal handler and inserted to the window (action map) as follows.
|
The action `view` is created, connected to the "activate" signal handler and inserted to the window (action map) as follows.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
act_view = g_simple_action_new_stateful ("view", g_variant_type_new("s"), g_variant_new_string ("list"));
|
act_view = g_simple_action_new_stateful ("view", g_variant_type_new("s"), g_variant_new_string ("list"));
|
||||||
g_signal_connect (act_view, "activate", G_CALLBACK (view_activated), NULL);
|
g_signal_connect (act_view, "activate", G_CALLBACK (view_activated), NULL);
|
||||||
g_action_map_add_action (G_ACTION_MAP (win), G_ACTION (act_view));
|
g_action_map_add_action (G_ACTION_MAP (win), G_ACTION (act_view));
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
act_view = g_simple_action_new_stateful ("view", g_variant_type_new("s"), g_variant_new_string ("list"));
|
||||||
|
g_signal_connect (act_view, "activate", G_CALLBACK (view_activated), NULL);
|
||||||
|
g_action_map_add_action (G_ACTION_MAP (win), G_ACTION (act_view));
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
The signal handler `view_activated` will be explained later.
|
The signal handler `view_activated` will be explained later.
|
||||||
|
|
||||||
|
@ -198,6 +225,7 @@ You can do anything you like by connecting the "activate" signal to the handler.
|
||||||
|
|
||||||
The example `list4` launches `tfe` text file editor if the item of the list is a text file.
|
The example `list4` launches `tfe` text file editor if the item of the list is a text file.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
static void
|
static void
|
||||||
list_activate (GtkListView *list, int position, gpointer user_data) {
|
list_activate (GtkListView *list, int position, gpointer user_data) {
|
||||||
|
@ -217,6 +245,27 @@ grid_activate (GtkGridView *grid, int position, gpointer user_data) {
|
||||||
g_signal_connect (GTK_LIST_VIEW (list), "activate", G_CALLBACK (list_activate), NULL);
|
g_signal_connect (GTK_LIST_VIEW (list), "activate", G_CALLBACK (list_activate), NULL);
|
||||||
g_signal_connect (GTK_GRID_VIEW (grid), "activate", G_CALLBACK (grid_activate), NULL);
|
g_signal_connect (GTK_GRID_VIEW (grid), "activate", G_CALLBACK (grid_activate), NULL);
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
static void
|
||||||
|
list_activate (GtkListView *list, int position, gpointer user_data) {
|
||||||
|
GFileInfo *info = G_FILE_INFO (g_list_model_get_item (G_LIST_MODEL (gtk_list_view_get_model (list)), position));
|
||||||
|
launch_tfe_with_file (info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grid_activate (GtkGridView *grid, int position, gpointer user_data) {
|
||||||
|
GFileInfo *info = G_FILE_INFO (g_list_model_get_item (G_LIST_MODEL (gtk_grid_view_get_model (grid)), position));
|
||||||
|
launch_tfe_with_file (info);
|
||||||
|
}
|
||||||
|
|
||||||
|
... ...
|
||||||
|
... ...
|
||||||
|
|
||||||
|
g_signal_connect (GTK_LIST_VIEW (list), "activate", G_CALLBACK (list_activate), NULL);
|
||||||
|
g_signal_connect (GTK_GRID_VIEW (grid), "activate", G_CALLBACK (grid_activate), NULL);
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
The second parameter of each handler is the position of the item (GFileInfo) of the GListModel.
|
The second parameter of each handler is the position of the item (GFileInfo) of the GListModel.
|
||||||
So you can get the item with `g_list_model_get_item` function.
|
So you can get the item with `g_list_model_get_item` function.
|
||||||
|
@ -254,7 +303,7 @@ The last parameter is the pointer to the pointer to a GError.
|
||||||
|
|
||||||
If your distribution supports GTK 4, using `g_app_info_launch_default_for_uri` is convenient.
|
If your distribution supports GTK 4, using `g_app_info_launch_default_for_uri` is convenient.
|
||||||
The function automatically determines the default application from the file and launches it.
|
The function automatically determines the default application from the file and launches it.
|
||||||
For example, if the file is text, then it launches gedit with the file.
|
For example, if the file is text, then it launches GNOME text editor with the file.
|
||||||
Such feature comes from desktop.
|
Such feature comes from desktop.
|
||||||
|
|
||||||
## Compilation and execution
|
## Compilation and execution
|
||||||
|
@ -264,7 +313,7 @@ To compile and execute list4, type as follows.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ cd list4 # or cd src/list4. It depends your current directory.
|
$ cd list4 # or cd src/list4. It depends your current directory.
|
||||||
$ meson _build
|
$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/list4
|
$ _build/list4
|
||||||
~~~
|
~~~
|
||||||
|
|
163
src/sec31.src.md
163
src/sec31.src.md
|
@ -56,8 +56,8 @@ The type of the value is int.
|
||||||
|G\_TYPE\_INT |int |gint | |
|
|G\_TYPE\_INT |int |gint | |
|
||||||
|G\_TYPE\_FLOAT |float |gfloat | |
|
|G\_TYPE\_FLOAT |float |gfloat | |
|
||||||
|G\_TYPE\_DOUBLE |double|gdouble | |
|
|G\_TYPE\_DOUBLE |double|gdouble | |
|
||||||
|G\_TYPE\_POINTER | |gpointer | |
|
|G\_TYPE\_POINTER |void *|gpointer |general pointer |
|
||||||
|G\_TYPE\_STRING | |gchararray|null-terminated Cstring|
|
|G\_TYPE\_STRING |char *|gchararray|null-terminated Cstring|
|
||||||
|G\_TYPE\_OBJECT | |GObject | |
|
|G\_TYPE\_OBJECT | |GObject | |
|
||||||
|GTK\_TYPE\_WINDOW| |GtkWindow | |
|
|GTK\_TYPE\_WINDOW| |GtkWindow | |
|
||||||
|
|
||||||
|
@ -79,9 +79,15 @@ Constant expression is usually used to give a constant value or instance to anot
|
||||||
A property expression (GtkPropertyExpression) looks up a property in a GObject instance.
|
A property expression (GtkPropertyExpression) looks up a property in a GObject instance.
|
||||||
For example, a property expression that refers "label" property in a GtkLabel object is created like this.
|
For example, a property expression that refers "label" property in a GtkLabel object is created like this.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
expression = gtk_property_expression_new (GTK_TYPE_LABEL, another_expression, "label");
|
expression = gtk_property_expression_new (GTK_TYPE_LABEL, another_expression, "label");
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
expression = gtk_property_expression_new (GTK_TYPE_LABEL, another_expression, "label");
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
The second parameter `another_expression` is one of:
|
The second parameter `another_expression` is one of:
|
||||||
|
|
||||||
|
@ -91,15 +97,23 @@ The instance is called `this` object.
|
||||||
|
|
||||||
For example,
|
For example,
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
label = gtk_label_new ("Hello");
|
label = gtk_label_new ("Hello");
|
||||||
another_expression = gtk_constant_expression_new (GTK_TYPE_LABEL, label);
|
another_expression = gtk_constant_expression_new (GTK_TYPE_LABEL, label);
|
||||||
expression = gtk_property_expression_new (GTK_TYPE_LABEL, another_expression, "label");
|
expression = gtk_property_expression_new (GTK_TYPE_LABEL, another_expression, "label");
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
label = gtk_label_new ("Hello");
|
||||||
|
another_expression = gtk_constant_expression_new (GTK_TYPE_LABEL, label);
|
||||||
|
expression = gtk_property_expression_new (GTK_TYPE_LABEL, another_expression, "label");
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
If `expression` is evaluated, the second parameter `another_expression` is evaluated in advance.
|
If `expression` is evaluated, the second parameter `another_expression` is evaluated in advance.
|
||||||
The value of `another_expression` is the `label` (GtkLabel instance).
|
The value of `another_expression` is the `label` (GtkLabel instance).
|
||||||
Then, `expression` looks up "label" property of the label and the evaluation results "Hello".
|
Then, `expression` looks up "label" property of the label and the evaluation results in "Hello".
|
||||||
|
|
||||||
In the example above, the second argument of `gtk_property_expression_new` is another expression.
|
In the example above, the second argument of `gtk_property_expression_new` is another expression.
|
||||||
But the second argument can be NULL.
|
But the second argument can be NULL.
|
||||||
|
@ -123,7 +137,7 @@ The expression just knows how to take the property from a future-given GtkLabel
|
||||||
The result is stored in the GValue `value`.
|
The result is stored in the GValue `value`.
|
||||||
The function `g_value_get_string` gets a string from the GValue.
|
The function `g_value_get_string` gets a string from the GValue.
|
||||||
But the string is owned by the GValue so you must not free the string.
|
But the string is owned by the GValue so you must not free the string.
|
||||||
- 18-19: Release the expression and unset the GValue.
|
- 18-19: Releases the expression and unset the GValue.
|
||||||
At the same time the string in the GValue is freed.
|
At the same time the string in the GValue is freed.
|
||||||
|
|
||||||
If the second argument of `gtk_property_expression_new` isn't NULL, it is another expression.
|
If the second argument of `gtk_property_expression_new` isn't NULL, it is another expression.
|
||||||
|
@ -144,6 +158,7 @@ When you program in C language, GtkCClosureExpression and GCClosure are appropri
|
||||||
|
|
||||||
A closure expression is created with `gtk_cclosure_expression_new` function.
|
A closure expression is created with `gtk_cclosure_expression_new` function.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
GtkExpression *
|
GtkExpression *
|
||||||
gtk_cclosure_expression_new (GType value_type,
|
gtk_cclosure_expression_new (GType value_type,
|
||||||
|
@ -154,6 +169,18 @@ gtk_cclosure_expression_new (GType value_type,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GClosureNotify user_destroy);
|
GClosureNotify user_destroy);
|
||||||
~~~
|
~~~
|
||||||
|
@else
|
||||||
|
~~~{.C}
|
||||||
|
GtkExpression *
|
||||||
|
gtk_cclosure_expression_new (GType value_type,
|
||||||
|
GClosureMarshal marshal,
|
||||||
|
guint n_params,
|
||||||
|
GtkExpression **params,
|
||||||
|
GCallback callback_func,
|
||||||
|
gpointer user_data,
|
||||||
|
GClosureNotify user_destroy);
|
||||||
|
~~~
|
||||||
|
@end
|
||||||
|
|
||||||
- `value_type` is the type of the value when it is evaluated.
|
- `value_type` is the type of the value when it is evaluated.
|
||||||
- `marshal` is a marshaller.
|
- `marshal` is a marshaller.
|
||||||
|
@ -183,10 +210,17 @@ callback (this, param1, param2, ...)
|
||||||
|
|
||||||
For example,
|
For example,
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
int
|
int
|
||||||
callback (GObject *object, int x, const char *s)
|
callback (GObject *object, int x, const char *s)
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
int
|
||||||
|
callback (GObject *object, int x, const char *s)
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
The following is `exp_closure_simple.c` in `src/expression`.
|
The following is `exp_closure_simple.c` in `src/expression`.
|
||||||
|
|
||||||
|
@ -203,13 +237,13 @@ If you want to return error report, change the return value type to be a pointer
|
||||||
One for error and the other for the sum.
|
One for error and the other for the sum.
|
||||||
The first argument of `gtk_cclosure_expression_new` is `G_TYPE_POINTER`.
|
The first argument of `gtk_cclosure_expression_new` is `G_TYPE_POINTER`.
|
||||||
There is a sample program `exp_closure_with_error_report` in `src/expression` directory.
|
There is a sample program `exp_closure_with_error_report` in `src/expression` directory.
|
||||||
- 19: gtk\_init initializes GTK. It is necessary for GtkLabel.
|
- 19: The function `gtk_init`` initializes GTK. It is necessary for GtkLabel.
|
||||||
- 20: A GtkLabel instance is created with "123+456".
|
- 20: A GtkLabel instance is created with "123+456".
|
||||||
- 21: The instance has floating reference. It is changed to an ordinary reference count.
|
- 21: The instance has floating reference. It is changed to an ordinary reference count.
|
||||||
- 22-23: Create a closure expression. Its return value type is `G_TYPE_INT` and no parameters or 'this' object.
|
- 22-23: Creates a closure expression. Its return value type is `G_TYPE_INT` and no parameters or 'this' object.
|
||||||
- 24: Evaluates the expression with the label as a 'this' object.
|
- 24: Evaluates the expression with the label as a 'this' object.
|
||||||
- 25: If the evaluation successes, show the sum of "123+456". It's 579.
|
- 25: If the evaluation successes, the sum of "123+456", which is 579, is shown.
|
||||||
- 27: If it fails, show an error message.
|
- 27: If it fails, an error message appears.
|
||||||
- 28-30: Releases the expression and the label. Unsets the value.
|
- 28-30: Releases the expression and the label. Unsets the value.
|
||||||
|
|
||||||
Closure expression is flexible than other type of expression because you can specify your own callback function.
|
Closure expression is flexible than other type of expression because you can specify your own callback function.
|
||||||
|
@ -219,12 +253,14 @@ Closure expression is flexible than other type of expression because you can spe
|
||||||
GtkExpressionWatch is a structure, not an object.
|
GtkExpressionWatch is a structure, not an object.
|
||||||
It represents a watched GtkExpression.
|
It represents a watched GtkExpression.
|
||||||
Two functions create GtkExpressionWatch structure.
|
Two functions create GtkExpressionWatch structure.
|
||||||
|
They are `gtk_expression_bind` and `gtk_expression_watch`.
|
||||||
|
|
||||||
### gtk\_expression\_bind function
|
### gtk\_expression\_bind function
|
||||||
|
|
||||||
This function binds the target object's property to the expression.
|
This function binds the target object's property to the expression.
|
||||||
If the value of the expression changes, the property reflects the value immediately.
|
If the value of the expression changes, the property reflects the value immediately.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
GtkExpressionWatch*
|
GtkExpressionWatch*
|
||||||
gtk_expression_bind (
|
gtk_expression_bind (
|
||||||
|
@ -234,6 +270,17 @@ gtk_expression_bind (
|
||||||
GObject* this_
|
GObject* this_
|
||||||
)
|
)
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
GtkExpressionWatch*
|
||||||
|
gtk_expression_bind (
|
||||||
|
GtkExpression* self,
|
||||||
|
GObject* target,
|
||||||
|
const char* property,
|
||||||
|
GObject* this_
|
||||||
|
)
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
This function takes the ownership of the expression.
|
This function takes the ownership of the expression.
|
||||||
So, if you want to own the expression, call `gtk_expression_ref ()` to increase the reference count of the expression.
|
So, if you want to own the expression, call `gtk_expression_ref ()` to increase the reference count of the expression.
|
||||||
|
@ -282,7 +329,7 @@ The point of the program is:
|
||||||
|
|
||||||
- 41-42: Two expressions are defined.
|
- 41-42: Two expressions are defined.
|
||||||
One is a property expression and the other is a closure expression.
|
One is a property expression and the other is a closure expression.
|
||||||
The property expression look up the "value"property of the adjustment instance.
|
The property expression looks up the "value" property of the adjustment instance.
|
||||||
The closure expression just converts the double into an integer.
|
The closure expression just converts the double into an integer.
|
||||||
- 43: `gtk_expression_bind` binds the label property of the GtkLabel instance to the integer returned by the closure expression.
|
- 43: `gtk_expression_bind` binds the label property of the GtkLabel instance to the integer returned by the closure expression.
|
||||||
It creates a GtkExpressionWatch structure.
|
It creates a GtkExpressionWatch structure.
|
||||||
|
@ -296,14 +343,15 @@ This signal is emitted when the close button is clicked.
|
||||||
The handler is called just before the window closes.
|
The handler is called just before the window closes.
|
||||||
It is the right moment to make the GtkExpressionWatch unwatched.
|
It is the right moment to make the GtkExpressionWatch unwatched.
|
||||||
- 10-14: "close-request" signal handler.
|
- 10-14: "close-request" signal handler.
|
||||||
`gtk_expression_watch_unwatch (watch)` makes the watch stop watching the expression.
|
The function `gtk_expression_watch_unwatch (watch)` makes the watch stop watching the expression.
|
||||||
It releases the expression and calls `gtk_expression_watch_unref (watch)` in it.
|
It also releases the expression.
|
||||||
|
|
||||||
If you want to bind a property to an expression, `gtk_expression_bind` is the best choice.
|
If you want to bind a property to an expression, `gtk_expression_bind` is the best choice.
|
||||||
You can do it with `gtk_expression_watch` function, but it is less suitable.
|
You can do it with `gtk_expression_watch` function, but it is less suitable.
|
||||||
|
|
||||||
### gtk\_expression\_watch function
|
### gtk\_expression\_watch function
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
GtkExpressionWatch*
|
GtkExpressionWatch*
|
||||||
gtk_expression_watch (
|
gtk_expression_watch (
|
||||||
|
@ -314,6 +362,18 @@ gtk_expression_watch (
|
||||||
GDestroyNotify user_destroy
|
GDestroyNotify user_destroy
|
||||||
)
|
)
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
GtkExpressionWatch*
|
||||||
|
gtk_expression_watch (
|
||||||
|
GtkExpression* self,
|
||||||
|
GObject* this_,
|
||||||
|
GtkExpressionNotify notify,
|
||||||
|
gpointer user_data,
|
||||||
|
GDestroyNotify user_destroy
|
||||||
|
)
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
The function doesn't take the ownership of the expression.
|
The function doesn't take the ownership of the expression.
|
||||||
It differs from `gtk_expression_bind`.
|
It differs from `gtk_expression_bind`.
|
||||||
|
@ -326,12 +386,21 @@ Put NULL if you don't need them.
|
||||||
|
|
||||||
Notify callback has the following format.
|
Notify callback has the following format.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~C
|
~~~C
|
||||||
void
|
void
|
||||||
notify (
|
notify (
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
)
|
)
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.C}
|
||||||
|
void
|
||||||
|
notify (
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
This function is used to do something when the value of the expression changes.
|
This function is used to do something when the value of the expression changes.
|
||||||
But if you want to bind a property to the value, use `gtk_expression_bind` instead.
|
But if you want to bind a property to the value, use `gtk_expression_bind` instead.
|
||||||
|
@ -381,6 +450,7 @@ It is put in the content of an object tag.
|
||||||
Name attribute specifies the property name of the object.
|
Name attribute specifies the property name of the object.
|
||||||
The content is an expression.
|
The content is an expression.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~xml
|
~~~xml
|
||||||
<constant type="gchararray">Hello world</constant>
|
<constant type="gchararray">Hello world</constant>
|
||||||
<lookup name="label" type="GtkLabel">label</lookup>
|
<lookup name="label" type="GtkLabel">label</lookup>
|
||||||
|
@ -389,16 +459,27 @@ The content is an expression.
|
||||||
<lookup name="default-width">win</lookup>
|
<lookup name="default-width">win</lookup>
|
||||||
</bind>
|
</bind>
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.xml}
|
||||||
|
<constant type="gchararray">Hello world</constant>
|
||||||
|
<lookup name="label" type="GtkLabel">label</lookup>
|
||||||
|
<closure type="gint" function="callback_function"></closure>
|
||||||
|
<bind name="label">
|
||||||
|
<lookup name="default-width">win</lookup>
|
||||||
|
</bind>
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
These tags are usually used for GtkBuilderListItemFactory.
|
These tags are usually used for GtkBuilderListItemFactory.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~xml
|
~~~xml
|
||||||
<interface>
|
<interface>
|
||||||
<template class="GtkListItem">
|
<template class="GtkListItem">
|
||||||
<property name="child">
|
<property name="child">
|
||||||
<object class="GtkLabel">
|
<object class="GtkLabel">
|
||||||
<binding name="label">
|
<binding name="label">
|
||||||
<lookup name="name" type="string">
|
<lookup name="string" type="GtkStringObject">
|
||||||
<lookup name="item">GtkListItem</lookup>
|
<lookup name="item">GtkListItem</lookup>
|
||||||
</lookup>
|
</lookup>
|
||||||
</binding>
|
</binding>
|
||||||
|
@ -407,15 +488,31 @@ These tags are usually used for GtkBuilderListItemFactory.
|
||||||
</template>
|
</template>
|
||||||
</interface>
|
</interface>
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.xml}
|
||||||
|
<interface>
|
||||||
|
<template class="GtkListItem">
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<binding name="label">
|
||||||
|
<lookup name="string" type="GtkStringObject">
|
||||||
|
<lookup name="item">GtkListItem</lookup>
|
||||||
|
</lookup>
|
||||||
|
</binding>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
|
GtkBuilderListItemFactory uses GtkBuilder to extends the GtkListItem with the XML data.
|
||||||
|
|
||||||
In the xml file above, "GtkListItem" is an instance of the GtkListItem template.
|
In the xml file above, "GtkListItem" is an instance of the GtkListItem template.
|
||||||
It is the 'this' object given to the expressions.
|
It is the 'this' object given to the expressions.
|
||||||
(The information is in the [GTK Development Blog](https://blog.gtk.org/2020/09/)).
|
(The information is in the [GTK Development Blog](https://blog.gtk.org/2020/09/)).
|
||||||
|
|
||||||
GtkBuilderListItemFactory uses GtkBuilder to build the XML data.
|
GtkBuilder calls `gtk_expression_bind` function when it finds a binding tag.
|
||||||
It sets the current object of the GtkBuilder to the GtkListItem instance.
|
|
||||||
|
|
||||||
GtkBuilder calls `gtk_expression_bind` function in the binding tag analysis.
|
|
||||||
The function sets the 'this' object like this:
|
The function sets the 'this' object like this:
|
||||||
|
|
||||||
1. If the binding tag has object attribute, the object will be the 'this' object.
|
1. If the binding tag has object attribute, the object will be the 'this' object.
|
||||||
|
@ -466,11 +563,12 @@ String duplication is necessary.
|
||||||
|
|
||||||
The C source file is very simple because almost everything is done in the ui file.
|
The C source file is very simple because almost everything is done in the ui file.
|
||||||
|
|
||||||
### Conversion between GValues
|
## Conversion between GValues
|
||||||
|
|
||||||
If you bind different type properties, type conversion is automatically done.
|
If you bind different type properties, type conversion is automatically done.
|
||||||
Suppose a label property (string) is bound to default-width property (int).
|
Suppose a label property (string) is bound to default-width property (int).
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~xml
|
~~~xml
|
||||||
<object class="GtkLabel">
|
<object class="GtkLabel">
|
||||||
<binding name="label">
|
<binding name="label">
|
||||||
|
@ -480,6 +578,17 @@ Suppose a label property (string) is bound to default-width property (int).
|
||||||
</binding>
|
</binding>
|
||||||
</object>
|
</object>
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
|
~~~{.xml}
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<binding name="label">
|
||||||
|
<lookup name="default-width">
|
||||||
|
win
|
||||||
|
</lookup>
|
||||||
|
</binding>
|
||||||
|
</object>
|
||||||
|
~~~
|
||||||
|
@@@end
|
||||||
|
|
||||||
The expression created by the lookup tag returns a int type GValue.
|
The expression created by the lookup tag returns a int type GValue.
|
||||||
On the other hand "label" property holds a string type GValue.
|
On the other hand "label" property holds a string type GValue.
|
||||||
|
@ -487,3 +596,23 @@ When a GValue is copied to another GValue, the type is automatically converted i
|
||||||
If the current width is 100, an int `100` is converted to a string `"100"`.
|
If the current width is 100, an int `100` is converted to a string `"100"`.
|
||||||
|
|
||||||
If you use `g_object_get` and `g_object_set` to copy properties, the value is automatically converted.
|
If you use `g_object_get` and `g_object_set` to copy properties, the value is automatically converted.
|
||||||
|
|
||||||
|
## Meson.build
|
||||||
|
|
||||||
|
The source files are in `src/expression` directory.
|
||||||
|
You can build all the files at once.
|
||||||
|
|
||||||
|
~~~
|
||||||
|
$ cd src/expression
|
||||||
|
$ meson setup _build
|
||||||
|
$ ninja -C _build
|
||||||
|
~~~
|
||||||
|
|
||||||
|
For example, if you want to run "exp", which is the executable file from "exp.c", type `_build/exp`.
|
||||||
|
You can run other programs as well.
|
||||||
|
|
||||||
|
The file `meson.build` is as follows.
|
||||||
|
|
||||||
|
@@@include
|
||||||
|
expression/meson.build
|
||||||
|
@@@
|
||||||
|
|
|
@ -60,9 +60,9 @@ This is the title on the header of the column.
|
||||||
- 32: Sets the "expand" property to TRUE to allow the column to expand as much as possible.
|
- 32: Sets the "expand" property to TRUE to allow the column to expand as much as possible.
|
||||||
(See the image above).
|
(See the image above).
|
||||||
- 33- 69: Sets the "factory" property to GtkBuilderListItemFactory.
|
- 33- 69: Sets the "factory" property to GtkBuilderListItemFactory.
|
||||||
The factory has "bytes" property which holds a ui string to define a template to build GtkListItem composite widget.
|
The factory has "bytes" property which holds a ui string to define a template to extend GtkListItem class.
|
||||||
The CDATA section (line 36-66) is the ui string to put into the "bytes" property.
|
The CDATA section (line 36-66) is the ui string to put into the "bytes" property.
|
||||||
The contents are the same as the ui file `factory_list.ui` in the section 27.
|
The contents are the same as the ui file `factory_list.ui` in the section 30.
|
||||||
- 70-77: Sets the "sorter" property to GtkStringSorter object.
|
- 70-77: Sets the "sorter" property to GtkStringSorter object.
|
||||||
This object provides a sorter that compares strings.
|
This object provides a sorter that compares strings.
|
||||||
It has "expression" property.
|
It has "expression" property.
|
||||||
|
@ -196,7 +196,8 @@ All the source files are in [`src/column`](column) directory.
|
||||||
Change your current directory to the directory and type the following.
|
Change your current directory to the directory and type the following.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ meson _build
|
$ cd src/colomn
|
||||||
|
$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/column
|
$ _build/column
|
||||||
~~~
|
~~~
|
||||||
|
|
158
src/sec33.src.md
158
src/sec33.src.md
|
@ -6,23 +6,14 @@ GtkBuilderlistItemFactory is convenient when GtkListView just shows the contents
|
||||||
Its binding direction is always from an item of a list to a child of GtkListItem.
|
Its binding direction is always from an item of a list to a child of GtkListItem.
|
||||||
|
|
||||||
When it comes to dynamic connection, it's not enough.
|
When it comes to dynamic connection, it's not enough.
|
||||||
For example, you want to edit the contents of a list.
|
For example, suppose you want to edit the contents of a list.
|
||||||
You set a child of GtkListItem to a GtkText instance so a user can edit a text with it.
|
You set a child of GtkListItem to a GtkText instance so a user can edit a text with it.
|
||||||
You need to bind an item in the list with the buffer of the GtkText.
|
You need to bind an item in the list with the buffer of the GtkText.
|
||||||
The direction is opposite from the one with GtkBuilderListItemFactory.
|
The direction is opposite from the one with GtkBuilderListItemFactory.
|
||||||
It is from the GtkText instance to the item in the list.
|
It is from the GtkText instance to the item in the list.
|
||||||
You can implement this with GtkSignalListItemFactory, which is more flexible than GtkBuilderListItemFactory.
|
You can implement this with GtkSignalListItemFactory, which is more flexible than GtkBuilderListItemFactory.
|
||||||
|
|
||||||
Two things are shown in this section.
|
This section shows just some parts of the source file `listeditor.c`.
|
||||||
|
|
||||||
- Binding from a child of a GtkListItem instance to an item of a list.
|
|
||||||
- Access a child of GtkListItem dynamically.
|
|
||||||
This direction is the same as the one with GtkBulderListItemFactory.
|
|
||||||
But GtkBulderListItemFactory uses GtkExpression from the item property of the GtkListItem.
|
|
||||||
So, it updates its child widget only when the item property changes.
|
|
||||||
In this example the child reflects the change in the same item in the list dynamically.
|
|
||||||
|
|
||||||
This section shows just a part of the source file `listeditor.c`.
|
|
||||||
If you want to see the whole codes, see `src/listeditor` directory of the [Gtk4 tutorial repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
If you want to see the whole codes, see `src/listeditor` directory of the [Gtk4 tutorial repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
||||||
|
|
||||||
## A list editor
|
## A list editor
|
||||||
|
@ -33,7 +24,7 @@ It reads a text file line by line.
|
||||||
Each line is an item of the list.
|
Each line is an item of the list.
|
||||||
The list is displayed with GtkColumnView.
|
The list is displayed with GtkColumnView.
|
||||||
There are two columns.
|
There are two columns.
|
||||||
The one is a button, which makes the line be a current line.
|
The one is a button, which shows if the line is a current line.
|
||||||
If the line is the current line, the button is colored with red.
|
If the line is the current line, the button is colored with red.
|
||||||
The other is a string which is the contents of the corresponding item of the list.
|
The other is a string which is the contents of the corresponding item of the list.
|
||||||
|
|
||||||
|
@ -47,18 +38,18 @@ You can compile end execute it as follows.
|
||||||
- Type the following on your commandline.
|
- Type the following on your commandline.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ meson _build
|
$ meson setup _build
|
||||||
$ ninja -C _build
|
$ ninja -C _build
|
||||||
$ _build/listeditor
|
$ _build/listeditor
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- Append button: appends a line after the current line, or at the last line if no current line exists.
|
- Append button: appends a line after the current line, or at the last line if no current line exists.
|
||||||
- Insert button: inserts a line before the current line.
|
- Insert button: inserts a line before the current line, or at the top line if no current line exists.
|
||||||
- Remove button: removes a current line.
|
- Remove button: removes a current line.
|
||||||
- Read button: reads a file.
|
- Read button: reads a file.
|
||||||
- Write button: writes the contents to a file.
|
- Write button: writes the contents to a file.
|
||||||
- close button: close the contents.
|
- close button: closes the contents.
|
||||||
- quit button: quit the application.
|
- quit button: quits the application.
|
||||||
- Button on the select column: makes the line current.
|
- Button on the select column: makes the line current.
|
||||||
- String column: GtkText. You can edit a string in the field.
|
- String column: GtkText. You can edit a string in the field.
|
||||||
|
|
||||||
|
@ -69,7 +60,7 @@ The file name is shown at the right of the write button.
|
||||||
|
|
||||||
The second column (GtkColumnViewColumn) sets its factory property to GtkSignalListItemFactory.
|
The second column (GtkColumnViewColumn) sets its factory property to GtkSignalListItemFactory.
|
||||||
It uses three signals setup, bind and unbind.
|
It uses three signals setup, bind and unbind.
|
||||||
The following is their sgnal handlers.
|
The following shows the signal handlers.
|
||||||
|
|
||||||
@@@include
|
@@@include
|
||||||
listeditor/listeditor.c setup2_cb bind2_cb unbind2_cb
|
listeditor/listeditor.c setup2_cb bind2_cb unbind2_cb
|
||||||
|
@ -84,17 +75,13 @@ So, teardown signal handler isn't necessary.
|
||||||
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 string data which is the content of the line.
|
||||||
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.
|
|
||||||
The other is `string` which is a content of the line.
|
|
||||||
- 10-11: `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.
|
||||||
And `buffer` is a GtkTextBuffer instance of the `text`.
|
And `buffer` is a GtkEntryBuffer instance of the `text`.
|
||||||
- 12: The LeData instance `data` is an item pointed by the `listitem`.
|
- 12: The LeData instance `data` is an item pointed by the `listitem`.
|
||||||
- 15-16: Sets the text of `text` 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 still 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 doesn't need to free the string.
|
||||||
- 18: `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`).
|
||||||
|
@ -107,14 +94,19 @@ 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.
|
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.
|
||||||
- 22-28: `unbind2_cb` is a unbind signal handler.
|
- 22-29: `unbind2_cb` is a unbind signal handler.
|
||||||
- 24: Retrieves the `bind` instance from the table in the `listitem` instance.
|
- 24: Retrieves the `bind` instance from the table in the `listitem` instance.
|
||||||
- 26: Unbind the binding.
|
- 26-27: Unbind the binding.
|
||||||
- 27: Removes the value corresponds to the "bind" key.
|
- 28: 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.
|
||||||
|
|
||||||
|
If it is impossible to use `g_object_bind_property`, use a notify signal on the GtkEntryBuffer instance.
|
||||||
|
You can use "deleted-text" and "inserted-text" signal instead.
|
||||||
|
The handler of the signals above copies the text in the GtkEntryBuffer instance to the LeData string.
|
||||||
|
Connect the notify signal handler in `bind2_cb` and disconnect it in `unbind2_cb`.
|
||||||
|
|
||||||
## Change the cell of GtkColumnView dynamically
|
## Change the cell of GtkColumnView dynamically
|
||||||
|
|
||||||
Next topic is to change the GtkColumnView (or GtkListView) cells dynamically.
|
Next topic is to change the GtkColumnView (or GtkListView) cells dynamically.
|
||||||
|
@ -139,85 +131,79 @@ The current line doesn't need to be on the display.
|
||||||
It is possible to be on the line out of the Window (GtkScrolledWindow).
|
It is possible to be on the line out of the Window (GtkScrolledWindow).
|
||||||
Actually, the program doesn't use GtkSingleSelection.
|
Actually, the program doesn't use GtkSingleSelection.
|
||||||
|
|
||||||
It is necessary to know the corresponding GtkListItem instance from the item in the list.
|
The LeWindow instance has two instance variables for recording the current line.
|
||||||
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.
|
- `win->position`: An int type variable. It is the position of the current line. It is zero-based. If no current line exists, it is -1.
|
||||||
Therefore, items (LeData) in the list always know the GtkListItem.
|
- `win->current_button`: A variable points the button, located at the first column, on the current line. If no current line exists, it is NULL.
|
||||||
If there's no GtkListItem bound to the item, NULL is assigned.
|
|
||||||
|
If the current line moves, the following two functions are called.
|
||||||
|
They updates the two varables.
|
||||||
|
|
||||||
@@@include
|
@@@include
|
||||||
listeditor/listeditor.c select_cb setup1_cb bind1_cb unbind1_cb
|
listeditor/listeditor.c update_current_position update_current_button
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
- 8-14: `setup1_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
The varable `win->position_label` points a GtkLabel instance.
|
||||||
This factory is inserted to the factory property of the first GtkColumnViewColumn.
|
The label shows the current line position.
|
||||||
|
|
||||||
|
The current button has CSS "current" class.
|
||||||
|
The button is colored red through the CSS "button.current {background: red;}".
|
||||||
|
|
||||||
|
The order of the call for these two functions is important.
|
||||||
|
The first function, which updates the position, is usually called first.
|
||||||
|
After that, a new line is appended or inserted.
|
||||||
|
Then, the second function is called.
|
||||||
|
|
||||||
|
The following functions call the two functions above.
|
||||||
|
Be careful about the order of the call.
|
||||||
|
|
||||||
|
@@@include
|
||||||
|
listeditor/listeditor.c select_cb setup1_cb bind1_cb
|
||||||
|
@@@
|
||||||
|
|
||||||
|
- 1-7: `select_cb` is a "clicked" signal handler.
|
||||||
|
The handler just calls the two functions and update the position and button.
|
||||||
|
- 9-15: `setup1_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
||||||
It sets the child of `listitem` to a 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 the 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.
|
- 17-24: `bind1_cb` is a bind signal handler.
|
||||||
LeWindow is defined in `listeditor.c`.
|
Usually, the position moves before this handler is called.
|
||||||
It's a child class of GtkApplicationWindow.
|
If the item is on the current line, the button is updated.
|
||||||
The handler just calls the `update_current` function.
|
No unbind handler is necessary.
|
||||||
The function will be explained later.
|
|
||||||
- 16-31: `bind1_cb` is a bind signal handler.
|
When a line is added, the current position is updated in advance.
|
||||||
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.
|
|
||||||
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.
|
|
||||||
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).
|
|
||||||
Otherwise bad things will happen.
|
|
||||||
|
|
||||||
@@@include
|
@@@include
|
||||||
listeditor/listeditor.c update_current
|
listeditor/listeditor.c app_cb ins_cb
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
The function `update_current` does several things.
|
When a line is removed, the current position becomes -1 and no button is current.
|
||||||
|
|
||||||
- It has two parameters.
|
@@@include
|
||||||
The first one is `win`, which is an instance of LeWindow class.
|
listeditor/listeditor.c rm_cb
|
||||||
It has some elements.
|
@@@
|
||||||
- win->position: an Integer. it is the current position. If no current line exists, it is -1.
|
|
||||||
- win->position_label: GtkLabel. It shows the current position.
|
|
||||||
- The second parameter is `new`, which is the new current position.
|
|
||||||
At the beginning of the function, win->position points the old position.
|
|
||||||
- 10-16: Update the text of GtkLabel.
|
|
||||||
- 18-26: If the old position (win->position) is not negative, the current line exists.
|
|
||||||
It gets a GtkListItem instance via the item (LeData) of the list.
|
|
||||||
And it gets the GtkButton instance which is the child of the GtkListItem.
|
|
||||||
It clears the "css-classes" property of the button.
|
|
||||||
- 27: Updates win->position.
|
|
||||||
- 28-36: If the new position is not negative (It's possible to be negative when the current line has been removed), the current line exists.
|
|
||||||
It sets the "css-classes" property of the button to `{"current", NULL}`.
|
|
||||||
It is a NULL-terminated array of strings.
|
|
||||||
Each string is a CSS class.
|
|
||||||
Now the button has "current" style class.
|
|
||||||
|
|
||||||
The color of buttons are determined by the "background" CSS style.
|
The color of buttons are determined by the "background" CSS style.
|
||||||
The following CSS is applied to the default GdkDisplay in advance (in the startup handler of the application).
|
The following CSS node is a bit complicated.
|
||||||
|
CSS node `column view` has `listview` child node.
|
||||||
|
It covers the rows in the GtkColumnView.
|
||||||
|
The `listview` node is the same as the one for GtkListView.
|
||||||
|
It has `row` child node, which is for each child widget.
|
||||||
|
Therefore, the following node corresponds buttons on the GtkColumnView widget.
|
||||||
|
In addition, it is applied to the "current" class.
|
||||||
|
|
||||||
|
@@@if gfm
|
||||||
~~~css
|
~~~css
|
||||||
columnview listview row button.current {background: red;}
|
columnview listview row button.current {background: red;}
|
||||||
~~~
|
~~~
|
||||||
|
@@@else
|
||||||
The selectors "columnview listview row" is needed before "button" selector.
|
~~~{.css}
|
||||||
Otherwise the buttons in the GtkColumnview won't be found.
|
columnview listview row button.current {background: red;}
|
||||||
The button selector has "current" class.
|
~~~
|
||||||
So, the only "current" class button is colored with red.
|
@@@end
|
||||||
Other buttons are not colored, which means they are white.
|
|
||||||
|
|
||||||
## Gtk\_widget\_dispose\_template function
|
|
||||||
|
|
||||||
The function `gtk_widget_dispose_template` clears the template children for the given widget.
|
|
||||||
This is the opposite of `gtk_widget_init_template()`.
|
|
||||||
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.
|
|
||||||
|
|
||||||
## A waring from GtkText
|
## A waring from GtkText
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue