Gtk4-tutorial/docs/sec21.html
2023-01-03 15:30:06 +09:00

1073 lines
112 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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="sec20.html">Prev: section20</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sec22.html">Next: section22</a>
</li>
</ul>
</div>
</div>
</nav>
<h1 id="template-xml-and-composite-widget">Template XML and composite
widget</h1>
<p>The tfe program in the previous section is not so good because many
things are crammed into <code>tfepplication.c</code>. And many static
variables in <code>tfepplication.c</code>. The file
<code>tfeapplication.c</code> should be divided into several files.</p>
<ul>
<li><code>tfeapplication.c</code> only has codes related to the
application.</li>
<li>A file for the main window</li>
<li>A file for a preference dialog</li>
<li>A file for an alert dialog</li>
</ul>
<p>The preference dialog is defined by a ui file. And it has GtkBox,
GtkLabel and GtkFontButton in it. Such widget can be defined as a
composite widget. Composite widget is:</p>
<ul>
<li>a child object (not child widget) of a widget. For example, the
preference composite widget is a child object of GtkDialog.</li>
<li>Composite widget can be built from template XML. The widget is
defined with template tag, not object tag.</li>
</ul>
<p>Next subsection shows how to build a preference dialog.</p>
<h2 id="preference-dialog">Preference dialog</h2>
<p>First, write a template XML file.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb1-1"><a href="#cb1-1"></a><span class="fu">&lt;?xml</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> encoding=</span><span class="st">&quot;UTF-8&quot;</span><span class="fu">?&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2"></a>&lt;<span class="kw">interface</span>&gt;</span>
<span id="cb1-3"><a href="#cb1-3"></a> &lt;<span class="kw">template</span><span class="ot"> class=</span><span class="st">&quot;TfePref&quot;</span><span class="ot"> parent=</span><span class="st">&quot;GtkDialog&quot;</span>&gt;</span>
<span id="cb1-4"><a href="#cb1-4"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;title&quot;</span>&gt;Preferences&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-5"><a href="#cb1-5"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;resizable&quot;</span>&gt;FALSE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-6"><a href="#cb1-6"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;modal&quot;</span>&gt;TRUE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-7"><a href="#cb1-7"></a> &lt;<span class="kw">child</span><span class="ot"> internal-child=</span><span class="st">&quot;content_area&quot;</span>&gt;</span>
<span id="cb1-8"><a href="#cb1-8"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkBox&quot;</span><span class="ot"> id=</span><span class="st">&quot;content_area&quot;</span>&gt;</span>
<span id="cb1-9"><a href="#cb1-9"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb1-10"><a href="#cb1-10"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkBox&quot;</span><span class="ot"> id=</span><span class="st">&quot;pref_boxh&quot;</span>&gt;</span>
<span id="cb1-11"><a href="#cb1-11"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;orientation&quot;</span>&gt;GTK_ORIENTATION_HORIZONTAL&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-12"><a href="#cb1-12"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;spacing&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-13"><a href="#cb1-13"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;margin-start&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-14"><a href="#cb1-14"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;margin-end&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-15"><a href="#cb1-15"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;margin-top&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-16"><a href="#cb1-16"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;margin-bottom&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-17"><a href="#cb1-17"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb1-18"><a href="#cb1-18"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkLabel&quot;</span><span class="ot"> id=</span><span class="st">&quot;fontlabel&quot;</span>&gt;</span>
<span id="cb1-19"><a href="#cb1-19"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;label&quot;</span>&gt;Font:&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-20"><a href="#cb1-20"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;xalign&quot;</span>&gt;1&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb1-21"><a href="#cb1-21"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb1-22"><a href="#cb1-22"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb1-23"><a href="#cb1-23"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb1-24"><a href="#cb1-24"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkFontButton&quot;</span><span class="ot"> id=</span><span class="st">&quot;fontbtn&quot;</span>&gt;</span>
<span id="cb1-25"><a href="#cb1-25"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb1-26"><a href="#cb1-26"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb1-27"><a href="#cb1-27"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb1-28"><a href="#cb1-28"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb1-29"><a href="#cb1-29"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb1-30"><a href="#cb1-30"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb1-31"><a href="#cb1-31"></a> &lt;/<span class="kw">template</span>&gt;</span>
<span id="cb1-32"><a href="#cb1-32"></a>&lt;/<span class="kw">interface</span>&gt;</span></code></pre></div>
<p>Template tag specifies a composite widget. The value of a class
attribute is the object name. It is “TfePref”. A parent attribute
specifies the direct parent class of the composite widget. Therefore.
<code>TfePref</code> is a child class of <code>GtkDialog</code>. A
parent attribute is optional. But it is recommended to specify it. Other
lines are the same as before.</p>
<p>The class <code>TfePref</code> is defined like TfeTextView. There are
two files <code>tfepref.h</code> and <code>tfepref.c</code>.</p>
<p>The file <code>tfepref.h</code> defines types and declares public
functions. The definitions are public and open to any C files.</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="pp">#ifndef __TFE_PREF_H__</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="pp">#define __TFE_PREF_H__</span></span>
<span id="cb2-3"><a href="#cb2-3"></a></span>
<span id="cb2-4"><a href="#cb2-4"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb2-5"><a href="#cb2-5"></a></span>
<span id="cb2-6"><a href="#cb2-6"></a><span class="pp">#define TFE_TYPE_PREF tfe_pref_get_type ()</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfePref<span class="op">,</span> tfe_pref<span class="op">,</span> TFE<span class="op">,</span> PREF<span class="op">,</span> GtkDialog<span class="op">)</span></span>
<span id="cb2-8"><a href="#cb2-8"></a></span>
<span id="cb2-9"><a href="#cb2-9"></a>GtkWidget <span class="op">*</span></span>
<span id="cb2-10"><a href="#cb2-10"></a>tfe_pref_new <span class="op">(</span><span class="dt">void</span><span class="op">);</span></span>
<span id="cb2-11"><a href="#cb2-11"></a></span>
<span id="cb2-12"><a href="#cb2-12"></a><span class="pp">#endif </span><span class="co">/* __TFE_PREF_H__ */</span></span></code></pre></div>
<ul>
<li>6: Defines a type <code>TFE_TYPE_PREF</code>, which is a macro
replaced by <code>tfe_pref_get_type ()</code>.</li>
<li>7: The macro <code>G_DECLAER_FINAL_TYPE</code> expands to:
<ul>
<li>The function <code>tfe_pref_get_type ()</code> is declared.</li>
<li>TfePrep type is defined as a typedef of
<code>struct _TfePrep</code>.</li>
<li>TfePrepClass type is defined as a typedef of
<code>struct {GtkDialogClass *parent;}</code>.</li>
<li>Two functions <code>TFE_PREF ()</code> and
<code>TFE_IS_PREF ()</code> is defined.</li>
</ul></li>
<li>9-10: <code>tfe_pref_new</code> creates a new TfePref object.</li>
</ul>
<p>The file <code>tfepref.c</code> includes:</p>
<ul>
<li><code>struct _TfePrep</code> structure</li>
<li><code>G_DEFINE_TYPE</code> macro</li>
<li>Initialize and dispose functions</li>
<li>public functions</li>
</ul>
<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="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="pp">#include </span><span class="im">&quot;tfepref.h&quot;</span></span>
<span id="cb3-3"><a href="#cb3-3"></a></span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="kw">struct</span> _TfePref</span>
<span id="cb3-5"><a href="#cb3-5"></a><span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6"></a> GtkDialog parent<span class="op">;</span></span>
<span id="cb3-7"><a href="#cb3-7"></a> GSettings <span class="op">*</span>settings<span class="op">;</span></span>
<span id="cb3-8"><a href="#cb3-8"></a> GtkFontButton <span class="op">*</span>fontbtn<span class="op">;</span></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="op">};</span></span>
<span id="cb3-10"><a href="#cb3-10"></a></span>
<span id="cb3-11"><a href="#cb3-11"></a>G_DEFINE_TYPE <span class="op">(</span>TfePref<span class="op">,</span> tfe_pref<span class="op">,</span> GTK_TYPE_DIALOG<span class="op">);</span></span>
<span id="cb3-12"><a href="#cb3-12"></a></span>
<span id="cb3-13"><a href="#cb3-13"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb3-14"><a href="#cb3-14"></a>tfe_pref_dispose <span class="op">(</span>GObject <span class="op">*</span>gobject<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-15"><a href="#cb3-15"></a> TfePref <span class="op">*</span>pref <span class="op">=</span> TFE_PREF <span class="op">(</span>gobject<span class="op">);</span></span>
<span id="cb3-16"><a href="#cb3-16"></a></span>
<span id="cb3-17"><a href="#cb3-17"></a> g_clear_object <span class="op">(&amp;</span>pref<span class="op">-&gt;</span>settings<span class="op">);</span></span>
<span id="cb3-18"><a href="#cb3-18"></a> G_OBJECT_CLASS <span class="op">(</span>tfe_pref_parent_class<span class="op">)-&gt;</span>dispose <span class="op">(</span>gobject<span class="op">);</span></span>
<span id="cb3-19"><a href="#cb3-19"></a><span class="op">}</span></span>
<span id="cb3-20"><a href="#cb3-20"></a></span>
<span id="cb3-21"><a href="#cb3-21"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb3-22"><a href="#cb3-22"></a>tfe_pref_init <span class="op">(</span>TfePref <span class="op">*</span>pref<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-23"><a href="#cb3-23"></a> gtk_widget_init_template <span class="op">(</span>GTK_WIDGET <span class="op">(</span>pref<span class="op">));</span></span>
<span id="cb3-24"><a href="#cb3-24"></a> pref<span class="op">-&gt;</span>settings <span class="op">=</span> g_settings_new <span class="op">(</span><span class="st">&quot;com.github.ToshioCP.tfe&quot;</span><span class="op">);</span></span>
<span id="cb3-25"><a href="#cb3-25"></a> g_settings_bind <span class="op">(</span>pref<span class="op">-&gt;</span>settings<span class="op">,</span> <span class="st">&quot;font&quot;</span><span class="op">,</span> pref<span class="op">-&gt;</span>fontbtn<span class="op">,</span> <span class="st">&quot;font&quot;</span><span class="op">,</span> G_SETTINGS_BIND_DEFAULT<span class="op">);</span></span>
<span id="cb3-26"><a href="#cb3-26"></a><span class="op">}</span></span>
<span id="cb3-27"><a href="#cb3-27"></a></span>
<span id="cb3-28"><a href="#cb3-28"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb3-29"><a href="#cb3-29"></a>tfe_pref_class_init <span class="op">(</span>TfePrefClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-30"><a href="#cb3-30"></a> GObjectClass <span class="op">*</span>object_class <span class="op">=</span> G_OBJECT_CLASS <span class="op">(</span>class<span class="op">);</span></span>
<span id="cb3-31"><a href="#cb3-31"></a></span>
<span id="cb3-32"><a href="#cb3-32"></a> object_class<span class="op">-&gt;</span>dispose <span class="op">=</span> tfe_pref_dispose<span class="op">;</span></span>
<span id="cb3-33"><a href="#cb3-33"></a> gtk_widget_class_set_template_from_resource <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> <span class="st">&quot;/com/github/ToshioCP/tfe/tfepref.ui&quot;</span><span class="op">);</span></span>
<span id="cb3-34"><a href="#cb3-34"></a> gtk_widget_class_bind_template_child <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> TfePref<span class="op">,</span> fontbtn<span class="op">);</span></span>
<span id="cb3-35"><a href="#cb3-35"></a><span class="op">}</span></span>
<span id="cb3-36"><a href="#cb3-36"></a></span>
<span id="cb3-37"><a href="#cb3-37"></a>GtkWidget <span class="op">*</span></span>
<span id="cb3-38"><a href="#cb3-38"></a>tfe_pref_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-39"><a href="#cb3-39"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_PREF<span class="op">,</span> NULL<span class="op">));</span></span>
<span id="cb3-40"><a href="#cb3-40"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>4-9: The structure <code>struct _TfePref</code> is defined. Every
TfePref instance has its own data of the structure. The structure has
references to:
<ul>
<li>a GSettings instance</li>
<li>a FontButton instance</li>
</ul></li>
<li>11: <code>G_DEFINE_TYPE</code> macro. The macro expands to:
<ul>
<li>the declaration of the class initialization function
<code>tfe_pref_class_init</code></li>
<li>the declaration of the instance initialization function
<code>tfe_pref_init</code></li>
<li>a static variable <code>tfe_pref_parent_class</code> that points the
parent class (GtkDialogClass) structure.</li>
<li>a definition of <code>tfe_pref_get_type ()</code> function</li>
</ul></li>
<li>13-19: <code>tfe_pref_dispose</code> function. It is called in the
destruction process and releases all the reference to other objects. For
further information about destruction process, refer to <a
href="sec11.html">Section 11</a>.</li>
<li>17: g_clear_object is often used in dispose handlers.
<code>g_clear_object (&amp;pref-&gt;gsettings)</code> does:
<ul>
<li><code>g_object_unref (pref-&gt;gsettings)</code></li>
<li><code>pref-&gt;settings = NULL</code></li>
</ul></li>
<li>21-26: Instance initialization function. The argument
<code>pref</code> points a newly created TfePref instance.</li>
<li>23: The function <code>gtk_widget_init_template</code> creates and
initializes the child widgets. The widgets are created based on the
template which is created in the
<code>gtk_widget_class_set_template_from_resource</code> function.</li>
<li>24: Creates GSettings instance and assigns the pointer to it into
<code>pref-&gt;settings</code>. The instance refers to a GSetting id
<code>com.github.ToshioCP.tfe</code>.</li>
<li>25: Binds the GSettings data <code>font</code> and the
<code>font</code> property of <code>pref-&gt;fontbtn</code>
(GtkFontButton). The element <code>pref-&gt;fontbtn</code> points the
GtkFontButton, which is the instance of <code>fontbtn</code> in the ui
file. The relation was made by the
<code>gtk_widget_class_bind_template_child</code> function.</li>
<li>28-35: Class initialization function.</li>
<li>32: Sets the dispose handler.</li>
<li>33: <code>gtk_widget_class_set_template_from_resource</code>
function associates the description in the XML file
(<code>tfepref.ui</code>) with the widget. At this moment no instance is
created. It just makes the class recognize the structure of the object.
Thats why the top level tag is not <code>&lt;object&gt;</code> but
<code>&lt;template&gt;</code> in the XML file. The instance will be
created in the <code>gtk_widget_init_template</code> function
later.</li>
<li>34: <code>gtk_widget_class_bind_template_child</code> macro binds
the structure member (<code>fontbtn</code> in
<code>struct _TfePref</code>) and the id <code>fontbtn</code> in the XML
file. The two names must be the same. This binding is between the member
and the template (not an instance).</li>
<li>37-40: The function <code>tfe_pref_new</code> creates a TfePref
instance.</li>
</ul>
<p>Now, It is very simple to use this dialog. A caller just creates this
object and shows it.</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>TfePref <span class="op">*</span>pref<span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>pref <span class="op">=</span> tfe_pref_new <span class="op">();</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>gtk_window_set_transient_for <span class="op">(</span>GTK_WINDOW <span class="op">(</span>pref<span class="op">),</span> win<span class="op">);</span> <span class="co">/* win is the main window */</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>pref<span class="op">));</span></span></code></pre></div>
<p>This instance is automatically destroyed when a user clicks on the
close button. Thats all. If you want to show the dialog again, just
create and show it.</p>
<figure>
<img src="image/pref_dialog.png" alt="Preference dialog" />
<figcaption aria-hidden="true">Preference dialog</figcaption>
</figure>
<h2 id="alert-dialog">Alert dialog</h2>
<p>It is almost same as preference dialog.</p>
<p>Its ui file is:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb5-1"><a href="#cb5-1"></a><span class="fu">&lt;?xml</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> encoding=</span><span class="st">&quot;UTF-8&quot;</span><span class="fu">?&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2"></a>&lt;<span class="kw">interface</span>&gt;</span>
<span id="cb5-3"><a href="#cb5-3"></a> &lt;<span class="kw">template</span><span class="ot"> class=</span><span class="st">&quot;TfeAlert&quot;</span><span class="ot"> parent=</span><span class="st">&quot;GtkDialog&quot;</span>&gt;</span>
<span id="cb5-4"><a href="#cb5-4"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;title&quot;</span>&gt;Are you sure?&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-5"><a href="#cb5-5"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;resizable&quot;</span>&gt;FALSE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-6"><a href="#cb5-6"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;modal&quot;</span>&gt;TRUE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-7"><a href="#cb5-7"></a> &lt;<span class="kw">child</span><span class="ot"> internal-child=</span><span class="st">&quot;content_area&quot;</span>&gt;</span>
<span id="cb5-8"><a href="#cb5-8"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkBox&quot;</span>&gt;</span>
<span id="cb5-9"><a href="#cb5-9"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb5-10"><a href="#cb5-10"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkBox&quot;</span>&gt;</span>
<span id="cb5-11"><a href="#cb5-11"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;orientation&quot;</span>&gt;GTK_ORIENTATION_HORIZONTAL&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-12"><a href="#cb5-12"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;spacing&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-13"><a href="#cb5-13"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;margin-start&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-14"><a href="#cb5-14"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;margin-end&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-15"><a href="#cb5-15"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;margin-top&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-16"><a href="#cb5-16"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;margin-bottom&quot;</span>&gt;12&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-17"><a href="#cb5-17"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb5-18"><a href="#cb5-18"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkImage&quot;</span>&gt;</span>
<span id="cb5-19"><a href="#cb5-19"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;icon-name&quot;</span>&gt;dialog-warning&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-20"><a href="#cb5-20"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;icon-size&quot;</span>&gt;GTK_ICON_SIZE_LARGE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-21"><a href="#cb5-21"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb5-22"><a href="#cb5-22"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb5-23"><a href="#cb5-23"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb5-24"><a href="#cb5-24"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkLabel&quot;</span><span class="ot"> id=</span><span class="st">&quot;lb_alert&quot;</span>&gt;</span>
<span id="cb5-25"><a href="#cb5-25"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb5-26"><a href="#cb5-26"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb5-27"><a href="#cb5-27"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb5-28"><a href="#cb5-28"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb5-29"><a href="#cb5-29"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb5-30"><a href="#cb5-30"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb5-31"><a href="#cb5-31"></a> &lt;<span class="kw">child</span><span class="ot"> type=</span><span class="st">&quot;action&quot;</span>&gt;</span>
<span id="cb5-32"><a href="#cb5-32"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkButton&quot;</span><span class="ot"> id=</span><span class="st">&quot;btn_cancel&quot;</span>&gt;</span>
<span id="cb5-33"><a href="#cb5-33"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;label&quot;</span>&gt;Cancel&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-34"><a href="#cb5-34"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb5-35"><a href="#cb5-35"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb5-36"><a href="#cb5-36"></a> &lt;<span class="kw">child</span><span class="ot"> type=</span><span class="st">&quot;action&quot;</span>&gt;</span>
<span id="cb5-37"><a href="#cb5-37"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkButton&quot;</span><span class="ot"> id=</span><span class="st">&quot;btn_accept&quot;</span>&gt;</span>
<span id="cb5-38"><a href="#cb5-38"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;label&quot;</span>&gt;Close&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb5-39"><a href="#cb5-39"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb5-40"><a href="#cb5-40"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb5-41"><a href="#cb5-41"></a> &lt;<span class="kw">action-widgets</span>&gt;</span>
<span id="cb5-42"><a href="#cb5-42"></a> &lt;<span class="kw">action-widget</span><span class="ot"> response=</span><span class="st">&quot;cancel&quot;</span><span class="ot"> default=</span><span class="st">&quot;true&quot;</span>&gt;btn_cancel&lt;/<span class="kw">action-widget</span>&gt;</span>
<span id="cb5-43"><a href="#cb5-43"></a> &lt;<span class="kw">action-widget</span><span class="ot"> response=</span><span class="st">&quot;accept&quot;</span>&gt;btn_accept&lt;/<span class="kw">action-widget</span>&gt;</span>
<span id="cb5-44"><a href="#cb5-44"></a> &lt;/<span class="kw">action-widgets</span>&gt;</span>
<span id="cb5-45"><a href="#cb5-45"></a> &lt;/<span class="kw">template</span>&gt;</span>
<span id="cb5-46"><a href="#cb5-46"></a>&lt;/<span class="kw">interface</span>&gt;</span></code></pre></div>
<p>The header file is:</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="pp">#ifndef __TFE_ALERT_H__</span></span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="pp">#define __TFE_ALERT_H__</span></span>
<span id="cb6-3"><a href="#cb6-3"></a></span>
<span id="cb6-4"><a href="#cb6-4"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb6-5"><a href="#cb6-5"></a></span>
<span id="cb6-6"><a href="#cb6-6"></a><span class="pp">#define TFE_TYPE_ALERT tfe_alert_get_type ()</span></span>
<span id="cb6-7"><a href="#cb6-7"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfeAlert<span class="op">,</span> tfe_alert<span class="op">,</span> TFE<span class="op">,</span> ALERT<span class="op">,</span> GtkDialog<span class="op">)</span></span>
<span id="cb6-8"><a href="#cb6-8"></a></span>
<span id="cb6-9"><a href="#cb6-9"></a><span class="dt">void</span></span>
<span id="cb6-10"><a href="#cb6-10"></a>tfe_alert_set_message <span class="op">(</span>TfeAlert <span class="op">*</span>alert<span class="op">,</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>message<span class="op">);</span></span>
<span id="cb6-11"><a href="#cb6-11"></a></span>
<span id="cb6-12"><a href="#cb6-12"></a><span class="dt">void</span></span>
<span id="cb6-13"><a href="#cb6-13"></a>tfe_alert_set_button_label <span class="op">(</span>TfeAlert <span class="op">*</span>alert<span class="op">,</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>label<span class="op">);</span></span>
<span id="cb6-14"><a href="#cb6-14"></a></span>
<span id="cb6-15"><a href="#cb6-15"></a>GtkWidget <span class="op">*</span></span>
<span id="cb6-16"><a href="#cb6-16"></a>tfe_alert_new <span class="op">(</span><span class="dt">void</span><span class="op">);</span></span>
<span id="cb6-17"><a href="#cb6-17"></a></span>
<span id="cb6-18"><a href="#cb6-18"></a><span class="pp">#endif </span><span class="co">/* __TFE_ALERT_H__ */</span></span></code></pre></div>
<p>There are three public functions. The functions
<code>tfe_alert_set_message</code> and
<code>tfe_alert_set_button_label</code> sets the label and button name
of the alert dialog. For example, if you want to show an alert that the
user tries to close without saving the content, set them like:</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>tfe_alert_set_message <span class="op">(</span>alert<span class="op">,</span> <span class="st">&quot;Contents aren&#39;t saved yet.</span><span class="sc">\n</span><span class="st">Are you sure to close?&quot;</span><span class="op">);</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>tfe_alert_set_button_label <span class="op">(</span>alert<span class="op">,</span> <span class="st">&quot;Close&quot;</span><span class="op">);</span></span></code></pre></div>
<p>The function <code>tfe_alert_new</code> creates a TfeAlert
dialog.</p>
<figure>
<img src="image/alert_dialog.png" alt="Alert dialog" />
<figcaption aria-hidden="true">Alert dialog</figcaption>
</figure>
<p>The C source file is:</p>
<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="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2"></a><span class="pp">#include </span><span class="im">&quot;tfealert.h&quot;</span></span>
<span id="cb8-3"><a href="#cb8-3"></a></span>
<span id="cb8-4"><a href="#cb8-4"></a><span class="kw">struct</span> _TfeAlert</span>
<span id="cb8-5"><a href="#cb8-5"></a><span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6"></a> GtkDialog parent<span class="op">;</span></span>
<span id="cb8-7"><a href="#cb8-7"></a> GtkLabel <span class="op">*</span>lb_alert<span class="op">;</span></span>
<span id="cb8-8"><a href="#cb8-8"></a> GtkButton <span class="op">*</span>btn_accept<span class="op">;</span></span>
<span id="cb8-9"><a href="#cb8-9"></a><span class="op">};</span></span>
<span id="cb8-10"><a href="#cb8-10"></a></span>
<span id="cb8-11"><a href="#cb8-11"></a>G_DEFINE_TYPE <span class="op">(</span>TfeAlert<span class="op">,</span> tfe_alert<span class="op">,</span> GTK_TYPE_DIALOG<span class="op">);</span></span>
<span id="cb8-12"><a href="#cb8-12"></a></span>
<span id="cb8-13"><a href="#cb8-13"></a><span class="dt">void</span></span>
<span id="cb8-14"><a href="#cb8-14"></a>tfe_alert_set_message <span class="op">(</span>TfeAlert <span class="op">*</span>alert<span class="op">,</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>message<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-15"><a href="#cb8-15"></a> gtk_label_set_text <span class="op">(</span>alert<span class="op">-&gt;</span>lb_alert<span class="op">,</span> message<span class="op">);</span></span>
<span id="cb8-16"><a href="#cb8-16"></a><span class="op">}</span></span>
<span id="cb8-17"><a href="#cb8-17"></a></span>
<span id="cb8-18"><a href="#cb8-18"></a><span class="dt">void</span></span>
<span id="cb8-19"><a href="#cb8-19"></a>tfe_alert_set_button_label <span class="op">(</span>TfeAlert <span class="op">*</span>alert<span class="op">,</span> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>label<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-20"><a href="#cb8-20"></a> gtk_button_set_label <span class="op">(</span>alert<span class="op">-&gt;</span>btn_accept<span class="op">,</span> label<span class="op">);</span></span>
<span id="cb8-21"><a href="#cb8-21"></a><span class="op">}</span></span>
<span id="cb8-22"><a href="#cb8-22"></a></span>
<span id="cb8-23"><a href="#cb8-23"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb8-24"><a href="#cb8-24"></a>tfe_alert_init <span class="op">(</span>TfeAlert <span class="op">*</span>alert<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-25"><a href="#cb8-25"></a> gtk_widget_init_template <span class="op">(</span>GTK_WIDGET <span class="op">(</span>alert<span class="op">));</span></span>
<span id="cb8-26"><a href="#cb8-26"></a><span class="op">}</span></span>
<span id="cb8-27"><a href="#cb8-27"></a></span>
<span id="cb8-28"><a href="#cb8-28"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb8-29"><a href="#cb8-29"></a>tfe_alert_class_init <span class="op">(</span>TfeAlertClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-30"><a href="#cb8-30"></a> gtk_widget_class_set_template_from_resource <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> <span class="st">&quot;/com/github/ToshioCP/tfe/tfealert.ui&quot;</span><span class="op">);</span></span>
<span id="cb8-31"><a href="#cb8-31"></a> gtk_widget_class_bind_template_child <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> TfeAlert<span class="op">,</span> lb_alert<span class="op">);</span></span>
<span id="cb8-32"><a href="#cb8-32"></a> gtk_widget_class_bind_template_child <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> TfeAlert<span class="op">,</span> btn_accept<span class="op">);</span></span>
<span id="cb8-33"><a href="#cb8-33"></a><span class="op">}</span></span>
<span id="cb8-34"><a href="#cb8-34"></a></span>
<span id="cb8-35"><a href="#cb8-35"></a>GtkWidget <span class="op">*</span></span>
<span id="cb8-36"><a href="#cb8-36"></a>tfe_alert_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-37"><a href="#cb8-37"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_ALERT<span class="op">,</span> NULL<span class="op">));</span></span>
<span id="cb8-38"><a href="#cb8-38"></a><span class="op">}</span></span></code></pre></div>
<p>The program is almost same as <code>tfepref.c</code>.</p>
<p>The Usage of the alert object is as follows.</p>
<ol type="1">
<li>Write the “response” signal handler.</li>
<li>Create a TfeAlert object.</li>
<li>Connect “response” signal to a handler</li>
<li>Show the dialog</li>
<li>In the signal handler, do something with regard to the response-id
and destroy the dialog.</li>
</ol>
<h2 id="top-level-window">Top-level window</h2>
<p><code>TfeWindow</code> is a child class of GtkApplicationWindow.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb9-1"><a href="#cb9-1"></a><span class="fu">&lt;?xml</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> encoding=</span><span class="st">&quot;UTF-8&quot;</span><span class="fu">?&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2"></a>&lt;<span class="kw">interface</span>&gt;</span>
<span id="cb9-3"><a href="#cb9-3"></a> &lt;<span class="kw">template</span><span class="ot"> class=</span><span class="st">&quot;TfeWindow&quot;</span><span class="ot"> parent=</span><span class="st">&quot;GtkApplicationWindow&quot;</span>&gt;</span>
<span id="cb9-4"><a href="#cb9-4"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;title&quot;</span>&gt;file editor&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-5"><a href="#cb9-5"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;default-width&quot;</span>&gt;600&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-6"><a href="#cb9-6"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;default-height&quot;</span>&gt;400&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-7"><a href="#cb9-7"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-8"><a href="#cb9-8"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkBox&quot;</span><span class="ot"> id=</span><span class="st">&quot;boxv&quot;</span>&gt;</span>
<span id="cb9-9"><a href="#cb9-9"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;orientation&quot;</span>&gt;GTK_ORIENTATION_VERTICAL&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-10"><a href="#cb9-10"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-11"><a href="#cb9-11"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkBox&quot;</span><span class="ot"> id=</span><span class="st">&quot;boxh&quot;</span>&gt;</span>
<span id="cb9-12"><a href="#cb9-12"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;orientation&quot;</span>&gt;GTK_ORIENTATION_HORIZONTAL&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-13"><a href="#cb9-13"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-14"><a href="#cb9-14"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkLabel&quot;</span><span class="ot"> id=</span><span class="st">&quot;dmy1&quot;</span>&gt;</span>
<span id="cb9-15"><a href="#cb9-15"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;width-chars&quot;</span>&gt;10&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-16"><a href="#cb9-16"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-17"><a href="#cb9-17"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-18"><a href="#cb9-18"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-19"><a href="#cb9-19"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkButton&quot;</span><span class="ot"> id=</span><span class="st">&quot;btno&quot;</span>&gt;</span>
<span id="cb9-20"><a href="#cb9-20"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;label&quot;</span>&gt;Open&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-21"><a href="#cb9-21"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;action-name&quot;</span>&gt;win.open&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-22"><a href="#cb9-22"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-23"><a href="#cb9-23"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-24"><a href="#cb9-24"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-25"><a href="#cb9-25"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkButton&quot;</span><span class="ot"> id=</span><span class="st">&quot;btns&quot;</span>&gt;</span>
<span id="cb9-26"><a href="#cb9-26"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;label&quot;</span>&gt;Save&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-27"><a href="#cb9-27"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;action-name&quot;</span>&gt;win.save&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-28"><a href="#cb9-28"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-29"><a href="#cb9-29"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-30"><a href="#cb9-30"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-31"><a href="#cb9-31"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkLabel&quot;</span><span class="ot"> id=</span><span class="st">&quot;dmy2&quot;</span>&gt;</span>
<span id="cb9-32"><a href="#cb9-32"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;hexpand&quot;</span>&gt;TRUE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-33"><a href="#cb9-33"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-34"><a href="#cb9-34"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-35"><a href="#cb9-35"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-36"><a href="#cb9-36"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkButton&quot;</span><span class="ot"> id=</span><span class="st">&quot;btnc&quot;</span>&gt;</span>
<span id="cb9-37"><a href="#cb9-37"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;label&quot;</span>&gt;Close&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-38"><a href="#cb9-38"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;action-name&quot;</span>&gt;win.close&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-39"><a href="#cb9-39"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-40"><a href="#cb9-40"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-41"><a href="#cb9-41"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-42"><a href="#cb9-42"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkMenuButton&quot;</span><span class="ot"> id=</span><span class="st">&quot;btnm&quot;</span>&gt;</span>
<span id="cb9-43"><a href="#cb9-43"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;direction&quot;</span>&gt;down&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-44"><a href="#cb9-44"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;halign&quot;</span>&gt;start&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-45"><a href="#cb9-45"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;icon-name&quot;</span>&gt;open-menu-symbolic&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-46"><a href="#cb9-46"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-47"><a href="#cb9-47"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-48"><a href="#cb9-48"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-49"><a href="#cb9-49"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkLabel&quot;</span><span class="ot"> id=</span><span class="st">&quot;dmy3&quot;</span>&gt;</span>
<span id="cb9-50"><a href="#cb9-50"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;width-chars&quot;</span>&gt;10&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-51"><a href="#cb9-51"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-52"><a href="#cb9-52"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-53"><a href="#cb9-53"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-54"><a href="#cb9-54"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-55"><a href="#cb9-55"></a> &lt;<span class="kw">child</span>&gt;</span>
<span id="cb9-56"><a href="#cb9-56"></a> &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkNotebook&quot;</span><span class="ot"> id=</span><span class="st">&quot;nb&quot;</span>&gt;</span>
<span id="cb9-57"><a href="#cb9-57"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;scrollable&quot;</span>&gt;TRUE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-58"><a href="#cb9-58"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;hexpand&quot;</span>&gt;TRUE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-59"><a href="#cb9-59"></a> &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;vexpand&quot;</span>&gt;TRUE&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb9-60"><a href="#cb9-60"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-61"><a href="#cb9-61"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-62"><a href="#cb9-62"></a> &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb9-63"><a href="#cb9-63"></a> &lt;/<span class="kw">child</span>&gt;</span>
<span id="cb9-64"><a href="#cb9-64"></a> &lt;/<span class="kw">template</span>&gt;</span>
<span id="cb9-65"><a href="#cb9-65"></a>&lt;/<span class="kw">interface</span>&gt;</span></code></pre></div>
<p>This XML file is almost same as before except template tag and
“action-name” property in buttons.</p>
<p>GtkButton implements GtkActionable interface, which has “action-name”
property. If this property is set, GtkButton activates the action when
it is clicked. For example, if an open button is clicked, “win.open”
action will be activated and <code>open_activated</code> handler will be
invoked.</p>
<p>This action is also used by “&lt;Control&gt;o” accelerator (See
<code>tfeapplication.c</code>). If you used “clicked” signal for the
button, you would need its signal handler. Then, there would be two
handlers:</p>
<ul>
<li>a handler for the “clicked” signal on the button</li>
<li>a handler for the “activate” signal on the “win.open” action, to
which “&lt;Control&gt;o” accelerator is connected</li>
</ul>
<p>These two handlers are almost same. It is inefficient. Connecting
buttons to actions is a good way to reduce unnecessary codes.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1"></a><span class="pp">#ifndef __TFE_WINDOW_H__</span></span>
<span id="cb10-2"><a href="#cb10-2"></a><span class="pp">#define __TFE_WINDOW_H__</span></span>
<span id="cb10-3"><a href="#cb10-3"></a></span>
<span id="cb10-4"><a href="#cb10-4"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb10-5"><a href="#cb10-5"></a></span>
<span id="cb10-6"><a href="#cb10-6"></a><span class="pp">#define TFE_TYPE_WINDOW tfe_window_get_type ()</span></span>
<span id="cb10-7"><a href="#cb10-7"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfeWindow<span class="op">,</span> tfe_window<span class="op">,</span> TFE<span class="op">,</span> WINDOW<span class="op">,</span> GtkApplicationWindow<span class="op">)</span></span>
<span id="cb10-8"><a href="#cb10-8"></a></span>
<span id="cb10-9"><a href="#cb10-9"></a><span class="dt">void</span></span>
<span id="cb10-10"><a href="#cb10-10"></a>tfe_window_notebook_page_new <span class="op">(</span>TfeWindow <span class="op">*</span>win<span class="op">);</span></span>
<span id="cb10-11"><a href="#cb10-11"></a></span>
<span id="cb10-12"><a href="#cb10-12"></a><span class="dt">void</span></span>
<span id="cb10-13"><a href="#cb10-13"></a>tfe_window_notebook_page_new_with_files <span class="op">(</span>TfeWindow <span class="op">*</span>win<span class="op">,</span> GFile <span class="op">**</span>files<span class="op">,</span> <span class="dt">int</span> n_files<span class="op">);</span></span>
<span id="cb10-14"><a href="#cb10-14"></a></span>
<span id="cb10-15"><a href="#cb10-15"></a>GtkWidget <span class="op">*</span></span>
<span id="cb10-16"><a href="#cb10-16"></a>tfe_window_new <span class="op">(</span>GtkApplication <span class="op">*</span>app<span class="op">);</span></span>
<span id="cb10-17"><a href="#cb10-17"></a></span>
<span id="cb10-18"><a href="#cb10-18"></a><span class="pp">#endif </span><span class="co">/* __TFE_WINDOW_H__ */</span></span></code></pre></div>
<p>There are three public functions. The function
<code>tfe_window_notebook_page_new</code> creates a new notebook page.
This is a wrapper function for <code>notebook_page_new</code>. It is
called by TfeApplication object. The function
<code>tfe_window_notebook_page_new_with_files</code> creates notebook
pages with a contents read from the given files. The function
<code>tfe_window_new</code> creates a TfeWindow instance.</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2"></a><span class="pp">#include </span><span class="im">&quot;tfewindow.h&quot;</span></span>
<span id="cb11-3"><a href="#cb11-3"></a><span class="pp">#include </span><span class="im">&quot;tfenotebook.h&quot;</span></span>
<span id="cb11-4"><a href="#cb11-4"></a><span class="pp">#include </span><span class="im">&quot;tfepref.h&quot;</span></span>
<span id="cb11-5"><a href="#cb11-5"></a><span class="pp">#include </span><span class="im">&quot;tfealert.h&quot;</span></span>
<span id="cb11-6"><a href="#cb11-6"></a></span>
<span id="cb11-7"><a href="#cb11-7"></a><span class="kw">struct</span> _TfeWindow <span class="op">{</span></span>
<span id="cb11-8"><a href="#cb11-8"></a> GtkApplicationWindow parent<span class="op">;</span></span>
<span id="cb11-9"><a href="#cb11-9"></a> GtkMenuButton <span class="op">*</span>btnm<span class="op">;</span></span>
<span id="cb11-10"><a href="#cb11-10"></a> GtkNotebook <span class="op">*</span>nb<span class="op">;</span></span>
<span id="cb11-11"><a href="#cb11-11"></a> gboolean is_quit<span class="op">;</span></span>
<span id="cb11-12"><a href="#cb11-12"></a><span class="op">};</span></span>
<span id="cb11-13"><a href="#cb11-13"></a></span>
<span id="cb11-14"><a href="#cb11-14"></a>G_DEFINE_TYPE <span class="op">(</span>TfeWindow<span class="op">,</span> tfe_window<span class="op">,</span> GTK_TYPE_APPLICATION_WINDOW<span class="op">);</span></span>
<span id="cb11-15"><a href="#cb11-15"></a></span>
<span id="cb11-16"><a href="#cb11-16"></a><span class="co">/* alert response signal handler */</span></span>
<span id="cb11-17"><a href="#cb11-17"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-18"><a href="#cb11-18"></a>alert_response_cb <span class="op">(</span>GtkDialog <span class="op">*</span>alert<span class="op">,</span> <span class="dt">int</span> response_id<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-19"><a href="#cb11-19"></a> TfeWindow <span class="op">*</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb11-20"><a href="#cb11-20"></a></span>
<span id="cb11-21"><a href="#cb11-21"></a> gtk_window_destroy <span class="op">(</span>GTK_WINDOW <span class="op">(</span>alert<span class="op">));</span></span>
<span id="cb11-22"><a href="#cb11-22"></a> <span class="cf">if</span> <span class="op">(</span>response_id <span class="op">==</span> GTK_RESPONSE_ACCEPT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-23"><a href="#cb11-23"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-&gt;</span>is_quit<span class="op">)</span></span>
<span id="cb11-24"><a href="#cb11-24"></a> gtk_window_destroy<span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
<span id="cb11-25"><a href="#cb11-25"></a> <span class="cf">else</span></span>
<span id="cb11-26"><a href="#cb11-26"></a> notebook_page_close <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">);</span></span>
<span id="cb11-27"><a href="#cb11-27"></a> <span class="op">}</span></span>
<span id="cb11-28"><a href="#cb11-28"></a><span class="op">}</span></span>
<span id="cb11-29"><a href="#cb11-29"></a></span>
<span id="cb11-30"><a href="#cb11-30"></a><span class="dt">static</span> gboolean</span>
<span id="cb11-31"><a href="#cb11-31"></a>close_request_cb <span class="op">(</span>TfeWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-32"><a href="#cb11-32"></a> TfeAlert <span class="op">*</span>alert<span class="op">;</span></span>
<span id="cb11-33"><a href="#cb11-33"></a></span>
<span id="cb11-34"><a href="#cb11-34"></a> <span class="cf">if</span> <span class="op">(</span>has_saved_all <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">)))</span></span>
<span id="cb11-35"><a href="#cb11-35"></a> <span class="cf">return</span> false<span class="op">;</span></span>
<span id="cb11-36"><a href="#cb11-36"></a> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb11-37"><a href="#cb11-37"></a> win<span class="op">-&gt;</span>is_quit <span class="op">=</span> true<span class="op">;</span></span>
<span id="cb11-38"><a href="#cb11-38"></a> alert <span class="op">=</span> TFE_ALERT <span class="op">(</span>tfe_alert_new <span class="op">());</span></span>
<span id="cb11-39"><a href="#cb11-39"></a> gtk_window_set_transient_for <span class="op">(</span>GTK_WINDOW <span class="op">(</span>alert<span class="op">),</span> GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
<span id="cb11-40"><a href="#cb11-40"></a> tfe_alert_set_message <span class="op">(</span>alert<span class="op">,</span> <span class="st">&quot;Contents aren&#39;t saved yet.</span><span class="sc">\n</span><span class="st">Are you sure to quit?&quot;</span><span class="op">);</span></span>
<span id="cb11-41"><a href="#cb11-41"></a> tfe_alert_set_button_label <span class="op">(</span>alert<span class="op">,</span> <span class="st">&quot;Quit&quot;</span><span class="op">);</span></span>
<span id="cb11-42"><a href="#cb11-42"></a> g_signal_connect <span class="op">(</span>GTK_DIALOG <span class="op">(</span>alert<span class="op">),</span> <span class="st">&quot;response&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>alert_response_cb<span class="op">),</span> win<span class="op">);</span></span>
<span id="cb11-43"><a href="#cb11-43"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>alert<span class="op">));</span></span>
<span id="cb11-44"><a href="#cb11-44"></a> <span class="cf">return</span> true<span class="op">;</span></span>
<span id="cb11-45"><a href="#cb11-45"></a> <span class="op">}</span></span>
<span id="cb11-46"><a href="#cb11-46"></a><span class="op">}</span></span>
<span id="cb11-47"><a href="#cb11-47"></a></span>
<span id="cb11-48"><a href="#cb11-48"></a><span class="co">/* ----- action activated handlers ----- */</span></span>
<span id="cb11-49"><a href="#cb11-49"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-50"><a href="#cb11-50"></a>open_activated <span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-51"><a href="#cb11-51"></a> TfeWindow <span class="op">*</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb11-52"><a href="#cb11-52"></a></span>
<span id="cb11-53"><a href="#cb11-53"></a> notebook_page_open <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">));</span></span>
<span id="cb11-54"><a href="#cb11-54"></a><span class="op">}</span></span>
<span id="cb11-55"><a href="#cb11-55"></a></span>
<span id="cb11-56"><a href="#cb11-56"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-57"><a href="#cb11-57"></a>save_activated <span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-58"><a href="#cb11-58"></a> TfeWindow <span class="op">*</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb11-59"><a href="#cb11-59"></a></span>
<span id="cb11-60"><a href="#cb11-60"></a> notebook_page_save <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">));</span></span>
<span id="cb11-61"><a href="#cb11-61"></a><span class="op">}</span></span>
<span id="cb11-62"><a href="#cb11-62"></a></span>
<span id="cb11-63"><a href="#cb11-63"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-64"><a href="#cb11-64"></a>close_activated <span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-65"><a href="#cb11-65"></a> TfeWindow <span class="op">*</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb11-66"><a href="#cb11-66"></a> TfeAlert <span class="op">*</span>alert<span class="op">;</span></span>
<span id="cb11-67"><a href="#cb11-67"></a></span>
<span id="cb11-68"><a href="#cb11-68"></a> <span class="cf">if</span> <span class="op">(</span>has_saved <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">))</span></span>
<span id="cb11-69"><a href="#cb11-69"></a> notebook_page_close <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">);</span></span>
<span id="cb11-70"><a href="#cb11-70"></a> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb11-71"><a href="#cb11-71"></a> win<span class="op">-&gt;</span>is_quit <span class="op">=</span> false<span class="op">;</span></span>
<span id="cb11-72"><a href="#cb11-72"></a> alert <span class="op">=</span> TFE_ALERT <span class="op">(</span>tfe_alert_new <span class="op">());</span></span>
<span id="cb11-73"><a href="#cb11-73"></a> gtk_window_set_transient_for <span class="op">(</span>GTK_WINDOW <span class="op">(</span>alert<span class="op">),</span> GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
<span id="cb11-74"><a href="#cb11-74"></a> tfe_alert_set_message <span class="op">(</span>alert<span class="op">,</span> <span class="st">&quot;Contents aren&#39;t saved yet.</span><span class="sc">\n</span><span class="st">Are you sure to close?&quot;</span><span class="op">);</span></span>
<span id="cb11-75"><a href="#cb11-75"></a> tfe_alert_set_button_label <span class="op">(</span>alert<span class="op">,</span> <span class="st">&quot;Close&quot;</span><span class="op">);</span></span>
<span id="cb11-76"><a href="#cb11-76"></a> g_signal_connect <span class="op">(</span>GTK_DIALOG <span class="op">(</span>alert<span class="op">),</span> <span class="st">&quot;response&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>alert_response_cb<span class="op">),</span> win<span class="op">);</span></span>
<span id="cb11-77"><a href="#cb11-77"></a> gtk_widget_show <span class="op">(</span>GTK_WIDGET <span class="op">(</span>alert<span class="op">));</span></span>
<span id="cb11-78"><a href="#cb11-78"></a> <span class="op">}</span></span>
<span id="cb11-79"><a href="#cb11-79"></a><span class="op">}</span></span>
<span id="cb11-80"><a href="#cb11-80"></a></span>
<span id="cb11-81"><a href="#cb11-81"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-82"><a href="#cb11-82"></a>new_activated <span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-83"><a href="#cb11-83"></a> TfeWindow <span class="op">*</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb11-84"><a href="#cb11-84"></a></span>
<span id="cb11-85"><a href="#cb11-85"></a> notebook_page_new <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">));</span></span>
<span id="cb11-86"><a href="#cb11-86"></a><span class="op">}</span></span>
<span id="cb11-87"><a href="#cb11-87"></a></span>
<span id="cb11-88"><a href="#cb11-88"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-89"><a href="#cb11-89"></a>saveas_activated <span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-90"><a href="#cb11-90"></a> TfeWindow <span class="op">*</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb11-91"><a href="#cb11-91"></a></span>
<span id="cb11-92"><a href="#cb11-92"></a> notebook_page_saveas <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">));</span></span>
<span id="cb11-93"><a href="#cb11-93"></a><span class="op">}</span></span>
<span id="cb11-94"><a href="#cb11-94"></a></span>
<span id="cb11-95"><a href="#cb11-95"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-96"><a href="#cb11-96"></a>pref_activated <span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-97"><a href="#cb11-97"></a> TfeWindow <span class="op">*</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb11-98"><a href="#cb11-98"></a> GtkWidget <span class="op">*</span>pref<span class="op">;</span></span>
<span id="cb11-99"><a href="#cb11-99"></a></span>
<span id="cb11-100"><a href="#cb11-100"></a> pref <span class="op">=</span> tfe_pref_new <span class="op">();</span></span>
<span id="cb11-101"><a href="#cb11-101"></a> gtk_window_set_transient_for <span class="op">(</span>GTK_WINDOW <span class="op">(</span>pref<span class="op">),</span> GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
<span id="cb11-102"><a href="#cb11-102"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>pref<span class="op">));</span></span>
<span id="cb11-103"><a href="#cb11-103"></a><span class="op">}</span></span>
<span id="cb11-104"><a href="#cb11-104"></a></span>
<span id="cb11-105"><a href="#cb11-105"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-106"><a href="#cb11-106"></a>close_all_activated <span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-107"><a href="#cb11-107"></a> TfeWindow <span class="op">*</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb11-108"><a href="#cb11-108"></a></span>
<span id="cb11-109"><a href="#cb11-109"></a> <span class="cf">if</span> <span class="op">(</span>close_request_cb <span class="op">(</span>win<span class="op">)</span> <span class="op">==</span> false<span class="op">)</span></span>
<span id="cb11-110"><a href="#cb11-110"></a> gtk_window_destroy <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
<span id="cb11-111"><a href="#cb11-111"></a><span class="op">}</span></span>
<span id="cb11-112"><a href="#cb11-112"></a></span>
<span id="cb11-113"><a href="#cb11-113"></a><span class="co">/* --- public functions --- */</span></span>
<span id="cb11-114"><a href="#cb11-114"></a></span>
<span id="cb11-115"><a href="#cb11-115"></a><span class="dt">void</span></span>
<span id="cb11-116"><a href="#cb11-116"></a>tfe_window_notebook_page_new <span class="op">(</span>TfeWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-117"><a href="#cb11-117"></a> notebook_page_new <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">);</span></span>
<span id="cb11-118"><a href="#cb11-118"></a><span class="op">}</span></span>
<span id="cb11-119"><a href="#cb11-119"></a></span>
<span id="cb11-120"><a href="#cb11-120"></a><span class="dt">void</span></span>
<span id="cb11-121"><a href="#cb11-121"></a>tfe_window_notebook_page_new_with_files <span class="op">(</span>TfeWindow <span class="op">*</span>win<span class="op">,</span> GFile <span class="op">**</span>files<span class="op">,</span> <span class="dt">int</span> n_files<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-122"><a href="#cb11-122"></a> <span class="dt">int</span> i<span class="op">;</span></span>
<span id="cb11-123"><a href="#cb11-123"></a></span>
<span id="cb11-124"><a href="#cb11-124"></a> <span class="cf">for</span> <span class="op">(</span>i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> n_files<span class="op">;</span> i<span class="op">++)</span></span>
<span id="cb11-125"><a href="#cb11-125"></a> notebook_page_new_with_file <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">,</span> files<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb11-126"><a href="#cb11-126"></a> <span class="cf">if</span> <span class="op">(</span>gtk_notebook_get_n_pages <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb11-127"><a href="#cb11-127"></a> notebook_page_new <span class="op">(</span>win<span class="op">-&gt;</span>nb<span class="op">);</span></span>
<span id="cb11-128"><a href="#cb11-128"></a><span class="op">}</span></span>
<span id="cb11-129"><a href="#cb11-129"></a></span>
<span id="cb11-130"><a href="#cb11-130"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-131"><a href="#cb11-131"></a>tfe_window_init <span class="op">(</span>TfeWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-132"><a href="#cb11-132"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
<span id="cb11-133"><a href="#cb11-133"></a> GMenuModel <span class="op">*</span>menu<span class="op">;</span></span>
<span id="cb11-134"><a href="#cb11-134"></a></span>
<span id="cb11-135"><a href="#cb11-135"></a> gtk_widget_init_template <span class="op">(</span>GTK_WIDGET <span class="op">(</span>win<span class="op">));</span></span>
<span id="cb11-136"><a href="#cb11-136"></a></span>
<span id="cb11-137"><a href="#cb11-137"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">&quot;/com/github/ToshioCP/tfe/menu.ui&quot;</span><span class="op">);</span></span>
<span id="cb11-138"><a href="#cb11-138"></a> menu <span class="op">=</span> G_MENU_MODEL <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">&quot;menu&quot;</span><span class="op">));</span></span>
<span id="cb11-139"><a href="#cb11-139"></a> gtk_menu_button_set_menu_model <span class="op">(</span>win<span class="op">-&gt;</span>btnm<span class="op">,</span> menu<span class="op">);</span></span>
<span id="cb11-140"><a href="#cb11-140"></a> g_object_unref<span class="op">(</span>build<span class="op">);</span></span>
<span id="cb11-141"><a href="#cb11-141"></a></span>
<span id="cb11-142"><a href="#cb11-142"></a><span class="co">/* ----- action ----- */</span></span>
<span id="cb11-143"><a href="#cb11-143"></a> <span class="dt">const</span> GActionEntry win_entries<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb11-144"><a href="#cb11-144"></a> <span class="op">{</span> <span class="st">&quot;open&quot;</span><span class="op">,</span> open_activated<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL <span class="op">},</span></span>
<span id="cb11-145"><a href="#cb11-145"></a> <span class="op">{</span> <span class="st">&quot;save&quot;</span><span class="op">,</span> save_activated<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL <span class="op">},</span></span>
<span id="cb11-146"><a href="#cb11-146"></a> <span class="op">{</span> <span class="st">&quot;close&quot;</span><span class="op">,</span> close_activated<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL <span class="op">},</span></span>
<span id="cb11-147"><a href="#cb11-147"></a> <span class="op">{</span> <span class="st">&quot;new&quot;</span><span class="op">,</span> new_activated<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL <span class="op">},</span></span>
<span id="cb11-148"><a href="#cb11-148"></a> <span class="op">{</span> <span class="st">&quot;saveas&quot;</span><span class="op">,</span> saveas_activated<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL <span class="op">},</span></span>
<span id="cb11-149"><a href="#cb11-149"></a> <span class="op">{</span> <span class="st">&quot;pref&quot;</span><span class="op">,</span> pref_activated<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL <span class="op">},</span></span>
<span id="cb11-150"><a href="#cb11-150"></a> <span class="op">{</span> <span class="st">&quot;close-all&quot;</span><span class="op">,</span> close_all_activated<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL <span class="op">}</span></span>
<span id="cb11-151"><a href="#cb11-151"></a> <span class="op">};</span></span>
<span id="cb11-152"><a href="#cb11-152"></a> g_action_map_add_action_entries <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>win<span class="op">),</span> win_entries<span class="op">,</span> G_N_ELEMENTS <span class="op">(</span>win_entries<span class="op">),</span> win<span class="op">);</span></span>
<span id="cb11-153"><a href="#cb11-153"></a></span>
<span id="cb11-154"><a href="#cb11-154"></a> g_signal_connect <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> <span class="st">&quot;close-request&quot;</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="cb11-155"><a href="#cb11-155"></a><span class="op">}</span></span>
<span id="cb11-156"><a href="#cb11-156"></a></span>
<span id="cb11-157"><a href="#cb11-157"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb11-158"><a href="#cb11-158"></a>tfe_window_class_init <span class="op">(</span>TfeWindowClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-159"><a href="#cb11-159"></a> gtk_widget_class_set_template_from_resource <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> <span class="st">&quot;/com/github/ToshioCP/tfe/tfewindow.ui&quot;</span><span class="op">);</span></span>
<span id="cb11-160"><a href="#cb11-160"></a> gtk_widget_class_bind_template_child <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> TfeWindow<span class="op">,</span> btnm<span class="op">);</span></span>
<span id="cb11-161"><a href="#cb11-161"></a> gtk_widget_class_bind_template_child <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> TfeWindow<span class="op">,</span> nb<span class="op">);</span></span>
<span id="cb11-162"><a href="#cb11-162"></a><span class="op">}</span></span>
<span id="cb11-163"><a href="#cb11-163"></a></span>
<span id="cb11-164"><a href="#cb11-164"></a>GtkWidget <span class="op">*</span></span>
<span id="cb11-165"><a href="#cb11-165"></a>tfe_window_new <span class="op">(</span>GtkApplication <span class="op">*</span>app<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-166"><a href="#cb11-166"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_WINDOW<span class="op">,</span> <span class="st">&quot;application&quot;</span><span class="op">,</span> app<span class="op">,</span> NULL<span class="op">));</span></span>
<span id="cb11-167"><a href="#cb11-167"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>7-12: <code>_TfeWindow</code> structure. A TfeWindow instance points
the structure.</li>
<li>14: <code>G_DEFINE_TYPE</code> macro.</li>
<li>17-28: <code>alert_response_cb</code> is a call back function for
the “response” signal of TfeAlert dialog.</li>
<li>21: Destroys the alert dialog.</li>
<li>22-27: If the user has clicked on the accept button, it destroys the
main window or closes the current notebook page.</li>
<li>30-46: A “close-request” signal handler on the TfeWindow. When a
user clicked on the close button (top right x-shaped button), the
handler is called before the window closes. If the handler returns true,
the default handler isnt called and the window doesnt close. If the
handler returns false, the default handler is called and the window
closes.</li>
<li>34: If <code>has_saved_all</code> returns true, the handler returns
false and the window will close. Otherwise, it shows an alert
dialog.</li>
<li>48-111: Handlers of action activated signal. The
<code>user_data</code> is a pointer to the TfeWindow instance.</li>
<li>115-128: Public functions.</li>
<li>130-155: Instance initialization function.</li>
<li>135: The function <code>gtk_widget_init_template</code> creates a
child widgets and initializes them.</li>
<li>137-140: Builds and inserts <code>menu</code>. It is inserted to the
menu button.</li>
<li>143-152: Creates actions and inserts them to the window. The scope
of the actions is “win”.</li>
<li>154: Connects the “close-request” signal and a handler.</li>
<li>157-162: Class initialization function.</li>
<li>159: Sets the composite widget template</li>
<li>160-161: Binds private variables with child class templates.</li>
<li>164-167: <code>tfe_window_new</code>. This function creates
TfeWindow instance.</li>
</ul>
<h2 id="tfeapplication">TfeApplication</h2>
<p>The file <code>tfeaplication.h</code> and
<code>tfeapplication.c</code> are now very simple. The following is the
header file.</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb12-1"><a href="#cb12-1"></a><span class="pp">#pragma once</span></span>
<span id="cb12-2"><a href="#cb12-2"></a></span>
<span id="cb12-3"><a href="#cb12-3"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb12-4"><a href="#cb12-4"></a></span>
<span id="cb12-5"><a href="#cb12-5"></a><span class="pp">#define TFE_TYPE_APPLICATION tfe_application_get_type ()</span></span>
<span id="cb12-6"><a href="#cb12-6"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfeApplication<span class="op">,</span> tfe_application<span class="op">,</span> TFE<span class="op">,</span> APPLICATION<span class="op">,</span> GtkApplication<span class="op">)</span></span>
<span id="cb12-7"><a href="#cb12-7"></a></span>
<span id="cb12-8"><a href="#cb12-8"></a>TfeApplication <span class="op">*</span></span>
<span id="cb12-9"><a href="#cb12-9"></a>tfe_application_new <span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> application_id<span class="op">,</span> GApplicationFlags flags<span class="op">);</span></span></code></pre></div>
<ul>
<li>1: <code>#pragma once</code> isnt an official pre-processor
command, but widely used. It makes the header file be read only
once.</li>
<li>5-6: <code>TFE_TYPE_APPLICATION</code> is defined as the type of
TfeApplication. <code>G_DECLARE_FINAL_TYPE</code> is a macro used in the
header file to define a new object.</li>
<li>8-9: The function <code>tfe_application_new</code> creates a new
TfeApplication instance.</li>
</ul>
<p>The following is <code>tfeapplication.c</code>. It defines the
application and supports:</p>
<ul>
<li>GSettings</li>
<li>CSS</li>
</ul>
<div class="sourceCode" id="cb13"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2"></a><span class="pp">#include </span><span class="im">&quot;tfeapplication.h&quot;</span></span>
<span id="cb13-3"><a href="#cb13-3"></a><span class="pp">#include </span><span class="im">&quot;tfewindow.h&quot;</span></span>
<span id="cb13-4"><a href="#cb13-4"></a><span class="pp">#include </span><span class="im">&quot;pfd2css.h&quot;</span></span>
<span id="cb13-5"><a href="#cb13-5"></a></span>
<span id="cb13-6"><a href="#cb13-6"></a><span class="kw">struct</span> _TfeApplication <span class="op">{</span></span>
<span id="cb13-7"><a href="#cb13-7"></a> GtkApplication parent<span class="op">;</span></span>
<span id="cb13-8"><a href="#cb13-8"></a> TfeWindow <span class="op">*</span>win<span class="op">;</span></span>
<span id="cb13-9"><a href="#cb13-9"></a> GSettings <span class="op">*</span>settings<span class="op">;</span></span>
<span id="cb13-10"><a href="#cb13-10"></a> GtkCssProvider <span class="op">*</span>provider<span class="op">;</span></span>
<span id="cb13-11"><a href="#cb13-11"></a><span class="op">};</span></span>
<span id="cb13-12"><a href="#cb13-12"></a></span>
<span id="cb13-13"><a href="#cb13-13"></a>G_DEFINE_TYPE <span class="op">(</span>TfeApplication<span class="op">,</span> tfe_application<span class="op">,</span> GTK_TYPE_APPLICATION<span class="op">);</span></span>
<span id="cb13-14"><a href="#cb13-14"></a></span>
<span id="cb13-15"><a href="#cb13-15"></a><span class="co">/* gsettings changed::font signal handler */</span></span>
<span id="cb13-16"><a href="#cb13-16"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb13-17"><a href="#cb13-17"></a>changed_font_cb <span class="op">(</span>GSettings <span class="op">*</span>settings<span class="op">,</span> <span class="dt">char</span> <span class="op">*</span>key<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-18"><a href="#cb13-18"></a> TfeApplication <span class="op">*</span>app <span class="op">=</span> TFE_APPLICATION <span class="op">(</span>user_data<span class="op">);</span></span>
<span id="cb13-19"><a href="#cb13-19"></a> <span class="dt">char</span> <span class="op">*</span>font<span class="op">,</span> <span class="op">*</span>s<span class="op">,</span> <span class="op">*</span>css<span class="op">;</span></span>
<span id="cb13-20"><a href="#cb13-20"></a> PangoFontDescription <span class="op">*</span>pango_font_desc<span class="op">;</span></span>
<span id="cb13-21"><a href="#cb13-21"></a></span>
<span id="cb13-22"><a href="#cb13-22"></a> font <span class="op">=</span> g_settings_get_string <span class="op">(</span>app<span class="op">-&gt;</span>settings<span class="op">,</span> <span class="st">&quot;font&quot;</span><span class="op">);</span></span>
<span id="cb13-23"><a href="#cb13-23"></a> pango_font_desc <span class="op">=</span> pango_font_description_from_string <span class="op">(</span>font<span class="op">);</span></span>
<span id="cb13-24"><a href="#cb13-24"></a> g_free <span class="op">(</span>font<span class="op">);</span></span>
<span id="cb13-25"><a href="#cb13-25"></a> s <span class="op">=</span> pfd2css <span class="op">(</span>pango_font_desc<span class="op">);</span> <span class="co">// converts Pango Font Description into CSS style string</span></span>
<span id="cb13-26"><a href="#cb13-26"></a> css <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">&quot;textview {%s}&quot;</span><span class="op">,</span> s<span class="op">);</span></span>
<span id="cb13-27"><a href="#cb13-27"></a> gtk_css_provider_load_from_data <span class="op">(</span>app<span class="op">-&gt;</span>provider<span class="op">,</span> css<span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb13-28"><a href="#cb13-28"></a> g_free <span class="op">(</span>s<span class="op">);</span></span>
<span id="cb13-29"><a href="#cb13-29"></a> g_free <span class="op">(</span>css<span class="op">);</span></span>
<span id="cb13-30"><a href="#cb13-30"></a><span class="op">}</span></span>
<span id="cb13-31"><a href="#cb13-31"></a></span>
<span id="cb13-32"><a href="#cb13-32"></a><span class="co">/* ----- activate, open, startup handlers ----- */</span></span>
<span id="cb13-33"><a href="#cb13-33"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb13-34"><a href="#cb13-34"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-35"><a href="#cb13-35"></a> TfeApplication <span class="op">*</span>app <span class="op">=</span> TFE_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
<span id="cb13-36"><a href="#cb13-36"></a></span>
<span id="cb13-37"><a href="#cb13-37"></a> tfe_window_notebook_page_new <span class="op">(</span>app<span class="op">-&gt;</span>win<span class="op">);</span></span>
<span id="cb13-38"><a href="#cb13-38"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>app<span class="op">-&gt;</span>win<span class="op">));</span></span>
<span id="cb13-39"><a href="#cb13-39"></a><span class="op">}</span></span>
<span id="cb13-40"><a href="#cb13-40"></a></span>
<span id="cb13-41"><a href="#cb13-41"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb13-42"><a href="#cb13-42"></a>app_open <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">,</span> GFile <span class="op">**</span> files<span class="op">,</span> gint n_files<span class="op">,</span> <span class="dt">const</span> gchar <span class="op">*</span>hint<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-43"><a href="#cb13-43"></a> TfeApplication <span class="op">*</span>app <span class="op">=</span> TFE_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
<span id="cb13-44"><a href="#cb13-44"></a></span>
<span id="cb13-45"><a href="#cb13-45"></a> tfe_window_notebook_page_new_with_files <span class="op">(</span>app<span class="op">-&gt;</span>win<span class="op">,</span> files<span class="op">,</span> n_files<span class="op">);</span></span>
<span id="cb13-46"><a href="#cb13-46"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>app<span class="op">-&gt;</span>win<span class="op">));</span></span>
<span id="cb13-47"><a href="#cb13-47"></a><span class="op">}</span></span>
<span id="cb13-48"><a href="#cb13-48"></a></span>
<span id="cb13-49"><a href="#cb13-49"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb13-50"><a href="#cb13-50"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-51"><a href="#cb13-51"></a> TfeApplication <span class="op">*</span>app <span class="op">=</span> TFE_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
<span id="cb13-52"><a href="#cb13-52"></a> GtkCssProvider <span class="op">*</span>provider0<span class="op">;</span></span>
<span id="cb13-53"><a href="#cb13-53"></a> GdkDisplay <span class="op">*</span>display<span class="op">;</span></span>
<span id="cb13-54"><a href="#cb13-54"></a> <span class="dt">int</span> i<span class="op">;</span></span>
<span id="cb13-55"><a href="#cb13-55"></a></span>
<span id="cb13-56"><a href="#cb13-56"></a> app<span class="op">-&gt;</span>win <span class="op">=</span> TFE_WINDOW <span class="op">(</span>tfe_window_new <span class="op">(</span>GTK_APPLICATION <span class="op">(</span>app<span class="op">)));</span></span>
<span id="cb13-57"><a href="#cb13-57"></a> provider0 <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span>
<span id="cb13-58"><a href="#cb13-58"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider0<span class="op">,</span> <span class="st">&quot;textview {padding: 10px;}&quot;</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb13-59"><a href="#cb13-59"></a> display <span class="op">=</span> gdk_display_get_default <span class="op">();</span></span>
<span id="cb13-60"><a href="#cb13-60"></a> gtk_style_context_add_provider_for_display <span class="op">(</span>display<span class="op">,</span> GTK_STYLE_PROVIDER <span class="op">(</span>provider0<span class="op">),</span></span>
<span id="cb13-61"><a href="#cb13-61"></a> GTK_STYLE_PROVIDER_PRIORITY_APPLICATION<span class="op">);</span></span>
<span id="cb13-62"><a href="#cb13-62"></a> g_object_unref <span class="op">(</span>provider0<span class="op">);</span></span>
<span id="cb13-63"><a href="#cb13-63"></a> app<span class="op">-&gt;</span>provider <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span>
<span id="cb13-64"><a href="#cb13-64"></a> gtk_style_context_add_provider_for_display <span class="op">(</span>display<span class="op">,</span> GTK_STYLE_PROVIDER <span class="op">(</span>app<span class="op">-&gt;</span>provider<span class="op">),</span></span>
<span id="cb13-65"><a href="#cb13-65"></a> GTK_STYLE_PROVIDER_PRIORITY_APPLICATION<span class="op">);</span></span>
<span id="cb13-66"><a href="#cb13-66"></a> app<span class="op">-&gt;</span>settings <span class="op">=</span> g_settings_new <span class="op">(</span><span class="st">&quot;com.github.ToshioCP.tfe&quot;</span><span class="op">);</span></span>
<span id="cb13-67"><a href="#cb13-67"></a> g_signal_connect <span class="op">(</span>app<span class="op">-&gt;</span>settings<span class="op">,</span> <span class="st">&quot;changed::font&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>changed_font_cb<span class="op">),</span> app<span class="op">);</span></span>
<span id="cb13-68"><a href="#cb13-68"></a> changed_font_cb<span class="op">(</span>app<span class="op">-&gt;</span>settings<span class="op">,</span> <span class="st">&quot;font&quot;</span><span class="op">,</span> app<span class="op">);</span></span>
<span id="cb13-69"><a href="#cb13-69"></a></span>
<span id="cb13-70"><a href="#cb13-70"></a><span class="co">/* ----- accelerator ----- */</span> </span>
<span id="cb13-71"><a href="#cb13-71"></a> <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb13-72"><a href="#cb13-72"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>action<span class="op">;</span></span>
<span id="cb13-73"><a href="#cb13-73"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>accels<span class="op">[</span><span class="dv">2</span><span class="op">];</span></span>
<span id="cb13-74"><a href="#cb13-74"></a> <span class="op">}</span> action_accels<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb13-75"><a href="#cb13-75"></a> <span class="op">{</span> <span class="st">&quot;win.open&quot;</span><span class="op">,</span> <span class="op">{</span> <span class="st">&quot;&lt;Control&gt;o&quot;</span><span class="op">,</span> NULL <span class="op">}</span> <span class="op">},</span></span>
<span id="cb13-76"><a href="#cb13-76"></a> <span class="op">{</span> <span class="st">&quot;win.save&quot;</span><span class="op">,</span> <span class="op">{</span> <span class="st">&quot;&lt;Control&gt;s&quot;</span><span class="op">,</span> NULL <span class="op">}</span> <span class="op">},</span></span>
<span id="cb13-77"><a href="#cb13-77"></a> <span class="op">{</span> <span class="st">&quot;win.close&quot;</span><span class="op">,</span> <span class="op">{</span> <span class="st">&quot;&lt;Control&gt;w&quot;</span><span class="op">,</span> NULL <span class="op">}</span> <span class="op">},</span></span>
<span id="cb13-78"><a href="#cb13-78"></a> <span class="op">{</span> <span class="st">&quot;win.new&quot;</span><span class="op">,</span> <span class="op">{</span> <span class="st">&quot;&lt;Control&gt;n&quot;</span><span class="op">,</span> NULL <span class="op">}</span> <span class="op">},</span></span>
<span id="cb13-79"><a href="#cb13-79"></a> <span class="op">{</span> <span class="st">&quot;win.saveas&quot;</span><span class="op">,</span> <span class="op">{</span> <span class="st">&quot;&lt;Shift&gt;&lt;Control&gt;s&quot;</span><span class="op">,</span> NULL <span class="op">}</span> <span class="op">},</span></span>
<span id="cb13-80"><a href="#cb13-80"></a> <span class="op">{</span> <span class="st">&quot;win.close-all&quot;</span><span class="op">,</span> <span class="op">{</span> <span class="st">&quot;&lt;Control&gt;q&quot;</span><span class="op">,</span> NULL <span class="op">}</span> <span class="op">},</span></span>
<span id="cb13-81"><a href="#cb13-81"></a> <span class="op">};</span></span>
<span id="cb13-82"><a href="#cb13-82"></a></span>
<span id="cb13-83"><a href="#cb13-83"></a> <span class="cf">for</span> <span class="op">(</span>i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> G_N_ELEMENTS<span class="op">(</span>action_accels<span class="op">);</span> i<span class="op">++)</span></span>
<span id="cb13-84"><a href="#cb13-84"></a> gtk_application_set_accels_for_action<span class="op">(</span>GTK_APPLICATION<span class="op">(</span>app<span class="op">),</span> action_accels<span class="op">[</span>i<span class="op">].</span>action<span class="op">,</span> action_accels<span class="op">[</span>i<span class="op">].</span>accels<span class="op">);</span></span>
<span id="cb13-85"><a href="#cb13-85"></a><span class="op">}</span></span>
<span id="cb13-86"><a href="#cb13-86"></a></span>
<span id="cb13-87"><a href="#cb13-87"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb13-88"><a href="#cb13-88"></a>tfe_application_dispose <span class="op">(</span>GObject <span class="op">*</span>gobject<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-89"><a href="#cb13-89"></a> TfeApplication <span class="op">*</span>app <span class="op">=</span> TFE_APPLICATION <span class="op">(</span>gobject<span class="op">);</span></span>
<span id="cb13-90"><a href="#cb13-90"></a></span>
<span id="cb13-91"><a href="#cb13-91"></a> g_clear_object <span class="op">(&amp;</span>app<span class="op">-&gt;</span>settings<span class="op">);</span></span>
<span id="cb13-92"><a href="#cb13-92"></a> g_clear_object <span class="op">(&amp;</span>app<span class="op">-&gt;</span>provider<span class="op">);</span></span>
<span id="cb13-93"><a href="#cb13-93"></a> G_OBJECT_CLASS <span class="op">(</span>tfe_application_parent_class<span class="op">)-&gt;</span>dispose <span class="op">(</span>gobject<span class="op">);</span></span>
<span id="cb13-94"><a href="#cb13-94"></a><span class="op">}</span></span>
<span id="cb13-95"><a href="#cb13-95"></a></span>
<span id="cb13-96"><a href="#cb13-96"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb13-97"><a href="#cb13-97"></a>tfe_application_init <span class="op">(</span>TfeApplication <span class="op">*</span>app<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-98"><a href="#cb13-98"></a> g_signal_connect <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> <span class="st">&quot;startup&quot;</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="cb13-99"><a href="#cb13-99"></a> g_signal_connect <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> <span class="st">&quot;activate&quot;</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="cb13-100"><a href="#cb13-100"></a> g_signal_connect <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> <span class="st">&quot;open&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_open<span class="op">),</span> NULL<span class="op">);</span></span>
<span id="cb13-101"><a href="#cb13-101"></a><span class="op">}</span></span>
<span id="cb13-102"><a href="#cb13-102"></a></span>
<span id="cb13-103"><a href="#cb13-103"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb13-104"><a href="#cb13-104"></a>tfe_application_class_init <span class="op">(</span>TfeApplicationClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-105"><a href="#cb13-105"></a> GObjectClass <span class="op">*</span>object_class <span class="op">=</span> G_OBJECT_CLASS <span class="op">(</span>class<span class="op">);</span></span>
<span id="cb13-106"><a href="#cb13-106"></a></span>
<span id="cb13-107"><a href="#cb13-107"></a> object_class<span class="op">-&gt;</span>dispose <span class="op">=</span> tfe_application_dispose<span class="op">;</span></span>
<span id="cb13-108"><a href="#cb13-108"></a><span class="op">}</span></span>
<span id="cb13-109"><a href="#cb13-109"></a></span>
<span id="cb13-110"><a href="#cb13-110"></a>TfeApplication <span class="op">*</span></span>
<span id="cb13-111"><a href="#cb13-111"></a>tfe_application_new <span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> application_id<span class="op">,</span> GApplicationFlags flags<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-112"><a href="#cb13-112"></a> <span class="cf">return</span> TFE_APPLICATION <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_APPLICATION<span class="op">,</span> <span class="st">&quot;application-id&quot;</span><span class="op">,</span> application_id<span class="op">,</span> <span class="st">&quot;flags&quot;</span><span class="op">,</span> flags<span class="op">,</span> NULL<span class="op">));</span></span>
<span id="cb13-113"><a href="#cb13-113"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>6-11: Defines <code>_TfeApplication</code> structure. The members
are:
<ul>
<li>win: main window instance</li>
<li>settings: GSettings instance.it is bound to “font” item in the
GSettings</li>
<li>provider: a provider for the font of the textview.</li>
</ul></li>
<li><code>G_DEFINE_TYPE</code> macro.</li>
<li>16-30: <code>changed_font_cb</code> is a handler for “changed::font”
signal on the GSettings instance. The signal name is “changed” and
“font” is a key name. When the valeu of “font” key is changed, the
signal is emitted. So, this handler doesnt directly relate to the font
button, but through the GSettings database. A user changes the font in
the font button =&gt; GSettings font key data is changed =&gt; the
handler is called.</li>
<li>22-24: Retrieves a string from the GSetting database and converts it
into a pango font description.</li>
<li>25-29: Sets the css provider with the font data. The provider has
been inserted to the current display in advance.</li>
<li>33-39: Activate signal handler. It uses
<code>tfe_window_notebook_page_new</code> instead of
<code>notebook_page_new</code>.</li>
<li>41-47: Open signal handler. It just calls
<code>tfe_window_notebook_page_new_with_files</code> and shows the main
window. Be careful that the activate and open handlers dont create a
new window. They just create a new notebook page. Therefore, even if the
second application runs, no new window appears. Just a new notebook page
is inserted to the same main window.</li>
<li>49-85: Startup signal handler.</li>
<li>56: Creates a new window (main window) and assigns it to
<code>app-&gt;win</code>.</li>
<li>57-61: Creates a css provider (<code>provider0</code>). It includes
only the padding data for the textview. The provider is inserted to the
default display.</li>
<li>63-65: Another css provider is created
(<code>app-&gt;provider</code>) and inserted to the default display. It
will include the font data for the textview.</li>
<li>66-68: Creates a new GSettings instance. If the GSettings data is
changed, the “changed” signal is emitted. The signal can have a key name
like “changed::font”. This style (“changed::font”) is called detailed
signal. The detailed signal is emitted only if the font data is changed.
The handler <code>changed_font_cb</code> is called to set the CSS with
the font data. The handler gets the font data from the GSettings data
which is the last font in the previous run of the application.</li>
<li>71-84: Defines accelerators.</li>
<li>87-94: A dispose handler. It releases references to the instances of
GSettings and GtkCssProvider.</li>
<li>96-101: An initialization for the instance. It connects three
signals (activate, open and startup) and their handlers.</li>
<li>183-188: An initialization for the class. It overrides the dispose
class method.</li>
<li>110-113: <code>tfe_application_new</code> creates a new
TfeApplication instance. The parameters are an application-id and
flags.</li>
</ul>
<h2 id="other-files">Other files</h2>
<p>main.c</p>
<div class="sourceCode" id="cb14"><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">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2"></a><span class="pp">#include </span><span class="im">&quot;tfeapplication.h&quot;</span></span>
<span id="cb14-3"><a href="#cb14-3"></a></span>
<span id="cb14-4"><a href="#cb14-4"></a><span class="pp">#define APPLICATION_ID &quot;com.github.ToshioCP.tfe&quot;</span></span>
<span id="cb14-5"><a href="#cb14-5"></a></span>
<span id="cb14-6"><a href="#cb14-6"></a><span class="dt">int</span></span>
<span id="cb14-7"><a href="#cb14-7"></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-8"><a href="#cb14-8"></a> TfeApplication <span class="op">*</span>app<span class="op">;</span></span>
<span id="cb14-9"><a href="#cb14-9"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
<span id="cb14-10"><a href="#cb14-10"></a></span>
<span id="cb14-11"><a href="#cb14-11"></a> app <span class="op">=</span> tfe_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_HANDLES_OPEN<span class="op">);</span></span>
<span id="cb14-12"><a href="#cb14-12"></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-13"><a href="#cb14-13"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
<span id="cb14-14"><a href="#cb14-14"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
<span id="cb14-15"><a href="#cb14-15"></a><span class="op">}</span></span></code></pre></div>
<p>CSS related files <code>pfd2css.h</code> and <code>pfd2css.c</code>
are the same as the previous section.</p>
<p>Resource XML file.</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb15-1"><a href="#cb15-1"></a><span class="fu">&lt;?xml</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> encoding=</span><span class="st">&quot;UTF-8&quot;</span><span class="fu">?&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2"></a>&lt;<span class="kw">gresources</span>&gt;</span>
<span id="cb15-3"><a href="#cb15-3"></a> &lt;<span class="kw">gresource</span><span class="ot"> prefix=</span><span class="st">&quot;/com/github/ToshioCP/tfe&quot;</span>&gt;</span>
<span id="cb15-4"><a href="#cb15-4"></a> &lt;<span class="kw">file</span>&gt;tfewindow.ui&lt;/<span class="kw">file</span>&gt;</span>
<span id="cb15-5"><a href="#cb15-5"></a> &lt;<span class="kw">file</span>&gt;tfepref.ui&lt;/<span class="kw">file</span>&gt;</span>
<span id="cb15-6"><a href="#cb15-6"></a> &lt;<span class="kw">file</span>&gt;tfealert.ui&lt;/<span class="kw">file</span>&gt;</span>
<span id="cb15-7"><a href="#cb15-7"></a> &lt;<span class="kw">file</span>&gt;menu.ui&lt;/<span class="kw">file</span>&gt;</span>
<span id="cb15-8"><a href="#cb15-8"></a> &lt;/<span class="kw">gresource</span>&gt;</span>
<span id="cb15-9"><a href="#cb15-9"></a>&lt;/<span class="kw">gresources</span>&gt;</span></code></pre></div>
<p>GSchema XML file</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb16-1"><a href="#cb16-1"></a><span class="fu">&lt;?xml</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> encoding=</span><span class="st">&quot;UTF-8&quot;</span><span class="fu">?&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2"></a>&lt;<span class="kw">schemalist</span>&gt;</span>
<span id="cb16-3"><a href="#cb16-3"></a> &lt;<span class="kw">schema</span><span class="ot"> path=</span><span class="st">&quot;/com/github/ToshioCP/tfe/&quot;</span><span class="ot"> id=</span><span class="st">&quot;com.github.ToshioCP.tfe&quot;</span>&gt;</span>
<span id="cb16-4"><a href="#cb16-4"></a> &lt;<span class="kw">key</span><span class="ot"> name=</span><span class="st">&quot;font&quot;</span><span class="ot"> type=</span><span class="st">&quot;s&quot;</span>&gt;</span>
<span id="cb16-5"><a href="#cb16-5"></a> &lt;<span class="kw">default</span>&gt;&#39;Monospace 12&#39;&lt;/<span class="kw">default</span>&gt;</span>
<span id="cb16-6"><a href="#cb16-6"></a> &lt;<span class="kw">summary</span>&gt;Font&lt;/<span class="kw">summary</span>&gt;</span>
<span id="cb16-7"><a href="#cb16-7"></a> &lt;<span class="kw">description</span>&gt;A font to be used for textview.&lt;/<span class="kw">description</span>&gt;</span>
<span id="cb16-8"><a href="#cb16-8"></a> &lt;/<span class="kw">key</span>&gt;</span>
<span id="cb16-9"><a href="#cb16-9"></a> &lt;/<span class="kw">schema</span>&gt;</span>
<span id="cb16-10"><a href="#cb16-10"></a>&lt;/<span class="kw">schemalist</span>&gt;</span></code></pre></div>
<p>Meson.build</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb17-1"><a href="#cb17-1"></a>project(&#39;tfe&#39;, &#39;c&#39;)</span>
<span id="cb17-2"><a href="#cb17-2"></a></span>
<span id="cb17-3"><a href="#cb17-3"></a>gtkdep = dependency(&#39;gtk4&#39;)</span>
<span id="cb17-4"><a href="#cb17-4"></a></span>
<span id="cb17-5"><a href="#cb17-5"></a>gnome=import(&#39;gnome&#39;)</span>
<span id="cb17-6"><a href="#cb17-6"></a>resources = gnome.compile_resources(&#39;resources&#39;,&#39;tfe.gresource.xml&#39;)</span>
<span id="cb17-7"><a href="#cb17-7"></a>gnome.compile_schemas(build_by_default: true, depend_files: &#39;com.github.ToshioCP.tfe.gschema.xml&#39;)</span>
<span id="cb17-8"><a href="#cb17-8"></a></span>
<span id="cb17-9"><a href="#cb17-9"></a>sourcefiles=files(&#39;main.c&#39;, &#39;tfeapplication.c&#39;, &#39;tfewindow.c&#39;, &#39;tfenotebook.c&#39;, &#39;tfepref.c&#39;, &#39;tfealert.c&#39;, &#39;pfd2css.c&#39;, &#39;../tfetextview/tfetextview.c&#39;)</span>
<span id="cb17-10"><a href="#cb17-10"></a></span>
<span id="cb17-11"><a href="#cb17-11"></a>executable(&#39;tfe&#39;, sourcefiles, resources, dependencies: gtkdep, export_dynamic: true, install: true)</span>
<span id="cb17-12"><a href="#cb17-12"></a></span>
<span id="cb17-13"><a href="#cb17-13"></a>schema_dir = get_option(&#39;prefix&#39;) / get_option(&#39;datadir&#39;) / &#39;glib-2.0/schemas/&#39;</span>
<span id="cb17-14"><a href="#cb17-14"></a>install_data(&#39;com.github.ToshioCP.tfe.gschema.xml&#39;, install_dir: schema_dir)</span>
<span id="cb17-15"><a href="#cb17-15"></a>gnome.post_install (glib_compile_schemas: true)</span></code></pre></div>
<h2 id="compilation-and-installation.">Compilation and
installation.</h2>
<p>If you want to install it to your local area, use
<code>--prefix=$HOME/.local</code> or <code>--prefix=$HOME</code>
option. If you want to install it to the system area, no option is
needed. It will be installed under <code>/user/local</code>
directory.</p>
<pre><code>$ meson --prefix=$HOME/.local _build
$ ninja -C _build
$ ninja -C _build install</code></pre>
<p>You need root privilege to install it to the system area..</p>
<pre><code>$ meson _build
$ ninja -C _build
$ sudo ninja -C _build install</code></pre>
<p>Source files are in src/tfe7 directory.</p>
<p>Composite widgets give us two advantages.</p>
<ul>
<li>A set of widgets is better than individual widgets because of the
simple coding.</li>
<li>They hold instance variables (members of the object structure) so
static variables are no longer necessary. It makes the program
simpler.</li>
</ul>
<p>We made a very small text editor. You can add features to this
editor. When you add a new feature, be careful about the structure of
the program. Maybe you need to divide a file into several files like
this section. It isnt good to put many things into one file. And it is
important to think about the relationship between source files and
widget structures.</p>
</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>