/
evo
/
Gtk4-tutorial
Обзор
Документация
Войти
/
evo
/
Gtk4-tutorial
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
v0.85
docs/sec24.html
534 строки
58 KB
Toshio Sekiya
Section 22, 24 and 25 are updated.
05 янв 2023, 14:41
05 янв 2023, 14:41
a8cf717
Код
Авторство
О чём код?
<!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="sec23.html">Prev: section23</a> </li> <li class="nav-item"> <a class="nav-link" href="sec25.html">Next: section25</a> </li> </ul> </div> </div> </nav> <h1 id="combine-gtkdrawingarea-and-tfetextview">Combine GtkDrawingArea and TfeTextView</h1> <p>Now, we will make a new application which has GtkDrawingArea and TfeTextView in it. Its name is “color”. If you write a name of a color in TfeTextView and click on the <code>run</code> button, then the color of GtkDrawingArea changes to the color given by you.</p> <figure> <img src="image/color.png" alt="color" /> <figcaption aria-hidden="true">color</figcaption> </figure> <p>The following colors are available. (without new line charactor)</p> <ul> <li>white</li> <li>black</li> <li>red</li> <li>green</li> <li>blue</li> </ul> <p>In addition the following two options are also available.</p> <ul> <li>light: Make the color of the drawing area lighter.</li> <li>dark: Make the color of the drawing area darker.</li> </ul> <p>This application can only do very simple things. However, it tells us that if we add powerful parser to it, we will be able to make it more efficient. I want to show it to you in the later section by making a turtle graphics language like Logo program language.</p> <p>In this section, we focus on how to bind the two objects.</p> <h2 id="color.ui-and-color.gresource.xml">Color.ui and color.gresource.xml</h2> <p>First, We need to make the ui file of the widgets. Title bar, four buttons in the tool bar, textview and drawing area. The ui file is as follows.</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"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span> <span id="cb1-2"><a href="#cb1-2"></a><<span class="kw">interface</span>></span> <span id="cb1-3"><a href="#cb1-3"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkApplicationWindow"</span><span class="ot"> id=</span><span class="st">"win"</span>></span> <span id="cb1-4"><a href="#cb1-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"title"</span>>color changer</<span class="kw">property</span>></span> <span id="cb1-5"><a href="#cb1-5"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-width"</span>>600</<span class="kw">property</span>></span> <span id="cb1-6"><a href="#cb1-6"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-height"</span>>400</<span class="kw">property</span>></span> <span id="cb1-7"><a href="#cb1-7"></a> <<span class="kw">child</span>></span> <span id="cb1-8"><a href="#cb1-8"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxv"</span>></span> <span id="cb1-9"><a href="#cb1-9"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_VERTICAL</<span class="kw">property</span>></span> <span id="cb1-10"><a href="#cb1-10"></a> <<span class="kw">child</span>></span> <span id="cb1-11"><a href="#cb1-11"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxh1"</span>></span> <span id="cb1-12"><a href="#cb1-12"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_HORIZONTAL</<span class="kw">property</span>></span> <span id="cb1-13"><a href="#cb1-13"></a> <<span class="kw">child</span>></span> <span id="cb1-14"><a href="#cb1-14"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy1"</span>></span> <span id="cb1-15"><a href="#cb1-15"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"width-chars"</span>>10</<span class="kw">property</span>></span> <span id="cb1-16"><a href="#cb1-16"></a> </<span class="kw">object</span>></span> <span id="cb1-17"><a href="#cb1-17"></a> </<span class="kw">child</span>></span> <span id="cb1-18"><a href="#cb1-18"></a> <<span class="kw">child</span>></span> <span id="cb1-19"><a href="#cb1-19"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btnr"</span>></span> <span id="cb1-20"><a href="#cb1-20"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Run</<span class="kw">property</span>></span> <span id="cb1-21"><a href="#cb1-21"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"run_cb"</span>></<span class="kw">signal</span>></span> <span id="cb1-22"><a href="#cb1-22"></a> </<span class="kw">object</span>></span> <span id="cb1-23"><a href="#cb1-23"></a> </<span class="kw">child</span>></span> <span id="cb1-24"><a href="#cb1-24"></a> <<span class="kw">child</span>></span> <span id="cb1-25"><a href="#cb1-25"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btno"</span>></span> <span id="cb1-26"><a href="#cb1-26"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Open</<span class="kw">property</span>></span> <span id="cb1-27"><a href="#cb1-27"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"open_cb"</span>></<span class="kw">signal</span>></span> <span id="cb1-28"><a href="#cb1-28"></a> </<span class="kw">object</span>></span> <span id="cb1-29"><a href="#cb1-29"></a> </<span class="kw">child</span>></span> <span id="cb1-30"><a href="#cb1-30"></a> <<span class="kw">child</span>></span> <span id="cb1-31"><a href="#cb1-31"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy2"</span>></span> <span id="cb1-32"><a href="#cb1-32"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span> <span id="cb1-33"><a href="#cb1-33"></a> </<span class="kw">object</span>></span> <span id="cb1-34"><a href="#cb1-34"></a> </<span class="kw">child</span>></span> <span id="cb1-35"><a href="#cb1-35"></a> <<span class="kw">child</span>></span> <span id="cb1-36"><a href="#cb1-36"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btns"</span>></span> <span id="cb1-37"><a href="#cb1-37"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Save</<span class="kw">property</span>></span> <span id="cb1-38"><a href="#cb1-38"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"save_cb"</span>></<span class="kw">signal</span>></span> <span id="cb1-39"><a href="#cb1-39"></a> </<span class="kw">object</span>></span> <span id="cb1-40"><a href="#cb1-40"></a> </<span class="kw">child</span>></span> <span id="cb1-41"><a href="#cb1-41"></a> <<span class="kw">child</span>></span> <span id="cb1-42"><a href="#cb1-42"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btnc"</span>></span> <span id="cb1-43"><a href="#cb1-43"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Close</<span class="kw">property</span>></span> <span id="cb1-44"><a href="#cb1-44"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"close_cb"</span>></<span class="kw">signal</span>></span> <span id="cb1-45"><a href="#cb1-45"></a> </<span class="kw">object</span>></span> <span id="cb1-46"><a href="#cb1-46"></a> </<span class="kw">child</span>></span> <span id="cb1-47"><a href="#cb1-47"></a> <<span class="kw">child</span>></span> <span id="cb1-48"><a href="#cb1-48"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy3"</span>></span> <span id="cb1-49"><a href="#cb1-49"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"width-chars"</span>>10</<span class="kw">property</span>></span> <span id="cb1-50"><a href="#cb1-50"></a> </<span class="kw">object</span>></span> <span id="cb1-51"><a href="#cb1-51"></a> </<span class="kw">child</span>></span> <span id="cb1-52"><a href="#cb1-52"></a> </<span class="kw">object</span>></span> <span id="cb1-53"><a href="#cb1-53"></a> </<span class="kw">child</span>></span> <span id="cb1-54"><a href="#cb1-54"></a> <<span class="kw">child</span>></span> <span id="cb1-55"><a href="#cb1-55"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxh2"</span>></span> <span id="cb1-56"><a href="#cb1-56"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_HORIZONTAL</<span class="kw">property</span>></span> <span id="cb1-57"><a href="#cb1-57"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"homogeneous"</span>>TRUE</<span class="kw">property</span>></span> <span id="cb1-58"><a href="#cb1-58"></a> <<span class="kw">child</span>></span> <span id="cb1-59"><a href="#cb1-59"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkScrolledWindow"</span><span class="ot"> id=</span><span class="st">"scr"</span>></span> <span id="cb1-60"><a href="#cb1-60"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span> <span id="cb1-61"><a href="#cb1-61"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vexpand"</span>>TRUE</<span class="kw">property</span>></span> <span id="cb1-62"><a href="#cb1-62"></a> <<span class="kw">child</span>></span> <span id="cb1-63"><a href="#cb1-63"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"TfeTextView"</span><span class="ot"> id=</span><span class="st">"tv"</span>></span> <span id="cb1-64"><a href="#cb1-64"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"wrap-mode"</span>>GTK_WRAP_WORD_CHAR</<span class="kw">property</span>></span> <span id="cb1-65"><a href="#cb1-65"></a> </<span class="kw">object</span>></span> <span id="cb1-66"><a href="#cb1-66"></a> </<span class="kw">child</span>></span> <span id="cb1-67"><a href="#cb1-67"></a> </<span class="kw">object</span>></span> <span id="cb1-68"><a href="#cb1-68"></a> </<span class="kw">child</span>></span> <span id="cb1-69"><a href="#cb1-69"></a> <<span class="kw">child</span>></span> <span id="cb1-70"><a href="#cb1-70"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkDrawingArea"</span><span class="ot"> id=</span><span class="st">"da"</span>></span> <span id="cb1-71"><a href="#cb1-71"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span> <span id="cb1-72"><a href="#cb1-72"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vexpand"</span>>TRUE</<span class="kw">property</span>></span> <span id="cb1-73"><a href="#cb1-73"></a> </<span class="kw">object</span>></span> <span id="cb1-74"><a href="#cb1-74"></a> </<span class="kw">child</span>></span> <span id="cb1-75"><a href="#cb1-75"></a> </<span class="kw">object</span>></span> <span id="cb1-76"><a href="#cb1-76"></a> </<span class="kw">child</span>></span> <span id="cb1-77"><a href="#cb1-77"></a> </<span class="kw">object</span>></span> <span id="cb1-78"><a href="#cb1-78"></a> </<span class="kw">child</span>></span> <span id="cb1-79"><a href="#cb1-79"></a> </<span class="kw">object</span>></span> <span id="cb1-80"><a href="#cb1-80"></a></<span class="kw">interface</span>></span></code></pre></div> <ul> <li>10-53: The horizontal box <code>boxh1</code> makes a tool bar which has four buttons, <code>Run</code>, <code>Open</code>, <code>Save</code> and <code>Close</code>. This is similar to the <code>tfe</code> text editor in <a href="sec9.html">Section 9</a>. There are two differences. <code>Run</code> button replaces <code>New</code> button. A signal element is added to each button object. It has “name” attribute which is a signal name and “handler” attribute which is the name of its signal handler. Options “-WI, –export-dynamic” CFLAG is necessary when you compile the application. You can achieve this by adding “export_dynamic: true” argument to the executable function in <code>meson.build</code>. And be careful that the handler must be defined without ‘static’ class.</li> <li>54-76: The horizontal box <code>boxh2</code> includes GtkScrolledWindow and GtkDrawingArea. GtkBox has “homogeneous property” with TRUE value, so the two children have the same width in the box. TfeTextView is a child of GtkScrolledWindow.</li> </ul> <p>The xml file for the resource compiler is almost same as before. Just substitute “color” for “tfe”.</p> <div class="sourceCode" id="cb2"><pre class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb2-1"><a href="#cb2-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span> <span id="cb2-2"><a href="#cb2-2"></a><<span class="kw">gresources</span>></span> <span id="cb2-3"><a href="#cb2-3"></a> <<span class="kw">gresource</span><span class="ot"> prefix=</span><span class="st">"/com/github/ToshioCP/color"</span>></span> <span id="cb2-4"><a href="#cb2-4"></a> <<span class="kw">file</span>>color.ui</<span class="kw">file</span>></span> <span id="cb2-5"><a href="#cb2-5"></a> </<span class="kw">gresource</span>></span> <span id="cb2-6"><a href="#cb2-6"></a></<span class="kw">gresources</span>></span></code></pre></div> <h2 id="drawing-function-and-surface">Drawing function and surface</h2> <p>The main point of this program is a drawing function.</p> <div class="sourceCode" id="cb3"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb3-2"><a href="#cb3-2"></a>draw_func <span class="op">(</span>GtkDrawingArea <span class="op">*</span>drawing_area<span class="op">,</span> cairo_t <span class="op">*</span>cr<span class="op">,</span> <span class="dt">int</span> width<span class="op">,</span> <span class="dt">int</span> height<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span> <span id="cb3-3"><a href="#cb3-3"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span> <span class="op">{</span></span> <span id="cb3-4"><a href="#cb3-4"></a> cairo_set_source_surface <span class="op">(</span>cr<span class="op">,</span> surface<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb3-5"><a href="#cb3-5"></a> cairo_paint <span class="op">(</span>cr<span class="op">);</span></span> <span id="cb3-6"><a href="#cb3-6"></a> <span class="op">}</span></span> <span id="cb3-7"><a href="#cb3-7"></a><span class="op">}</span></span></code></pre></div> <p>The <code>surface</code> variable in line 3 is a static variable.</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><span class="dt">static</span> cairo_surface_t <span class="op">*</span>surface <span class="op">=</span> NULL<span class="op">;</span></span></code></pre></div> <p>The drawing function just copies the <code>surface</code> to its own surface with the <code>cairo_paint</code> function. The surface (pointed by the static variable <code>surface</code>) is built by the <code>run</code> function.</p> <div class="sourceCode" id="cb5"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb5-2"><a href="#cb5-2"></a>run <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span> <span id="cb5-3"><a href="#cb5-3"></a> GtkTextBuffer <span class="op">*</span>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="cb5-4"><a href="#cb5-4"></a> GtkTextIter start_iter<span class="op">;</span></span> <span id="cb5-5"><a href="#cb5-5"></a> GtkTextIter end_iter<span class="op">;</span></span> <span id="cb5-6"><a href="#cb5-6"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span> <span id="cb5-7"><a href="#cb5-7"></a> cairo_t <span class="op">*</span>cr<span class="op">;</span></span> <span id="cb5-8"><a href="#cb5-8"></a></span> <span id="cb5-9"><a href="#cb5-9"></a> gtk_text_buffer_get_bounds <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">);</span></span> <span id="cb5-10"><a href="#cb5-10"></a> contents <span class="op">=</span> gtk_text_buffer_get_text <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">,</span> FALSE<span class="op">);</span></span> <span id="cb5-11"><a href="#cb5-11"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span> <span class="op">{</span></span> <span id="cb5-12"><a href="#cb5-12"></a> cr <span class="op">=</span> cairo_create <span class="op">(</span>surface<span class="op">);</span></span> <span id="cb5-13"><a href="#cb5-13"></a> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"red"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb5-14"><a href="#cb5-14"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb5-15"><a href="#cb5-15"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"green"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb5-16"><a href="#cb5-16"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb5-17"><a href="#cb5-17"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"blue"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb5-18"><a href="#cb5-18"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span> <span id="cb5-19"><a href="#cb5-19"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"white"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb5-20"><a href="#cb5-20"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span> <span id="cb5-21"><a href="#cb5-21"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"black"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb5-22"><a href="#cb5-22"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb5-23"><a href="#cb5-23"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"light"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb5-24"><a href="#cb5-24"></a> cairo_set_source_rgba <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="fl">0.5</span><span class="op">);</span></span> <span id="cb5-25"><a href="#cb5-25"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"dark"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb5-26"><a href="#cb5-26"></a> cairo_set_source_rgba <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="fl">0.5</span><span class="op">);</span></span> <span id="cb5-27"><a href="#cb5-27"></a> <span class="cf">else</span></span> <span id="cb5-28"><a href="#cb5-28"></a> cairo_set_source_surface <span class="op">(</span>cr<span class="op">,</span> surface<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb5-29"><a href="#cb5-29"></a> cairo_paint <span class="op">(</span>cr<span class="op">);</span></span> <span id="cb5-30"><a href="#cb5-30"></a> cairo_destroy <span class="op">(</span>cr<span class="op">);</span></span> <span id="cb5-31"><a href="#cb5-31"></a> <span class="op">}</span></span> <span id="cb5-32"><a href="#cb5-32"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span> <span id="cb5-33"><a href="#cb5-33"></a><span class="op">}</span></span></code></pre></div> <ul> <li>9-10: Gets the string in the GtkTextBuffer and inserts it to <code>contents</code>.</li> <li>11: If the variable <code>surface</code> points a surface instance, it is painted as follows.</li> <li>12- 30: The source is set based on the string <code>contents</code> and copied to the surface with <code>cairo_paint</code>.</li> <li>24,26: Alpha channel is used in “light” and “dark” procedure.</li> </ul> <p>The drawing area just reflects the <code>surface</code>. But one problem is resizing. If a user resizes the main window, the drawing area is also resized. It makes size difference between the surface and the drawing area. So, the surface needs to be resized to fit the drawing area.</p> <p>It is accomplished by connecting the “resize” signal on the drawing area to a handler.</p> <div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>g_signal_connect <span class="op">(</span>GTK_DRAWING_AREA <span class="op">(</span>da<span class="op">),</span> <span class="st">"resize"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>resize_cb<span class="op">),</span> NULL<span class="op">);</span></span></code></pre></div> <p>The handler is as follows.</p> <div class="sourceCode" id="cb7"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb7-2"><a href="#cb7-2"></a>resize_cb <span class="op">(</span>GtkDrawingArea <span class="op">*</span>drawing_area<span class="op">,</span> <span class="dt">int</span> width<span class="op">,</span> <span class="dt">int</span> height<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span> <span id="cb7-3"><a href="#cb7-3"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span></span> <span id="cb7-4"><a href="#cb7-4"></a> cairo_surface_destroy <span class="op">(</span>surface<span class="op">);</span></span> <span id="cb7-5"><a href="#cb7-5"></a> surface <span class="op">=</span> cairo_image_surface_create <span class="op">(</span>CAIRO_FORMAT_ARGB32<span class="op">,</span> width<span class="op">,</span> height<span class="op">);</span></span> <span id="cb7-6"><a href="#cb7-6"></a> run <span class="op">();</span></span> <span id="cb7-7"><a href="#cb7-7"></a><span class="op">}</span></span></code></pre></div> <p>If the variable <code>surface</code> sets a surface instance, it is destroyed. A new surface is created and its size fits the drawing area. The surface is assigned to the variable <code>surface</code>. The function <code>run</code> is called and the surface is colored.</p> <p>The signal is emitted when:</p> <ul> <li>The drawing area is realized (it appears on the display).</li> <li>It is changed (resized) while realized</li> </ul> <p>So, the first surface is created when it is realized.</p> <h2 id="colorapplication.c">Colorapplication.c</h2> <p>This is the main file.</p> <ul> <li>Builds widgets by GtkBuilder.</li> <li>Sets a drawing function for GtkDrawingArea. And connects a handler to the “resize” signal on the GtkDrawingArea instance.</li> <li>Implements each call back function. Particularly, <code>Run</code> signal handler is the point in this program.</li> </ul> <p>The following is <code>colorapplication.c</code>.</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"><gtk/gtk.h></span></span> <span id="cb8-2"><a href="#cb8-2"></a><span class="pp">#include </span><span class="im">"../tfetextview/tfetextview.h"</span></span> <span id="cb8-3"><a href="#cb8-3"></a></span> <span id="cb8-4"><a href="#cb8-4"></a><span class="dt">static</span> GtkWidget <span class="op">*</span>win<span class="op">;</span></span> <span id="cb8-5"><a href="#cb8-5"></a><span class="dt">static</span> GtkWidget <span class="op">*</span>tv<span class="op">;</span></span> <span id="cb8-6"><a href="#cb8-6"></a><span class="dt">static</span> GtkWidget <span class="op">*</span>da<span class="op">;</span></span> <span id="cb8-7"><a href="#cb8-7"></a></span> <span id="cb8-8"><a href="#cb8-8"></a><span class="dt">static</span> cairo_surface_t <span class="op">*</span>surface <span class="op">=</span> NULL<span class="op">;</span></span> <span id="cb8-9"><a href="#cb8-9"></a></span> <span id="cb8-10"><a href="#cb8-10"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb8-11"><a href="#cb8-11"></a>run <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span> <span id="cb8-12"><a href="#cb8-12"></a> GtkTextBuffer <span class="op">*</span>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="cb8-13"><a href="#cb8-13"></a> GtkTextIter start_iter<span class="op">;</span></span> <span id="cb8-14"><a href="#cb8-14"></a> GtkTextIter end_iter<span class="op">;</span></span> <span id="cb8-15"><a href="#cb8-15"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span> <span id="cb8-16"><a href="#cb8-16"></a> cairo_t <span class="op">*</span>cr<span class="op">;</span></span> <span id="cb8-17"><a href="#cb8-17"></a></span> <span id="cb8-18"><a href="#cb8-18"></a> gtk_text_buffer_get_bounds <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">);</span></span> <span id="cb8-19"><a href="#cb8-19"></a> contents <span class="op">=</span> gtk_text_buffer_get_text <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">,</span> FALSE<span class="op">);</span></span> <span id="cb8-20"><a href="#cb8-20"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-21"><a href="#cb8-21"></a> cr <span class="op">=</span> cairo_create <span class="op">(</span>surface<span class="op">);</span></span> <span id="cb8-22"><a href="#cb8-22"></a> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"red"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb8-23"><a href="#cb8-23"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb8-24"><a href="#cb8-24"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"green"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb8-25"><a href="#cb8-25"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb8-26"><a href="#cb8-26"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"blue"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb8-27"><a href="#cb8-27"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span> <span id="cb8-28"><a href="#cb8-28"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"white"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb8-29"><a href="#cb8-29"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span> <span id="cb8-30"><a href="#cb8-30"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"black"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb8-31"><a href="#cb8-31"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb8-32"><a href="#cb8-32"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"light"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb8-33"><a href="#cb8-33"></a> cairo_set_source_rgba <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="fl">0.5</span><span class="op">);</span></span> <span id="cb8-34"><a href="#cb8-34"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"dark"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span> <span id="cb8-35"><a href="#cb8-35"></a> cairo_set_source_rgba <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="fl">0.5</span><span class="op">);</span></span> <span id="cb8-36"><a href="#cb8-36"></a> <span class="cf">else</span></span> <span id="cb8-37"><a href="#cb8-37"></a> cairo_set_source_surface <span class="op">(</span>cr<span class="op">,</span> surface<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb8-38"><a href="#cb8-38"></a> cairo_paint <span class="op">(</span>cr<span class="op">);</span></span> <span id="cb8-39"><a href="#cb8-39"></a> cairo_destroy <span class="op">(</span>cr<span class="op">);</span></span> <span id="cb8-40"><a href="#cb8-40"></a> <span class="op">}</span></span> <span id="cb8-41"><a href="#cb8-41"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span> <span id="cb8-42"><a href="#cb8-42"></a><span class="op">}</span></span> <span id="cb8-43"><a href="#cb8-43"></a></span> <span id="cb8-44"><a href="#cb8-44"></a><span class="dt">void</span></span> <span id="cb8-45"><a href="#cb8-45"></a>run_cb <span class="op">(</span>GtkWidget <span class="op">*</span>btnr<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-46"><a href="#cb8-46"></a> run <span class="op">();</span></span> <span id="cb8-47"><a href="#cb8-47"></a> gtk_widget_queue_draw <span class="op">(</span>GTK_WIDGET <span class="op">(</span>da<span class="op">));</span></span> <span id="cb8-48"><a href="#cb8-48"></a><span class="op">}</span></span> <span id="cb8-49"><a href="#cb8-49"></a></span> <span id="cb8-50"><a href="#cb8-50"></a><span class="dt">void</span></span> <span id="cb8-51"><a href="#cb8-51"></a>open_cb <span class="op">(</span>GtkWidget <span class="op">*</span>btno<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-52"><a href="#cb8-52"></a> tfe_text_view_open <span class="op">(</span>TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">),</span> GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span> <span id="cb8-53"><a href="#cb8-53"></a><span class="op">}</span></span> <span id="cb8-54"><a href="#cb8-54"></a></span> <span id="cb8-55"><a href="#cb8-55"></a><span class="dt">void</span></span> <span id="cb8-56"><a href="#cb8-56"></a>save_cb <span class="op">(</span>GtkWidget <span class="op">*</span>btns<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-57"><a href="#cb8-57"></a> tfe_text_view_save <span class="op">(</span>TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span> <span id="cb8-58"><a href="#cb8-58"></a><span class="op">}</span></span> <span id="cb8-59"><a href="#cb8-59"></a></span> <span id="cb8-60"><a href="#cb8-60"></a><span class="dt">void</span></span> <span id="cb8-61"><a href="#cb8-61"></a>close_cb <span class="op">(</span>GtkWidget <span class="op">*</span>btnc<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-62"><a href="#cb8-62"></a> gtk_window_destroy <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span> <span id="cb8-63"><a href="#cb8-63"></a><span class="op">}</span></span> <span id="cb8-64"><a href="#cb8-64"></a></span> <span id="cb8-65"><a href="#cb8-65"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb8-66"><a href="#cb8-66"></a>resize_cb <span class="op">(</span>GtkDrawingArea <span class="op">*</span>drawing_area<span class="op">,</span> <span class="dt">int</span> width<span class="op">,</span> <span class="dt">int</span> height<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-67"><a href="#cb8-67"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span></span> <span id="cb8-68"><a href="#cb8-68"></a> cairo_surface_destroy <span class="op">(</span>surface<span class="op">);</span></span> <span id="cb8-69"><a href="#cb8-69"></a> surface <span class="op">=</span> cairo_image_surface_create <span class="op">(</span>CAIRO_FORMAT_ARGB32<span class="op">,</span> width<span class="op">,</span> height<span class="op">);</span></span> <span id="cb8-70"><a href="#cb8-70"></a> run <span class="op">();</span></span> <span id="cb8-71"><a href="#cb8-71"></a><span class="op">}</span></span> <span id="cb8-72"><a href="#cb8-72"></a></span> <span id="cb8-73"><a href="#cb8-73"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb8-74"><a href="#cb8-74"></a>draw_func <span class="op">(</span>GtkDrawingArea <span class="op">*</span>drawing_area<span class="op">,</span> cairo_t <span class="op">*</span>cr<span class="op">,</span> <span class="dt">int</span> width<span class="op">,</span> <span class="dt">int</span> height<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-75"><a href="#cb8-75"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-76"><a href="#cb8-76"></a> cairo_set_source_surface <span class="op">(</span>cr<span class="op">,</span> surface<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span> <span id="cb8-77"><a href="#cb8-77"></a> cairo_paint <span class="op">(</span>cr<span class="op">);</span></span> <span id="cb8-78"><a href="#cb8-78"></a> <span class="op">}</span></span> <span id="cb8-79"><a href="#cb8-79"></a><span class="op">}</span></span> <span id="cb8-80"><a href="#cb8-80"></a></span> <span id="cb8-81"><a href="#cb8-81"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb8-82"><a href="#cb8-82"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-83"><a href="#cb8-83"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span> <span id="cb8-84"><a href="#cb8-84"></a><span class="op">}</span></span> <span id="cb8-85"><a href="#cb8-85"></a></span> <span id="cb8-86"><a href="#cb8-86"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb8-87"><a href="#cb8-87"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-88"><a href="#cb8-88"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span> <span id="cb8-89"><a href="#cb8-89"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span> <span id="cb8-90"><a href="#cb8-90"></a> GdkDisplay <span class="op">*</span>display<span class="op">;</span></span> <span id="cb8-91"><a href="#cb8-91"></a></span> <span id="cb8-92"><a href="#cb8-92"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">"/com/github/ToshioCP/color/color.ui"</span><span class="op">);</span></span> <span id="cb8-93"><a href="#cb8-93"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"win"</span><span class="op">));</span></span> <span id="cb8-94"><a href="#cb8-94"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> app<span class="op">);</span></span> <span id="cb8-95"><a href="#cb8-95"></a> tv <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">"tv"</span><span class="op">));</span></span> <span id="cb8-96"><a href="#cb8-96"></a> da <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">"da"</span><span class="op">));</span></span> <span id="cb8-97"><a href="#cb8-97"></a> g_object_unref<span class="op">(</span>build<span class="op">);</span></span> <span id="cb8-98"><a href="#cb8-98"></a> g_signal_connect <span class="op">(</span>GTK_DRAWING_AREA <span class="op">(</span>da<span class="op">),</span> <span class="st">"resize"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>resize_cb<span class="op">),</span> NULL<span class="op">);</span></span> <span id="cb8-99"><a href="#cb8-99"></a> gtk_drawing_area_set_draw_func <span class="op">(</span>GTK_DRAWING_AREA <span class="op">(</span>da<span class="op">),</span> draw_func<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span> <span id="cb8-100"><a href="#cb8-100"></a></span> <span id="cb8-101"><a href="#cb8-101"></a> display <span class="op">=</span> gdk_display_get_default <span class="op">();</span></span> <span id="cb8-102"><a href="#cb8-102"></a> GtkCssProvider <span class="op">*</span>provider <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span> <span id="cb8-103"><a href="#cb8-103"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> <span class="st">"textview {padding: 10px; font-family: monospace; font-size: 12pt;}"</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span> <span id="cb8-104"><a href="#cb8-104"></a> gtk_style_context_add_provider_for_display <span class="op">(</span>display<span class="op">,</span> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">),</span> GTK_STYLE_PROVIDER_PRIORITY_USER<span class="op">);</span></span> <span id="cb8-105"><a href="#cb8-105"></a><span class="op">}</span></span> <span id="cb8-106"><a href="#cb8-106"></a></span> <span id="cb8-107"><a href="#cb8-107"></a><span class="dt">static</span> <span class="dt">void</span></span> <span id="cb8-108"><a href="#cb8-108"></a>app_shutdown <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-109"><a href="#cb8-109"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span></span> <span id="cb8-110"><a href="#cb8-110"></a> cairo_surface_destroy <span class="op">(</span>surface<span class="op">);</span></span> <span id="cb8-111"><a href="#cb8-111"></a><span class="op">}</span></span> <span id="cb8-112"><a href="#cb8-112"></a></span> <span id="cb8-113"><a href="#cb8-113"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.color"</span></span> <span id="cb8-114"><a href="#cb8-114"></a></span> <span id="cb8-115"><a href="#cb8-115"></a><span class="dt">int</span></span> <span id="cb8-116"><a href="#cb8-116"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span> <span id="cb8-117"><a href="#cb8-117"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span> <span id="cb8-118"><a href="#cb8-118"></a> <span class="dt">int</span> stat<span class="op">;</span></span> <span id="cb8-119"><a href="#cb8-119"></a></span> <span id="cb8-120"><a href="#cb8-120"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span> <span id="cb8-121"><a href="#cb8-121"></a></span> <span id="cb8-122"><a href="#cb8-122"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span> <span id="cb8-123"><a href="#cb8-123"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"shutdown"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_shutdown<span class="op">),</span> NULL<span class="op">);</span></span> <span id="cb8-124"><a href="#cb8-124"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span> <span id="cb8-125"><a href="#cb8-125"></a></span> <span id="cb8-126"><a href="#cb8-126"></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="cb8-127"><a href="#cb8-127"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span> <span id="cb8-128"><a href="#cb8-128"></a> <span class="cf">return</span> stat<span class="op">;</span></span> <span id="cb8-129"><a href="#cb8-129"></a><span class="op">}</span></span></code></pre></div> <ul> <li>4-8: Win, tv, da and surface are defined as static variables.</li> <li>10-42: Run function.</li> <li>44-63: Handlers for button signals.</li> <li>65-71: Resize handler.</li> <li>73-79: Drawing function.</li> <li>81-84: Application activate handler. It just shows the main window.</li> <li>86-105: Application startup handler.</li> <li>92- 97: It builds widgets according to the ui resource. The static variables win, tv and da are assigned instances.</li> <li>98: Connects “resize” signal and a handler.</li> <li>99: Drawing function is set.</li> <li>101-104: CSS for textview padding is set.</li> <li>107-111: Application shutdown handler. If there exists a surface instance, it will be destroyed.</li> <li>116-129: A function <code>main</code>. It creates a new application instance. And connects three signals startup, shutdown and activate to their handlers. It runs the application. It releases the reference to the application and returns with <code>stat</code> value.</li> </ul> <h2 id="meson.build">Meson.build</h2> <p>This file is almost same as before. An argument “export_dynamic: true” is added to executable function.</p> <div class="sourceCode" id="cb9"><pre class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb9-1"><a href="#cb9-1"></a>project('color', 'c')</span> <span id="cb9-2"><a href="#cb9-2"></a></span> <span id="cb9-3"><a href="#cb9-3"></a>gtkdep = dependency('gtk4')</span> <span id="cb9-4"><a href="#cb9-4"></a></span> <span id="cb9-5"><a href="#cb9-5"></a>gnome=import('gnome')</span> <span id="cb9-6"><a href="#cb9-6"></a>resources = gnome.compile_resources('resources','color.gresource.xml')</span> <span id="cb9-7"><a href="#cb9-7"></a></span> <span id="cb9-8"><a href="#cb9-8"></a>sourcefiles=files('colorapplication.c', '../tfetextview/tfetextview.c')</span> <span id="cb9-9"><a href="#cb9-9"></a></span> <span id="cb9-10"><a href="#cb9-10"></a>executable('color', sourcefiles, resources, dependencies: gtkdep, export_dynamic: true)</span></code></pre></div> <h2 id="build-and-try">Build and try</h2> <p>Type the following to compile the program.</p> <pre><code>$ meson _build $ ninja -C _build</code></pre> <p>The application is made in <code>_build</code> directory. Type the following to execute it.</p> <pre><code>$ _build/color</code></pre> <p>Type “red”, “green”, “blue”, “white”, black”, “light” or “dark” in the TfeTextView. No new line charactor is needed. Then, click on the <code>Run</code> button. Make sure the color of GtkDrawingArea changes.</p> <p>In this program TfeTextView is used to change the color. You can use buttons or menus instead of textview. Probably it is more appropriate. Using textview is unnatural. It is a good practice to make such application by yourself.</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>