Gtk4-tutorial/docs/sec10.html
Toshio Sekiya 7b14d03a24 Change the width of HTML contents.
Update the distribution package information.
2023-12-10 16:39:32 +08:00

372 lines
30 KiB
HTML
Raw Permalink 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.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" 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="sec9.html">Prev: section9</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sec11.html">Next: section11</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="row justify-content-center">
<div class="col-xl-10 col-xxl-9">
<h1 id="build-system">Build system</h1>
<h2 id="managing-big-source-files">Managing big source files</h2>
<p>Weve compiled a small editor so far. The program is also small and
not complicated yet. But if it grows bigger, it will be difficult to
maintain. So, we should do the followings now.</p>
<ul>
<li>Weve had only one C source file and put everything in it. We need
to divide it and sort them out.</li>
<li>There are two compilers, <code>gcc</code> and
<code>glib-compile-resources</code>. We should control them by one
building tool.</li>
</ul>
<h2 id="divide-a-c-source-file-into-two-parts.">Divide a C source file
into two parts.</h2>
<p>When you divide C source file into several parts, each file should
contain one thing. For example, our source has two things, the
definition of TfeTextView and functions related to GtkApplication and
GtkApplicationWindow. It is a good idea to separate them into two files,
<code>tfetextview.c</code> and <code>tfe.c</code>.</p>
<ul>
<li><code>tfetextview.c</code> includes the definition and functions of
TfeTextView.</li>
<li><code>tfe.c</code> includes functions like <code>main</code>,
<code>app_activate</code>, <code>app_open</code> and so on, which relate
to GtkApplication and GtkApplicationWindow</li>
</ul>
<p>Now we have three source files, <code>tfetextview.c</code>,
<code>tfe.c</code> and <code>tfe3.ui</code>. The <code>3</code> of
<code>tfe3.ui</code> is like a version number. Managing version with
filenames is one possible idea but it also has a problem. You need to
rewrite filename in each version and it affects to contents of source
files that refer to filenames. So, we should take <code>3</code> away
from the filename.</p>
<p>In <code>tfe.c</code> the function <code>tfe_text_view_new</code> is
invoked to create a TfeTextView instance. But it is defined in
<code>tfetextview.c</code>, not <code>tfe.c</code>. The lack of the
declaration (not definition) of <code>tfe_text_view_new</code> makes
error when <code>tfe.c</code> is compiled. The declaration is necessary
in <code>tfe.c</code>. Those public information is usually written in
header files. It has <code>.h</code> suffix like
<code>tfetextview.h</code>. And header files are included by C source
files. For example, <code>tfetextview.h</code> is included by
<code>tfe.c</code>.</p>
<p>The source files are shown below.</p>
<p><code>tfetextview.h</code></p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2"></a></span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="pp">#define TFE_TYPE_TEXT_VIEW tfe_text_view_get_type ()</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfeTextView<span class="op">,</span> tfe_text_view<span class="op">,</span> TFE<span class="op">,</span> TEXT_VIEW<span class="op">,</span> GtkTextView<span class="op">)</span></span>
<span id="cb1-5"><a href="#cb1-5"></a></span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="dt">void</span></span>
<span id="cb1-7"><a href="#cb1-7"></a>tfe_text_view_set_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">,</span> GFile <span class="op">*</span>f<span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8"></a></span>
<span id="cb1-9"><a href="#cb1-9"></a>GFile <span class="op">*</span></span>
<span id="cb1-10"><a href="#cb1-10"></a>tfe_text_view_get_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">);</span></span>
<span id="cb1-11"><a href="#cb1-11"></a></span>
<span id="cb1-12"><a href="#cb1-12"></a>GtkWidget <span class="op">*</span></span>
<span id="cb1-13"><a href="#cb1-13"></a>tfe_text_view_new <span class="op">(</span><span class="dt">void</span><span class="op">);</span></span></code></pre></div>
<p><code>tfetextview.c</code></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">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="pp">#include </span><span class="im">&quot;tfetextview.h&quot;</span></span>
<span id="cb2-3"><a href="#cb2-3"></a></span>
<span id="cb2-4"><a href="#cb2-4"></a><span class="kw">struct</span> _TfeTextView</span>
<span id="cb2-5"><a href="#cb2-5"></a><span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6"></a> GtkTextView parent<span class="op">;</span></span>
<span id="cb2-7"><a href="#cb2-7"></a> GFile <span class="op">*</span>file<span class="op">;</span></span>
<span id="cb2-8"><a href="#cb2-8"></a><span class="op">};</span></span>
<span id="cb2-9"><a href="#cb2-9"></a></span>
<span id="cb2-10"><a href="#cb2-10"></a>G_DEFINE_TYPE <span class="op">(</span>TfeTextView<span class="op">,</span> tfe_text_view<span class="op">,</span> GTK_TYPE_TEXT_VIEW<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="dt">static</span> <span class="dt">void</span></span>
<span id="cb2-13"><a href="#cb2-13"></a>tfe_text_view_init <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14"></a><span class="op">}</span></span>
<span id="cb2-15"><a href="#cb2-15"></a></span>
<span id="cb2-16"><a href="#cb2-16"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb2-17"><a href="#cb2-17"></a>tfe_text_view_class_init <span class="op">(</span>TfeTextViewClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-18"><a href="#cb2-18"></a><span class="op">}</span></span>
<span id="cb2-19"><a href="#cb2-19"></a></span>
<span id="cb2-20"><a href="#cb2-20"></a><span class="dt">void</span></span>
<span id="cb2-21"><a href="#cb2-21"></a>tfe_text_view_set_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">,</span> GFile <span class="op">*</span>f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-22"><a href="#cb2-22"></a> tv<span class="op">-&gt;</span>file <span class="op">=</span> f<span class="op">;</span></span>
<span id="cb2-23"><a href="#cb2-23"></a><span class="op">}</span></span>
<span id="cb2-24"><a href="#cb2-24"></a></span>
<span id="cb2-25"><a href="#cb2-25"></a>GFile <span class="op">*</span></span>
<span id="cb2-26"><a href="#cb2-26"></a>tfe_text_view_get_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-27"><a href="#cb2-27"></a> <span class="cf">return</span> tv<span class="op">-&gt;</span>file<span class="op">;</span></span>
<span id="cb2-28"><a href="#cb2-28"></a><span class="op">}</span></span>
<span id="cb2-29"><a href="#cb2-29"></a></span>
<span id="cb2-30"><a href="#cb2-30"></a>GtkWidget <span class="op">*</span></span>
<span id="cb2-31"><a href="#cb2-31"></a>tfe_text_view_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-32"><a href="#cb2-32"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_TEXT_VIEW<span class="op">,</span> NULL<span class="op">));</span></span>
<span id="cb2-33"><a href="#cb2-33"></a><span class="op">}</span></span></code></pre></div>
<p><code>tfe.c</code></p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="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;tfetextview.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="dt">static</span> <span class="dt">void</span></span>
<span id="cb3-5"><a href="#cb3-5"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6"></a> g_print <span class="op">(</span><span class="st">&quot;You need a filename argument.</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb3-7"><a href="#cb3-7"></a><span class="op">}</span></span>
<span id="cb3-8"><a href="#cb3-8"></a></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb3-10"><a href="#cb3-10"></a>app_open <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">,</span> GFile <span class="op">**</span> files<span class="op">,</span> gint n_files<span class="op">,</span> gchar <span class="op">*</span>hint<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-11"><a href="#cb3-11"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
<span id="cb3-12"><a href="#cb3-12"></a> GtkWidget <span class="op">*</span>nb<span class="op">;</span></span>
<span id="cb3-13"><a href="#cb3-13"></a> GtkWidget <span class="op">*</span>lab<span class="op">;</span></span>
<span id="cb3-14"><a href="#cb3-14"></a> GtkNotebookPage <span class="op">*</span>nbp<span class="op">;</span></span>
<span id="cb3-15"><a href="#cb3-15"></a> GtkWidget <span class="op">*</span>scr<span class="op">;</span></span>
<span id="cb3-16"><a href="#cb3-16"></a> GtkWidget <span class="op">*</span>tv<span class="op">;</span></span>
<span id="cb3-17"><a href="#cb3-17"></a> GtkTextBuffer <span class="op">*</span>tb<span class="op">;</span></span>
<span id="cb3-18"><a href="#cb3-18"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span>
<span id="cb3-19"><a href="#cb3-19"></a> gsize length<span class="op">;</span></span>
<span id="cb3-20"><a href="#cb3-20"></a> <span class="dt">char</span> <span class="op">*</span>filename<span class="op">;</span></span>
<span id="cb3-21"><a href="#cb3-21"></a> <span class="dt">int</span> i<span class="op">;</span></span>
<span id="cb3-22"><a href="#cb3-22"></a> GError <span class="op">*</span>err <span class="op">=</span> NULL<span class="op">;</span></span>
<span id="cb3-23"><a href="#cb3-23"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
<span id="cb3-24"><a href="#cb3-24"></a></span>
<span id="cb3-25"><a href="#cb3-25"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">&quot;/com/github/ToshioCP/tfe/tfe.ui&quot;</span><span class="op">);</span></span>
<span id="cb3-26"><a href="#cb3-26"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">&quot;win&quot;</span><span class="op">));</span></span>
<span id="cb3-27"><a href="#cb3-27"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> GTK_APPLICATION <span class="op">(</span>app<span class="op">));</span></span>
<span id="cb3-28"><a href="#cb3-28"></a> nb <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">&quot;nb&quot;</span><span class="op">));</span></span>
<span id="cb3-29"><a href="#cb3-29"></a> g_object_unref <span class="op">(</span>build<span class="op">);</span></span>
<span id="cb3-30"><a href="#cb3-30"></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 class="op">{</span></span>
<span id="cb3-31"><a href="#cb3-31"></a> <span class="cf">if</span> <span class="op">(</span>g_file_load_contents <span class="op">(</span>files<span class="op">[</span>i<span class="op">],</span> NULL<span class="op">,</span> <span class="op">&amp;</span>contents<span class="op">,</span> <span class="op">&amp;</span>length<span class="op">,</span> NULL<span class="op">,</span> <span class="op">&amp;</span>err<span class="op">))</span> <span class="op">{</span></span>
<span id="cb3-32"><a href="#cb3-32"></a> scr <span class="op">=</span> gtk_scrolled_window_new <span class="op">();</span></span>
<span id="cb3-33"><a href="#cb3-33"></a> tv <span class="op">=</span> tfe_text_view_new <span class="op">();</span></span>
<span id="cb3-34"><a href="#cb3-34"></a> tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
<span id="cb3-35"><a href="#cb3-35"></a> gtk_text_view_set_wrap_mode <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">),</span> GTK_WRAP_WORD_CHAR<span class="op">);</span></span>
<span id="cb3-36"><a href="#cb3-36"></a> gtk_scrolled_window_set_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">),</span> tv<span class="op">);</span></span>
<span id="cb3-37"><a href="#cb3-37"></a></span>
<span id="cb3-38"><a href="#cb3-38"></a> tfe_text_view_set_file <span class="op">(</span>TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">),</span> g_file_dup <span class="op">(</span>files<span class="op">[</span>i<span class="op">]));</span></span>
<span id="cb3-39"><a href="#cb3-39"></a> gtk_text_buffer_set_text <span class="op">(</span>tb<span class="op">,</span> contents<span class="op">,</span> length<span class="op">);</span></span>
<span id="cb3-40"><a href="#cb3-40"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span>
<span id="cb3-41"><a href="#cb3-41"></a> filename <span class="op">=</span> g_file_get_basename <span class="op">(</span>files<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb3-42"><a href="#cb3-42"></a> lab <span class="op">=</span> gtk_label_new <span class="op">(</span>filename<span class="op">);</span></span>
<span id="cb3-43"><a href="#cb3-43"></a> gtk_notebook_append_page <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">),</span> scr<span class="op">,</span> lab<span class="op">);</span></span>
<span id="cb3-44"><a href="#cb3-44"></a> nbp <span class="op">=</span> gtk_notebook_get_page <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">),</span> scr<span class="op">);</span></span>
<span id="cb3-45"><a href="#cb3-45"></a> g_object_set <span class="op">(</span>nbp<span class="op">,</span> <span class="st">&quot;tab-expand&quot;</span><span class="op">,</span> TRUE<span class="op">,</span> NULL<span class="op">);</span></span>
<span id="cb3-46"><a href="#cb3-46"></a> g_free <span class="op">(</span>filename<span class="op">);</span></span>
<span id="cb3-47"><a href="#cb3-47"></a> <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb3-48"><a href="#cb3-48"></a> g_printerr <span class="op">(</span><span class="st">&quot;%s.</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> err<span class="op">-&gt;</span>message<span class="op">);</span></span>
<span id="cb3-49"><a href="#cb3-49"></a> g_clear_error <span class="op">(&amp;</span>err<span class="op">);</span></span>
<span id="cb3-50"><a href="#cb3-50"></a> <span class="op">}</span></span>
<span id="cb3-51"><a href="#cb3-51"></a> <span class="op">}</span></span>
<span id="cb3-52"><a href="#cb3-52"></a> <span class="cf">if</span> <span class="op">(</span>gtk_notebook_get_n_pages <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">))</span> <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-53"><a href="#cb3-53"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
<span id="cb3-54"><a href="#cb3-54"></a> <span class="op">}</span> <span class="cf">else</span></span>
<span id="cb3-55"><a href="#cb3-55"></a> gtk_window_destroy <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
<span id="cb3-56"><a href="#cb3-56"></a><span class="op">}</span></span>
<span id="cb3-57"><a href="#cb3-57"></a></span>
<span id="cb3-58"><a href="#cb3-58"></a><span class="dt">int</span></span>
<span id="cb3-59"><a href="#cb3-59"></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="cb3-60"><a href="#cb3-60"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
<span id="cb3-61"><a href="#cb3-61"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
<span id="cb3-62"><a href="#cb3-62"></a></span>
<span id="cb3-63"><a href="#cb3-63"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span><span class="st">&quot;com.github.ToshioCP.tfe&quot;</span><span class="op">,</span> G_APPLICATION_HANDLES_OPEN<span class="op">);</span></span>
<span id="cb3-64"><a href="#cb3-64"></a> g_signal_connect <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="cb3-65"><a href="#cb3-65"></a> g_signal_connect <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="cb3-66"><a href="#cb3-66"></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="cb3-67"><a href="#cb3-67"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
<span id="cb3-68"><a href="#cb3-68"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
<span id="cb3-69"><a href="#cb3-69"></a><span class="op">}</span></span></code></pre></div>
<p>The ui file <code>tfe.ui</code> is the same as <code>tfe3.ui</code>
in the previous section.</p>
<p><code>tfe.gresource.xml</code></p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb4-1"><a href="#cb4-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="cb4-2"><a href="#cb4-2"></a>&lt;<span class="kw">gresources</span>&gt;</span>
<span id="cb4-3"><a href="#cb4-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="cb4-4"><a href="#cb4-4"></a> &lt;<span class="kw">file</span>&gt;tfe.ui&lt;/<span class="kw">file</span>&gt;</span>
<span id="cb4-5"><a href="#cb4-5"></a> &lt;/<span class="kw">gresource</span>&gt;</span>
<span id="cb4-6"><a href="#cb4-6"></a>&lt;/<span class="kw">gresources</span>&gt;</span></code></pre></div>
<p>Dividing a file makes it easy to maintain. But now we face a new
problem. The building step increases.</p>
<ul>
<li>Compiling the ui file <code>tfe.ui</code> into
<code>resources.c</code>.</li>
<li>Compiling <code>tfe.c</code> into <code>tfe.o</code> (object
file).</li>
<li>Compiling <code>tfetextview.c</code> into
<code>tfetextview.o</code>.</li>
<li>Compiling <code>resources.c</code> into
<code>resources.o</code>.</li>
<li>Linking all the object files into application <code>tfe</code>.</li>
</ul>
<p>Build tools manage the steps.</p>
<h2 id="meson-and-ninja">Meson and Ninja</h2>
<p>Ill explain Meson and Ninja build tools.</p>
<p>Other possible tools are Make and Autotools. They are traditional
tools but slower than Ninja. So, many developers use Meson and Ninja
lately. For example, GTK 4 uses them.</p>
<p>You need to create <code>meson.build</code> file first.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb5-1"><a href="#cb5-1"></a>project(&#39;tfe&#39;, &#39;c&#39;)</span>
<span id="cb5-2"><a href="#cb5-2"></a></span>
<span id="cb5-3"><a href="#cb5-3"></a>gtkdep = dependency(&#39;gtk4&#39;)</span>
<span id="cb5-4"><a href="#cb5-4"></a></span>
<span id="cb5-5"><a href="#cb5-5"></a>gnome=import(&#39;gnome&#39;)</span>
<span id="cb5-6"><a href="#cb5-6"></a>resources = gnome.compile_resources(&#39;resources&#39;,&#39;tfe.gresource.xml&#39;)</span>
<span id="cb5-7"><a href="#cb5-7"></a></span>
<span id="cb5-8"><a href="#cb5-8"></a>sourcefiles=files(&#39;tfe.c&#39;, &#39;tfetextview.c&#39;)</span>
<span id="cb5-9"><a href="#cb5-9"></a></span>
<span id="cb5-10"><a href="#cb5-10"></a>executable(&#39;tfe&#39;, sourcefiles, resources, dependencies: gtkdep, install: false)</span></code></pre></div>
<ul>
<li>1: The function <code>project</code> defines things about the
project. The first argument is the name of the project and the second is
the programming language.</li>
<li>3: The function <code>dependency</code> defines a dependency that is
taken by <code>pkg-config</code>. We put <code>gtk4</code> as an
argument.</li>
<li>5: The function <code>import</code> imports a module. In line 5, the
gnome module is imported and assigned to the variable
<code>gnome</code>. The gnome module provides helper tools to build GTK
programs.</li>
<li>6: The method <code>.compile_resources</code> is of the gnome module
and compiles files to resources under the instruction of xml file. In
line 6, the resource filename is <code>resources</code>, which means
<code>resources.c</code> and <code>resources.h</code>, and xml file is
<code>tfe.gresource.xml</code>. This method generates C source file by
default.</li>
<li>8: Defines source files.</li>
<li>10: Executable function generates a target file by compiling source
files. The first argument is the filename of the target. The following
arguments are source files. The last two arguments have keys and values.
For example, the fourth argument has a key <code>dependencies</code> , a
delimiter (<code>:</code>) and a value <code>gtkdep</code>. This type of
parameter is called <em>keyword parameter</em> or <em>kwargs</em>. The
value <code>gtkdep</code> is defined in line 3. The last argument tells
that this project doesnt install the executable file. So it is just
compiled in the build directory.</li>
</ul>
<p>Now run meson and ninja.</p>
<pre><code>$ meson setup _build
$ ninja -C _build</code></pre>
<p>meson has two arguments.</p>
<ul>
<li>setup: The first argument is a command of meson. Setup is the
default, so you can leave it out. But it is recommended to write it
explicitly since version 0.64.0.</li>
<li>The second argument is the name of the build directory.</li>
</ul>
<p>Then, the executable file <code>tfe</code> is generated under the
directory <code>_build</code>.</p>
<pre><code>$ _build/tfe tfe.c tfetextview.c</code></pre>
<p>A window appears. It includes a notebook with two pages. One is
<code>tfe.c</code> and the other is <code>tfetextview.c</code>.</p>
<p>For further information, see <a href="https://mesonbuild.com/">The
Meson Build system</a>.</p>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>
</html>