mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2025-01-11 20:03:35 +01:00
Merge branch 'dev'
This commit is contained in:
commit
ae15d4abbd
15 changed files with 721 additions and 711 deletions
Binary file not shown.
Before Width: | Height: | Size: 77 KiB |
|
@ -151,14 +151,14 @@ more features.</p>
|
|||
lines, words and characters</h2>
|
||||
<pre><code>$ LANG=C wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfenotebook.c tfe5/tfenotebook.h tfetextview/tfetextview.c tfetextview/tfetextview.h tfe5/tfe.ui
|
||||
10 17 294 tfe5/meson.build
|
||||
101 308 3274 tfe5/tfeapplication.c
|
||||
110 336 3631 tfe5/tfeapplication.c
|
||||
6 9 153 tfe5/tfe.gresource.xml
|
||||
145 387 3667 tfe5/tfenotebook.c
|
||||
15 21 241 tfe5/tfenotebook.h
|
||||
239 863 9264 tfetextview/tfetextview.c
|
||||
35 60 701 tfetextview/tfetextview.h
|
||||
61 100 2073 tfe5/tfe.ui
|
||||
612 1765 19667 total</code></pre>
|
||||
621 1793 20024 total</code></pre>
|
||||
</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>
|
||||
|
|
|
@ -186,7 +186,7 @@ file</h2>
|
|||
<p>If you want to install a developing version of GTK 4, you need to
|
||||
build it from the source. See <a
|
||||
href="https://docs.gtk.org/gtk4/building.html">Compiling the GTK
|
||||
Libraries</a> secion in the GTK 4 API reference.</p>
|
||||
Libraries</a> section in the GTK 4 API reference.</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>
|
||||
|
|
496
docs/sec23.html
496
docs/sec23.html
|
@ -5,7 +5,7 @@
|
|||
<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>Gtk4 tutorial</title>
|
||||
<title>GTK 4 tutorial</title>
|
||||
<style>
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
|
@ -112,352 +112,390 @@
|
|||
</div>
|
||||
</nav>
|
||||
<h1 id="periodic-events">Periodic Events</h1>
|
||||
<p>This chapter was written by Paul Schulz <a href="mailto:paul@mawsonlakes.org" class="email">paul@mawsonlakes.org</a>.</p>
|
||||
<h2 id="how-do-we-create-an-animation">How do we create an animation?</h2>
|
||||
<p>In this section we will continue to build on our previous work. We will create an analog clock application. By adding a function which periodically redraws GtkDrawingArea, the clock will be able to continuously display the time.</p>
|
||||
<p>The application uses a compiled in ‘resource’ file, so if the GTK4 libraries and their dependencies are installed and available, the application will run from anywhere.</p>
|
||||
<p>The program also makes use of some standard mathematical and time handling functions.</p>
|
||||
<p>The clocks mechanics were taken from a Cairo drawing example, using gtkmm4, which can be found <a href="https://developer-old.gnome.org/gtkmm-tutorial/stable/sec-drawing-clock-example.html.en">here</a>.</p>
|
||||
<p>This chapter was written by Paul Schulz <a
|
||||
href="mailto:paul@mawsonlakes.org"
|
||||
class="email">paul@mawsonlakes.org</a>.</p>
|
||||
<h2 id="how-do-we-create-an-animation">How do we create an
|
||||
animation?</h2>
|
||||
<p>In this section we will continue to build on our previous work. We
|
||||
will create an analog clock application. By adding a function which
|
||||
periodically redraws GtkDrawingArea, the clock will be able to
|
||||
continuously display the time.</p>
|
||||
<p>The application uses a compiled in ‘resource’ file, so if the GTK4
|
||||
libraries and their dependencies are installed and available, the
|
||||
application will run from anywhere.</p>
|
||||
<p>The program also makes use of some standard mathematical and time
|
||||
handling functions.</p>
|
||||
<p>The clocks mechanics were taken from a Cairo drawing example, using
|
||||
gtkmm4, which can be found <a
|
||||
href="https://developer-old.gnome.org/gtkmm-tutorial/stable/sec-drawing-clock-example.html.en">here</a>.</p>
|
||||
<p>The complete code is at the end.</p>
|
||||
<h2 id="drawing-the-clock-face-hour-minute-and-second-hands">Drawing the clock face, hour, minute and second hands</h2>
|
||||
<p>The <code>draw_clock()</code> function does all the work. See the in-file comments for an explanation of how the Cairo drawing works.</p>
|
||||
<p>For a detailed reference of what each of the Cairo functions does see the <a href="https://www.cairographics.org/manual/cairo-cairo-t.html">cairo_t reference</a>.</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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2"></a>draw_clock (GtkDrawingArea *area, cairo_t *cr, <span class="dt">int</span> width, <span class="dt">int</span> height, gpointer user_data) {</span>
|
||||
<h2 id="drawing-the-clock-face-hour-minute-and-second-hands">Drawing the
|
||||
clock face, hour, minute and second hands</h2>
|
||||
<p>The <code>draw_clock()</code> function does all the work. See the
|
||||
in-file comments for an explanation of how the Cairo drawing works.</p>
|
||||
<p>For a detailed reference of what each of the Cairo functions does see
|
||||
the <a
|
||||
href="https://www.cairographics.org/manual/cairo-cairo-t.html">cairo_t
|
||||
reference</a>.</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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2"></a>draw_clock <span class="op">(</span>GtkDrawingArea <span class="op">*</span>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="cb1-3"><a href="#cb1-3"></a></span>
|
||||
<span id="cb1-4"><a href="#cb1-4"></a> <span class="co">// Scale to unit square and translate (0, 0) to be (0.5, 0.5), i.e.</span></span>
|
||||
<span id="cb1-5"><a href="#cb1-5"></a> <span class="co">// the center of the window</span></span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a> cairo_scale(cr, width, height);</span>
|
||||
<span id="cb1-7"><a href="#cb1-7"></a> cairo_translate(cr, <span class="fl">0.5</span>, <span class="fl">0.5</span>);</span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a> cairo_scale<span class="op">(</span>cr<span class="op">,</span> width<span class="op">,</span> height<span class="op">);</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7"></a> cairo_translate<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.5</span><span class="op">,</span> <span class="fl">0.5</span><span class="op">);</span></span>
|
||||
<span id="cb1-8"><a href="#cb1-8"></a></span>
|
||||
<span id="cb1-9"><a href="#cb1-9"></a> <span class="co">// Set the line width and save the cairo drawing state.</span></span>
|
||||
<span id="cb1-10"><a href="#cb1-10"></a> cairo_set_line_width(cr, m_line_width);</span>
|
||||
<span id="cb1-11"><a href="#cb1-11"></a> cairo_save(cr);</span>
|
||||
<span id="cb1-10"><a href="#cb1-10"></a> cairo_set_line_width<span class="op">(</span>cr<span class="op">,</span> m_line_width<span class="op">);</span></span>
|
||||
<span id="cb1-11"><a href="#cb1-11"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-12"><a href="#cb1-12"></a></span>
|
||||
<span id="cb1-13"><a href="#cb1-13"></a> <span class="co">// Set the background to a slightly transparent green.</span></span>
|
||||
<span id="cb1-14"><a href="#cb1-14"></a> cairo_set_source_rgba(cr, <span class="fl">0.337</span>, <span class="fl">0.612</span>, <span class="fl">0.117</span>, <span class="fl">0.9</span>); <span class="co">// green</span></span>
|
||||
<span id="cb1-15"><a href="#cb1-15"></a> cairo_paint(cr);</span>
|
||||
<span id="cb1-14"><a href="#cb1-14"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.337</span><span class="op">,</span> <span class="fl">0.612</span><span class="op">,</span> <span class="fl">0.117</span><span class="op">,</span> <span class="fl">0.9</span><span class="op">);</span> <span class="co">// green</span></span>
|
||||
<span id="cb1-15"><a href="#cb1-15"></a> cairo_paint<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-16"><a href="#cb1-16"></a></span>
|
||||
<span id="cb1-17"><a href="#cb1-17"></a> <span class="co">// Resore back to precious drawing state and draw the circular path</span></span>
|
||||
<span id="cb1-18"><a href="#cb1-18"></a> <span class="co">// representing the clockface. Save this state (including the path) so we</span></span>
|
||||
<span id="cb1-19"><a href="#cb1-19"></a> <span class="co">// can reuse it.</span></span>
|
||||
<span id="cb1-20"><a href="#cb1-20"></a> cairo_restore(cr);</span>
|
||||
<span id="cb1-21"><a href="#cb1-21"></a> cairo_arc(cr, <span class="fl">0.0</span>, <span class="fl">0.0</span>, m_radius, <span class="fl">0.0</span>, <span class="fl">2.0</span> * M_PI);</span>
|
||||
<span id="cb1-22"><a href="#cb1-22"></a> cairo_save(cr);</span>
|
||||
<span id="cb1-20"><a href="#cb1-20"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-21"><a href="#cb1-21"></a> cairo_arc<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> m_radius<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">2.0</span> <span class="op">*</span> M_PI<span class="op">);</span></span>
|
||||
<span id="cb1-22"><a href="#cb1-22"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-23"><a href="#cb1-23"></a></span>
|
||||
<span id="cb1-24"><a href="#cb1-24"></a> <span class="co">// Fill the clockface with white</span></span>
|
||||
<span id="cb1-25"><a href="#cb1-25"></a> cairo_set_source_rgba(cr, <span class="fl">1.0</span>, <span class="fl">1.0</span>, <span class="fl">1.0</span>, <span class="fl">0.8</span>);</span>
|
||||
<span id="cb1-26"><a href="#cb1-26"></a> cairo_fill_preserve(cr);</span>
|
||||
<span id="cb1-25"><a href="#cb1-25"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">1.0</span><span class="op">,</span> <span class="fl">1.0</span><span class="op">,</span> <span class="fl">1.0</span><span class="op">,</span> <span class="fl">0.8</span><span class="op">);</span></span>
|
||||
<span id="cb1-26"><a href="#cb1-26"></a> cairo_fill_preserve<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-27"><a href="#cb1-27"></a> <span class="co">// Restore the path, paint the outside of the clock face.</span></span>
|
||||
<span id="cb1-28"><a href="#cb1-28"></a> cairo_restore(cr);</span>
|
||||
<span id="cb1-29"><a href="#cb1-29"></a> cairo_stroke_preserve(cr);</span>
|
||||
<span id="cb1-28"><a href="#cb1-28"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-29"><a href="#cb1-29"></a> cairo_stroke_preserve<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-30"><a href="#cb1-30"></a> <span class="co">// Set the 'clip region' to the inside of the path (fill region).</span></span>
|
||||
<span id="cb1-31"><a href="#cb1-31"></a> cairo_clip(cr);</span>
|
||||
<span id="cb1-31"><a href="#cb1-31"></a> cairo_clip<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-32"><a href="#cb1-32"></a></span>
|
||||
<span id="cb1-33"><a href="#cb1-33"></a> <span class="co">// Clock ticks</span></span>
|
||||
<span id="cb1-34"><a href="#cb1-34"></a> <span class="cf">for</span> (<span class="dt">int</span> i = <span class="dv">0</span>; i < <span class="dv">12</span>; i++)</span>
|
||||
<span id="cb1-35"><a href="#cb1-35"></a> {</span>
|
||||
<span id="cb1-34"><a href="#cb1-34"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> <span class="dv">12</span><span class="op">;</span> i<span class="op">++)</span></span>
|
||||
<span id="cb1-35"><a href="#cb1-35"></a> <span class="op">{</span></span>
|
||||
<span id="cb1-36"><a href="#cb1-36"></a> <span class="co">// Major tick size</span></span>
|
||||
<span id="cb1-37"><a href="#cb1-37"></a> <span class="dt">double</span> inset = <span class="fl">0.05</span>;</span>
|
||||
<span id="cb1-37"><a href="#cb1-37"></a> <span class="dt">double</span> inset <span class="op">=</span> <span class="fl">0.05</span><span class="op">;</span></span>
|
||||
<span id="cb1-38"><a href="#cb1-38"></a></span>
|
||||
<span id="cb1-39"><a href="#cb1-39"></a> <span class="co">// Save the graphics state, restore after drawing tick to maintain pen</span></span>
|
||||
<span id="cb1-40"><a href="#cb1-40"></a> <span class="co">// size</span></span>
|
||||
<span id="cb1-41"><a href="#cb1-41"></a> cairo_save(cr);</span>
|
||||
<span id="cb1-42"><a href="#cb1-42"></a> cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);</span>
|
||||
<span id="cb1-41"><a href="#cb1-41"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-42"><a href="#cb1-42"></a> cairo_set_line_cap<span class="op">(</span>cr<span class="op">,</span> CAIRO_LINE_CAP_ROUND<span class="op">);</span></span>
|
||||
<span id="cb1-43"><a href="#cb1-43"></a></span>
|
||||
<span id="cb1-44"><a href="#cb1-44"></a> <span class="co">// Minor ticks are shorter, and narrower.</span></span>
|
||||
<span id="cb1-45"><a href="#cb1-45"></a> <span class="cf">if</span>(i % <span class="dv">3</span> != <span class="dv">0</span>)</span>
|
||||
<span id="cb1-46"><a href="#cb1-46"></a> {</span>
|
||||
<span id="cb1-47"><a href="#cb1-47"></a> inset *= <span class="fl">0.8</span>;</span>
|
||||
<span id="cb1-48"><a href="#cb1-48"></a> cairo_set_line_width(cr, <span class="fl">0.03</span>);</span>
|
||||
<span id="cb1-49"><a href="#cb1-49"></a> }</span>
|
||||
<span id="cb1-45"><a href="#cb1-45"></a> <span class="cf">if</span><span class="op">(</span>i <span class="op">%</span> <span class="dv">3</span> <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb1-46"><a href="#cb1-46"></a> <span class="op">{</span></span>
|
||||
<span id="cb1-47"><a href="#cb1-47"></a> inset <span class="op">*=</span> <span class="fl">0.8</span><span class="op">;</span></span>
|
||||
<span id="cb1-48"><a href="#cb1-48"></a> cairo_set_line_width<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.03</span><span class="op">);</span></span>
|
||||
<span id="cb1-49"><a href="#cb1-49"></a> <span class="op">}</span></span>
|
||||
<span id="cb1-50"><a href="#cb1-50"></a></span>
|
||||
<span id="cb1-51"><a href="#cb1-51"></a> <span class="co">// Draw tick mark</span></span>
|
||||
<span id="cb1-52"><a href="#cb1-52"></a> cairo_move_to(</span>
|
||||
<span id="cb1-53"><a href="#cb1-53"></a> cr,</span>
|
||||
<span id="cb1-54"><a href="#cb1-54"></a> (m_radius - inset) * cos (i * M_PI / <span class="fl">6.0</span>),</span>
|
||||
<span id="cb1-55"><a href="#cb1-55"></a> (m_radius - inset) * sin (i * M_PI / <span class="fl">6.0</span>));</span>
|
||||
<span id="cb1-56"><a href="#cb1-56"></a> cairo_line_to(</span>
|
||||
<span id="cb1-57"><a href="#cb1-57"></a> cr,</span>
|
||||
<span id="cb1-58"><a href="#cb1-58"></a> m_radius * cos (i * M_PI / <span class="fl">6.0</span>),</span>
|
||||
<span id="cb1-59"><a href="#cb1-59"></a> m_radius * sin (i * M_PI / <span class="fl">6.0</span>));</span>
|
||||
<span id="cb1-60"><a href="#cb1-60"></a> cairo_stroke(cr);</span>
|
||||
<span id="cb1-61"><a href="#cb1-61"></a> cairo_restore(cr); <span class="co">/* stack-pen-size */</span></span>
|
||||
<span id="cb1-62"><a href="#cb1-62"></a> }</span>
|
||||
<span id="cb1-52"><a href="#cb1-52"></a> cairo_move_to<span class="op">(</span></span>
|
||||
<span id="cb1-53"><a href="#cb1-53"></a> cr<span class="op">,</span></span>
|
||||
<span id="cb1-54"><a href="#cb1-54"></a> <span class="op">(</span>m_radius <span class="op">-</span> inset<span class="op">)</span> <span class="op">*</span> cos <span class="op">(</span>i <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">),</span></span>
|
||||
<span id="cb1-55"><a href="#cb1-55"></a> <span class="op">(</span>m_radius <span class="op">-</span> inset<span class="op">)</span> <span class="op">*</span> sin <span class="op">(</span>i <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">));</span></span>
|
||||
<span id="cb1-56"><a href="#cb1-56"></a> cairo_line_to<span class="op">(</span></span>
|
||||
<span id="cb1-57"><a href="#cb1-57"></a> cr<span class="op">,</span></span>
|
||||
<span id="cb1-58"><a href="#cb1-58"></a> m_radius <span class="op">*</span> cos <span class="op">(</span>i <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">),</span></span>
|
||||
<span id="cb1-59"><a href="#cb1-59"></a> m_radius <span class="op">*</span> sin <span class="op">(</span>i <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">));</span></span>
|
||||
<span id="cb1-60"><a href="#cb1-60"></a> cairo_stroke<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-61"><a href="#cb1-61"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span> <span class="co">/* stack-pen-size */</span></span>
|
||||
<span id="cb1-62"><a href="#cb1-62"></a> <span class="op">}</span></span>
|
||||
<span id="cb1-63"><a href="#cb1-63"></a></span>
|
||||
<span id="cb1-64"><a href="#cb1-64"></a> <span class="co">// Draw the analog hands</span></span>
|
||||
<span id="cb1-65"><a href="#cb1-65"></a></span>
|
||||
<span id="cb1-66"><a href="#cb1-66"></a> <span class="co">// Get the current Unix time, convert to the local time and break into time</span></span>
|
||||
<span id="cb1-67"><a href="#cb1-67"></a> <span class="co">// structure to read various time parts.</span></span>
|
||||
<span id="cb1-68"><a href="#cb1-68"></a> <span class="dt">time_t</span> rawtime;</span>
|
||||
<span id="cb1-69"><a href="#cb1-69"></a> time(&rawtime);</span>
|
||||
<span id="cb1-70"><a href="#cb1-70"></a> <span class="kw">struct</span> tm * timeinfo = localtime (&rawtime);</span>
|
||||
<span id="cb1-68"><a href="#cb1-68"></a> <span class="dt">time_t</span> rawtime<span class="op">;</span></span>
|
||||
<span id="cb1-69"><a href="#cb1-69"></a> time<span class="op">(&</span>rawtime<span class="op">);</span></span>
|
||||
<span id="cb1-70"><a href="#cb1-70"></a> <span class="kw">struct</span> tm <span class="op">*</span> timeinfo <span class="op">=</span> localtime <span class="op">(&</span>rawtime<span class="op">);</span></span>
|
||||
<span id="cb1-71"><a href="#cb1-71"></a></span>
|
||||
<span id="cb1-72"><a href="#cb1-72"></a> <span class="co">// Calculate the angles of the hands of our clock</span></span>
|
||||
<span id="cb1-73"><a href="#cb1-73"></a> <span class="dt">double</span> hours = timeinfo->tm_hour * M_PI / <span class="fl">6.0</span>;</span>
|
||||
<span id="cb1-74"><a href="#cb1-74"></a> <span class="dt">double</span> minutes = timeinfo->tm_min * M_PI / <span class="fl">30.0</span>;</span>
|
||||
<span id="cb1-75"><a href="#cb1-75"></a> <span class="dt">double</span> seconds = timeinfo->tm_sec * M_PI / <span class="fl">30.0</span>;</span>
|
||||
<span id="cb1-73"><a href="#cb1-73"></a> <span class="dt">double</span> hours <span class="op">=</span> timeinfo<span class="op">-></span>tm_hour <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">;</span></span>
|
||||
<span id="cb1-74"><a href="#cb1-74"></a> <span class="dt">double</span> minutes <span class="op">=</span> timeinfo<span class="op">-></span>tm_min <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">30.0</span><span class="op">;</span></span>
|
||||
<span id="cb1-75"><a href="#cb1-75"></a> <span class="dt">double</span> seconds <span class="op">=</span> timeinfo<span class="op">-></span>tm_sec <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">30.0</span><span class="op">;</span></span>
|
||||
<span id="cb1-76"><a href="#cb1-76"></a></span>
|
||||
<span id="cb1-77"><a href="#cb1-77"></a> <span class="co">// Save the graphics state</span></span>
|
||||
<span id="cb1-78"><a href="#cb1-78"></a> cairo_save(cr);</span>
|
||||
<span id="cb1-79"><a href="#cb1-79"></a> cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);</span>
|
||||
<span id="cb1-78"><a href="#cb1-78"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-79"><a href="#cb1-79"></a> cairo_set_line_cap<span class="op">(</span>cr<span class="op">,</span> CAIRO_LINE_CAP_ROUND<span class="op">);</span></span>
|
||||
<span id="cb1-80"><a href="#cb1-80"></a></span>
|
||||
<span id="cb1-81"><a href="#cb1-81"></a> cairo_save(cr);</span>
|
||||
<span id="cb1-81"><a href="#cb1-81"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-82"><a href="#cb1-82"></a></span>
|
||||
<span id="cb1-83"><a href="#cb1-83"></a> <span class="co">// Draw the seconds hand</span></span>
|
||||
<span id="cb1-84"><a href="#cb1-84"></a> cairo_set_line_width(cr, m_line_width / <span class="fl">3.0</span>);</span>
|
||||
<span id="cb1-85"><a href="#cb1-85"></a> cairo_set_source_rgba(cr, <span class="fl">0.7</span>, <span class="fl">0.7</span>, <span class="fl">0.7</span>, <span class="fl">0.8</span>); <span class="co">// gray</span></span>
|
||||
<span id="cb1-86"><a href="#cb1-86"></a> cairo_move_to(cr, <span class="fl">0.0</span>, <span class="fl">0.0</span>);</span>
|
||||
<span id="cb1-87"><a href="#cb1-87"></a> cairo_line_to(cr,</span>
|
||||
<span id="cb1-88"><a href="#cb1-88"></a> sin(seconds) * (m_radius * <span class="fl">0.9</span>),</span>
|
||||
<span id="cb1-89"><a href="#cb1-89"></a> -cos(seconds) * (m_radius * <span class="fl">0.9</span>));</span>
|
||||
<span id="cb1-90"><a href="#cb1-90"></a> cairo_stroke(cr);</span>
|
||||
<span id="cb1-91"><a href="#cb1-91"></a> cairo_restore(cr);</span>
|
||||
<span id="cb1-84"><a href="#cb1-84"></a> cairo_set_line_width<span class="op">(</span>cr<span class="op">,</span> m_line_width <span class="op">/</span> <span class="fl">3.0</span><span class="op">);</span></span>
|
||||
<span id="cb1-85"><a href="#cb1-85"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.7</span><span class="op">,</span> <span class="fl">0.7</span><span class="op">,</span> <span class="fl">0.7</span><span class="op">,</span> <span class="fl">0.8</span><span class="op">);</span> <span class="co">// gray</span></span>
|
||||
<span id="cb1-86"><a href="#cb1-86"></a> cairo_move_to<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">);</span></span>
|
||||
<span id="cb1-87"><a href="#cb1-87"></a> cairo_line_to<span class="op">(</span>cr<span class="op">,</span></span>
|
||||
<span id="cb1-88"><a href="#cb1-88"></a> sin<span class="op">(</span>seconds<span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.9</span><span class="op">),</span></span>
|
||||
<span id="cb1-89"><a href="#cb1-89"></a> <span class="op">-</span>cos<span class="op">(</span>seconds<span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.9</span><span class="op">));</span></span>
|
||||
<span id="cb1-90"><a href="#cb1-90"></a> cairo_stroke<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-91"><a href="#cb1-91"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-92"><a href="#cb1-92"></a></span>
|
||||
<span id="cb1-93"><a href="#cb1-93"></a> <span class="co">// Draw the minutes hand</span></span>
|
||||
<span id="cb1-94"><a href="#cb1-94"></a> cairo_set_source_rgba(cr, <span class="fl">0.117</span>, <span class="fl">0.337</span>, <span class="fl">0.612</span>, <span class="fl">0.9</span>); <span class="co">// blue</span></span>
|
||||
<span id="cb1-95"><a href="#cb1-95"></a> cairo_move_to(cr, <span class="dv">0</span>, <span class="dv">0</span>);</span>
|
||||
<span id="cb1-96"><a href="#cb1-96"></a> cairo_line_to(cr,</span>
|
||||
<span id="cb1-97"><a href="#cb1-97"></a> sin(minutes + seconds / <span class="dv">60</span>) * (m_radius * <span class="fl">0.8</span>),</span>
|
||||
<span id="cb1-98"><a href="#cb1-98"></a> -cos(minutes + seconds / <span class="dv">60</span>) * (m_radius * <span class="fl">0.8</span>));</span>
|
||||
<span id="cb1-99"><a href="#cb1-99"></a> cairo_stroke(cr);</span>
|
||||
<span id="cb1-94"><a href="#cb1-94"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.117</span><span class="op">,</span> <span class="fl">0.337</span><span class="op">,</span> <span class="fl">0.612</span><span class="op">,</span> <span class="fl">0.9</span><span class="op">);</span> <span class="co">// blue</span></span>
|
||||
<span id="cb1-95"><a href="#cb1-95"></a> cairo_move_to<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>
|
||||
<span id="cb1-96"><a href="#cb1-96"></a> cairo_line_to<span class="op">(</span>cr<span class="op">,</span></span>
|
||||
<span id="cb1-97"><a href="#cb1-97"></a> sin<span class="op">(</span>minutes <span class="op">+</span> seconds <span class="op">/</span> <span class="dv">60</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.8</span><span class="op">),</span></span>
|
||||
<span id="cb1-98"><a href="#cb1-98"></a> <span class="op">-</span>cos<span class="op">(</span>minutes <span class="op">+</span> seconds <span class="op">/</span> <span class="dv">60</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.8</span><span class="op">));</span></span>
|
||||
<span id="cb1-99"><a href="#cb1-99"></a> cairo_stroke<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-100"><a href="#cb1-100"></a></span>
|
||||
<span id="cb1-101"><a href="#cb1-101"></a> <span class="co">// draw the hours hand</span></span>
|
||||
<span id="cb1-102"><a href="#cb1-102"></a> cairo_set_source_rgba(cr, <span class="fl">0.337</span>, <span class="fl">0.612</span>, <span class="fl">0.117</span>, <span class="fl">0.9</span>); <span class="co">// green</span></span>
|
||||
<span id="cb1-103"><a href="#cb1-103"></a> cairo_move_to(cr, <span class="fl">0.0</span>, <span class="fl">0.0</span>);</span>
|
||||
<span id="cb1-104"><a href="#cb1-104"></a> cairo_line_to(cr,</span>
|
||||
<span id="cb1-105"><a href="#cb1-105"></a> sin(hours + minutes / <span class="fl">12.0</span>) * (m_radius * <span class="fl">0.5</span>),</span>
|
||||
<span id="cb1-106"><a href="#cb1-106"></a> -cos(hours + minutes / <span class="fl">12.0</span>) * (m_radius * <span class="fl">0.5</span>));</span>
|
||||
<span id="cb1-107"><a href="#cb1-107"></a> cairo_stroke(cr);</span>
|
||||
<span id="cb1-108"><a href="#cb1-108"></a> cairo_restore(cr);</span>
|
||||
<span id="cb1-102"><a href="#cb1-102"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.337</span><span class="op">,</span> <span class="fl">0.612</span><span class="op">,</span> <span class="fl">0.117</span><span class="op">,</span> <span class="fl">0.9</span><span class="op">);</span> <span class="co">// green</span></span>
|
||||
<span id="cb1-103"><a href="#cb1-103"></a> cairo_move_to<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">);</span></span>
|
||||
<span id="cb1-104"><a href="#cb1-104"></a> cairo_line_to<span class="op">(</span>cr<span class="op">,</span></span>
|
||||
<span id="cb1-105"><a href="#cb1-105"></a> sin<span class="op">(</span>hours <span class="op">+</span> minutes <span class="op">/</span> <span class="fl">12.0</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.5</span><span class="op">),</span></span>
|
||||
<span id="cb1-106"><a href="#cb1-106"></a> <span class="op">-</span>cos<span class="op">(</span>hours <span class="op">+</span> minutes <span class="op">/</span> <span class="fl">12.0</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.5</span><span class="op">));</span></span>
|
||||
<span id="cb1-107"><a href="#cb1-107"></a> cairo_stroke<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-108"><a href="#cb1-108"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-109"><a href="#cb1-109"></a></span>
|
||||
<span id="cb1-110"><a href="#cb1-110"></a> <span class="co">// Draw a little dot in the middle</span></span>
|
||||
<span id="cb1-111"><a href="#cb1-111"></a> cairo_arc(cr, <span class="fl">0.0</span>, <span class="fl">0.0</span>, m_line_width / <span class="fl">3.0</span>, <span class="fl">0.0</span>, <span class="fl">2.0</span> * M_PI);</span>
|
||||
<span id="cb1-112"><a href="#cb1-112"></a> cairo_fill(cr);</span>
|
||||
<span id="cb1-113"><a href="#cb1-113"></a>}</span></code></pre></div>
|
||||
<p>In order for the clock to be drawn, the drawing function <code>draw_clock()</code> needs to be registered with GTK4. This is done in the <code>app_activate()</code> function (on line 24).</p>
|
||||
<p>Whenever the application needs to redraw the GtkDrawingArea, it will now call <code>draw_clock()</code>.</p>
|
||||
<p>There is still a problem though. In order to animate the clock we need to also tell the application that the clock needs to be redrawn every second. This process starts by registering (on the next line, line 15) a timeout function with <code>g_timeout_add()</code> that will wakeup and run another function <code>time_handler</code>, every second (or 1000ms).</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2"></a>app_activate (GApplication *app, gpointer user_data) {</span>
|
||||
<span id="cb2-3"><a href="#cb2-3"></a> GtkWidget *win;</span>
|
||||
<span id="cb2-4"><a href="#cb2-4"></a> GtkWidget *clock;</span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a> GtkBuilder *build;</span>
|
||||
<span id="cb1-111"><a href="#cb1-111"></a> cairo_arc<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> m_line_width <span class="op">/</span> <span class="fl">3.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">2.0</span> <span class="op">*</span> M_PI<span class="op">);</span></span>
|
||||
<span id="cb1-112"><a href="#cb1-112"></a> cairo_fill<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb1-113"><a href="#cb1-113"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>In order for the clock to be drawn, the drawing function
|
||||
<code>draw_clock()</code> needs to be registered with GTK4. This is done
|
||||
in the <code>app_activate()</code> function (on line 24).</p>
|
||||
<p>Whenever the application needs to redraw the GtkDrawingArea, it will
|
||||
now call <code>draw_clock()</code>.</p>
|
||||
<p>There is still a problem though. In order to animate the clock we
|
||||
need to also tell the application that the clock needs to be redrawn
|
||||
every second. This process starts by registering (on the next line, line
|
||||
15) a timeout function with <code>g_timeout_add()</code> that will
|
||||
wakeup and run another function <code>time_handler</code>, every second
|
||||
(or 1000ms).</p>
|
||||
<div class="sourceCode" id="cb2"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
||||
<span id="cb2-4"><a href="#cb2-4"></a> GtkWidget <span class="op">*</span>clock<span class="op">;</span></span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
|
||||
<span id="cb2-6"><a href="#cb2-6"></a></span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a> build = gtk_builder_new_from_resource (<span class="st">"/com/github/ToshioCP/tfc/tfc.ui"</span>);</span>
|
||||
<span id="cb2-8"><a href="#cb2-8"></a> win = GTK_WIDGET (gtk_builder_get_object (build, <span class="st">"win"</span>));</span>
|
||||
<span id="cb2-9"><a href="#cb2-9"></a> gtk_window_set_application (GTK_WINDOW (win), GTK_APPLICATION (app));</span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">"/com/github/ToshioCP/tfc/tfc.ui"</span><span class="op">);</span></span>
|
||||
<span id="cb2-8"><a href="#cb2-8"></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="cb2-9"><a href="#cb2-9"></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="cb2-10"><a href="#cb2-10"></a></span>
|
||||
<span id="cb2-11"><a href="#cb2-11"></a> clock = GTK_WIDGET (gtk_builder_get_object (build, <span class="st">"clock"</span>));</span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> g_object_unref(build);</span>
|
||||
<span id="cb2-11"><a href="#cb2-11"></a> clock <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">"clock"</span><span class="op">));</span></span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> g_object_unref<span class="op">(</span>build<span class="op">);</span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13"></a></span>
|
||||
<span id="cb2-14"><a href="#cb2-14"></a> gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA (clock), draw_clock, NULL, NULL);</span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a> g_timeout_add(<span class="dv">1000</span>, (GSourceFunc) time_handler, (gpointer) clock);</span>
|
||||
<span id="cb2-16"><a href="#cb2-16"></a> gtk_widget_show(win);</span>
|
||||
<span id="cb2-14"><a href="#cb2-14"></a> gtk_drawing_area_set_draw_func<span class="op">(</span>GTK_DRAWING_AREA <span class="op">(</span>clock<span class="op">),</span> draw_clock<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a> g_timeout_add<span class="op">(</span><span class="dv">1000</span><span class="op">,</span> <span class="op">(</span>GSourceFunc<span class="op">)</span> time_handler<span class="op">,</span> <span class="op">(</span>gpointer<span class="op">)</span> clock<span class="op">);</span></span>
|
||||
<span id="cb2-16"><a href="#cb2-16"></a> gtk_widget_show<span class="op">(</span>win<span class="op">);</span></span>
|
||||
<span id="cb2-17"><a href="#cb2-17"></a></span>
|
||||
<span id="cb2-18"><a href="#cb2-18"></a>}</span></code></pre></div>
|
||||
<p>Our <code>time_handler()</code> function is very simple, as it just calls <code>gtk_widget_queue_draw()</code> which schedules a redraw of the widget.</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>gboolean</span>
|
||||
<span id="cb3-2"><a href="#cb3-2"></a>time_handler(GtkWidget* widget) {</span>
|
||||
<span id="cb3-3"><a href="#cb3-3"></a> gtk_widget_queue_draw(widget);</span>
|
||||
<span id="cb2-18"><a href="#cb2-18"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>Our <code>time_handler()</code> function is very simple, as it just
|
||||
calls <code>gtk_widget_queue_draw()</code> which schedules a redraw of
|
||||
the widget.</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>gboolean</span>
|
||||
<span id="cb3-2"><a href="#cb3-2"></a>time_handler<span class="op">(</span>GtkWidget<span class="op">*</span> widget<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb3-3"><a href="#cb3-3"></a> gtk_widget_queue_draw<span class="op">(</span>widget<span class="op">);</span></span>
|
||||
<span id="cb3-4"><a href="#cb3-4"></a></span>
|
||||
<span id="cb3-5"><a href="#cb3-5"></a> <span class="cf">return</span> TRUE;</span>
|
||||
<span id="cb3-6"><a href="#cb3-6"></a>}</span></code></pre></div>
|
||||
<p>.. and that is all there is to it. If you compile and run the example you will get a ticking analog clock.</p>
|
||||
<p>If you get this working, you can try modifying some of the code in <code>draw_clock()</code> to tweak the application (such as change the color or size and length of the hands) or even add text, or create a digital clock.</p>
|
||||
<span id="cb3-5"><a href="#cb3-5"></a> <span class="cf">return</span> TRUE<span class="op">;</span></span>
|
||||
<span id="cb3-6"><a href="#cb3-6"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>.. and that is all there is to it. If you compile and run the example
|
||||
you will get a ticking analog clock.</p>
|
||||
<p>If you get this working, you can try modifying some of the code in
|
||||
<code>draw_clock()</code> to tweak the application (such as change the
|
||||
color or size and length of the hands) or even add text, or create a
|
||||
digital clock.</p>
|
||||
<h2 id="the-complete-code">The Complete code</h2>
|
||||
<p>You can find the source files in the <code>tfc</code> directory. it can be compiled with <code>./comp tfc</code>.</p>
|
||||
<p>You can find the source files in the <code>tfc</code> directory. it
|
||||
can be compiled with <code>./comp tfc</code>.</p>
|
||||
<p><code>tfc.c</code></p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<div class="sourceCode" id="cb4"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb4-2"><a href="#cb4-2"></a><span class="pp">#include </span><span class="im"><math.h></span></span>
|
||||
<span id="cb4-3"><a href="#cb4-3"></a><span class="pp">#include </span><span class="im"><time.h></span></span>
|
||||
<span id="cb4-4"><a href="#cb4-4"></a></span>
|
||||
<span id="cb4-5"><a href="#cb4-5"></a><span class="dt">float</span> m_radius = <span class="fl">0.42</span>;</span>
|
||||
<span id="cb4-6"><a href="#cb4-6"></a><span class="dt">float</span> m_line_width = <span class="fl">0.05</span>;</span>
|
||||
<span id="cb4-5"><a href="#cb4-5"></a><span class="dt">float</span> m_radius <span class="op">=</span> <span class="fl">0.42</span><span class="op">;</span></span>
|
||||
<span id="cb4-6"><a href="#cb4-6"></a><span class="dt">float</span> m_line_width <span class="op">=</span> <span class="fl">0.05</span><span class="op">;</span></span>
|
||||
<span id="cb4-7"><a href="#cb4-7"></a></span>
|
||||
<span id="cb4-8"><a href="#cb4-8"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb4-9"><a href="#cb4-9"></a>draw_clock (GtkDrawingArea *area, cairo_t *cr, <span class="dt">int</span> width, <span class="dt">int</span> height, gpointer user_data) {</span>
|
||||
<span id="cb4-9"><a href="#cb4-9"></a>draw_clock <span class="op">(</span>GtkDrawingArea <span class="op">*</span>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="cb4-10"><a href="#cb4-10"></a></span>
|
||||
<span id="cb4-11"><a href="#cb4-11"></a> <span class="co">// Scale to unit square and translate (0, 0) to be (0.5, 0.5), i.e.</span></span>
|
||||
<span id="cb4-12"><a href="#cb4-12"></a> <span class="co">// the center of the window</span></span>
|
||||
<span id="cb4-13"><a href="#cb4-13"></a> cairo_scale(cr, width, height);</span>
|
||||
<span id="cb4-14"><a href="#cb4-14"></a> cairo_translate(cr, <span class="fl">0.5</span>, <span class="fl">0.5</span>);</span>
|
||||
<span id="cb4-13"><a href="#cb4-13"></a> cairo_scale<span class="op">(</span>cr<span class="op">,</span> width<span class="op">,</span> height<span class="op">);</span></span>
|
||||
<span id="cb4-14"><a href="#cb4-14"></a> cairo_translate<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.5</span><span class="op">,</span> <span class="fl">0.5</span><span class="op">);</span></span>
|
||||
<span id="cb4-15"><a href="#cb4-15"></a></span>
|
||||
<span id="cb4-16"><a href="#cb4-16"></a> <span class="co">// Set the line width and save the cairo drawing state.</span></span>
|
||||
<span id="cb4-17"><a href="#cb4-17"></a> cairo_set_line_width(cr, m_line_width);</span>
|
||||
<span id="cb4-18"><a href="#cb4-18"></a> cairo_save(cr);</span>
|
||||
<span id="cb4-17"><a href="#cb4-17"></a> cairo_set_line_width<span class="op">(</span>cr<span class="op">,</span> m_line_width<span class="op">);</span></span>
|
||||
<span id="cb4-18"><a href="#cb4-18"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-19"><a href="#cb4-19"></a></span>
|
||||
<span id="cb4-20"><a href="#cb4-20"></a> <span class="co">// Set the background to a slightly transparent green.</span></span>
|
||||
<span id="cb4-21"><a href="#cb4-21"></a> cairo_set_source_rgba(cr, <span class="fl">0.337</span>, <span class="fl">0.612</span>, <span class="fl">0.117</span>, <span class="fl">0.9</span>); <span class="co">// green</span></span>
|
||||
<span id="cb4-22"><a href="#cb4-22"></a> cairo_paint(cr);</span>
|
||||
<span id="cb4-21"><a href="#cb4-21"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.337</span><span class="op">,</span> <span class="fl">0.612</span><span class="op">,</span> <span class="fl">0.117</span><span class="op">,</span> <span class="fl">0.9</span><span class="op">);</span> <span class="co">// green</span></span>
|
||||
<span id="cb4-22"><a href="#cb4-22"></a> cairo_paint<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-23"><a href="#cb4-23"></a></span>
|
||||
<span id="cb4-24"><a href="#cb4-24"></a> <span class="co">// Resore back to precious drawing state and draw the circular path</span></span>
|
||||
<span id="cb4-25"><a href="#cb4-25"></a> <span class="co">// representing the clockface. Save this state (including the path) so we</span></span>
|
||||
<span id="cb4-26"><a href="#cb4-26"></a> <span class="co">// can reuse it.</span></span>
|
||||
<span id="cb4-27"><a href="#cb4-27"></a> cairo_restore(cr);</span>
|
||||
<span id="cb4-28"><a href="#cb4-28"></a> cairo_arc(cr, <span class="fl">0.0</span>, <span class="fl">0.0</span>, m_radius, <span class="fl">0.0</span>, <span class="fl">2.0</span> * M_PI);</span>
|
||||
<span id="cb4-29"><a href="#cb4-29"></a> cairo_save(cr);</span>
|
||||
<span id="cb4-27"><a href="#cb4-27"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-28"><a href="#cb4-28"></a> cairo_arc<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> m_radius<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">2.0</span> <span class="op">*</span> M_PI<span class="op">);</span></span>
|
||||
<span id="cb4-29"><a href="#cb4-29"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-30"><a href="#cb4-30"></a></span>
|
||||
<span id="cb4-31"><a href="#cb4-31"></a> <span class="co">// Fill the clockface with white</span></span>
|
||||
<span id="cb4-32"><a href="#cb4-32"></a> cairo_set_source_rgba(cr, <span class="fl">1.0</span>, <span class="fl">1.0</span>, <span class="fl">1.0</span>, <span class="fl">0.8</span>);</span>
|
||||
<span id="cb4-33"><a href="#cb4-33"></a> cairo_fill_preserve(cr);</span>
|
||||
<span id="cb4-32"><a href="#cb4-32"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">1.0</span><span class="op">,</span> <span class="fl">1.0</span><span class="op">,</span> <span class="fl">1.0</span><span class="op">,</span> <span class="fl">0.8</span><span class="op">);</span></span>
|
||||
<span id="cb4-33"><a href="#cb4-33"></a> cairo_fill_preserve<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-34"><a href="#cb4-34"></a> <span class="co">// Restore the path, paint the outside of the clock face.</span></span>
|
||||
<span id="cb4-35"><a href="#cb4-35"></a> cairo_restore(cr);</span>
|
||||
<span id="cb4-36"><a href="#cb4-36"></a> cairo_stroke_preserve(cr);</span>
|
||||
<span id="cb4-35"><a href="#cb4-35"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-36"><a href="#cb4-36"></a> cairo_stroke_preserve<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-37"><a href="#cb4-37"></a> <span class="co">// Set the 'clip region' to the inside of the path (fill region).</span></span>
|
||||
<span id="cb4-38"><a href="#cb4-38"></a> cairo_clip(cr);</span>
|
||||
<span id="cb4-38"><a href="#cb4-38"></a> cairo_clip<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-39"><a href="#cb4-39"></a></span>
|
||||
<span id="cb4-40"><a href="#cb4-40"></a> <span class="co">// Clock ticks</span></span>
|
||||
<span id="cb4-41"><a href="#cb4-41"></a> <span class="cf">for</span> (<span class="dt">int</span> i = <span class="dv">0</span>; i < <span class="dv">12</span>; i++)</span>
|
||||
<span id="cb4-42"><a href="#cb4-42"></a> {</span>
|
||||
<span id="cb4-41"><a href="#cb4-41"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> <span class="dv">12</span><span class="op">;</span> i<span class="op">++)</span></span>
|
||||
<span id="cb4-42"><a href="#cb4-42"></a> <span class="op">{</span></span>
|
||||
<span id="cb4-43"><a href="#cb4-43"></a> <span class="co">// Major tick size</span></span>
|
||||
<span id="cb4-44"><a href="#cb4-44"></a> <span class="dt">double</span> inset = <span class="fl">0.05</span>;</span>
|
||||
<span id="cb4-44"><a href="#cb4-44"></a> <span class="dt">double</span> inset <span class="op">=</span> <span class="fl">0.05</span><span class="op">;</span></span>
|
||||
<span id="cb4-45"><a href="#cb4-45"></a></span>
|
||||
<span id="cb4-46"><a href="#cb4-46"></a> <span class="co">// Save the graphics state, restore after drawing tick to maintain pen</span></span>
|
||||
<span id="cb4-47"><a href="#cb4-47"></a> <span class="co">// size</span></span>
|
||||
<span id="cb4-48"><a href="#cb4-48"></a> cairo_save(cr);</span>
|
||||
<span id="cb4-49"><a href="#cb4-49"></a> cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);</span>
|
||||
<span id="cb4-48"><a href="#cb4-48"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-49"><a href="#cb4-49"></a> cairo_set_line_cap<span class="op">(</span>cr<span class="op">,</span> CAIRO_LINE_CAP_ROUND<span class="op">);</span></span>
|
||||
<span id="cb4-50"><a href="#cb4-50"></a></span>
|
||||
<span id="cb4-51"><a href="#cb4-51"></a> <span class="co">// Minor ticks are shorter, and narrower.</span></span>
|
||||
<span id="cb4-52"><a href="#cb4-52"></a> <span class="cf">if</span>(i % <span class="dv">3</span> != <span class="dv">0</span>)</span>
|
||||
<span id="cb4-53"><a href="#cb4-53"></a> {</span>
|
||||
<span id="cb4-54"><a href="#cb4-54"></a> inset *= <span class="fl">0.8</span>;</span>
|
||||
<span id="cb4-55"><a href="#cb4-55"></a> cairo_set_line_width(cr, <span class="fl">0.03</span>);</span>
|
||||
<span id="cb4-56"><a href="#cb4-56"></a> }</span>
|
||||
<span id="cb4-52"><a href="#cb4-52"></a> <span class="cf">if</span><span class="op">(</span>i <span class="op">%</span> <span class="dv">3</span> <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb4-53"><a href="#cb4-53"></a> <span class="op">{</span></span>
|
||||
<span id="cb4-54"><a href="#cb4-54"></a> inset <span class="op">*=</span> <span class="fl">0.8</span><span class="op">;</span></span>
|
||||
<span id="cb4-55"><a href="#cb4-55"></a> cairo_set_line_width<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.03</span><span class="op">);</span></span>
|
||||
<span id="cb4-56"><a href="#cb4-56"></a> <span class="op">}</span></span>
|
||||
<span id="cb4-57"><a href="#cb4-57"></a></span>
|
||||
<span id="cb4-58"><a href="#cb4-58"></a> <span class="co">// Draw tick mark</span></span>
|
||||
<span id="cb4-59"><a href="#cb4-59"></a> cairo_move_to(</span>
|
||||
<span id="cb4-60"><a href="#cb4-60"></a> cr,</span>
|
||||
<span id="cb4-61"><a href="#cb4-61"></a> (m_radius - inset) * cos (i * M_PI / <span class="fl">6.0</span>),</span>
|
||||
<span id="cb4-62"><a href="#cb4-62"></a> (m_radius - inset) * sin (i * M_PI / <span class="fl">6.0</span>));</span>
|
||||
<span id="cb4-63"><a href="#cb4-63"></a> cairo_line_to(</span>
|
||||
<span id="cb4-64"><a href="#cb4-64"></a> cr,</span>
|
||||
<span id="cb4-65"><a href="#cb4-65"></a> m_radius * cos (i * M_PI / <span class="fl">6.0</span>),</span>
|
||||
<span id="cb4-66"><a href="#cb4-66"></a> m_radius * sin (i * M_PI / <span class="fl">6.0</span>));</span>
|
||||
<span id="cb4-67"><a href="#cb4-67"></a> cairo_stroke(cr);</span>
|
||||
<span id="cb4-68"><a href="#cb4-68"></a> cairo_restore(cr); <span class="co">/* stack-pen-size */</span></span>
|
||||
<span id="cb4-69"><a href="#cb4-69"></a> }</span>
|
||||
<span id="cb4-59"><a href="#cb4-59"></a> cairo_move_to<span class="op">(</span></span>
|
||||
<span id="cb4-60"><a href="#cb4-60"></a> cr<span class="op">,</span></span>
|
||||
<span id="cb4-61"><a href="#cb4-61"></a> <span class="op">(</span>m_radius <span class="op">-</span> inset<span class="op">)</span> <span class="op">*</span> cos <span class="op">(</span>i <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">),</span></span>
|
||||
<span id="cb4-62"><a href="#cb4-62"></a> <span class="op">(</span>m_radius <span class="op">-</span> inset<span class="op">)</span> <span class="op">*</span> sin <span class="op">(</span>i <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">));</span></span>
|
||||
<span id="cb4-63"><a href="#cb4-63"></a> cairo_line_to<span class="op">(</span></span>
|
||||
<span id="cb4-64"><a href="#cb4-64"></a> cr<span class="op">,</span></span>
|
||||
<span id="cb4-65"><a href="#cb4-65"></a> m_radius <span class="op">*</span> cos <span class="op">(</span>i <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">),</span></span>
|
||||
<span id="cb4-66"><a href="#cb4-66"></a> m_radius <span class="op">*</span> sin <span class="op">(</span>i <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">));</span></span>
|
||||
<span id="cb4-67"><a href="#cb4-67"></a> cairo_stroke<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-68"><a href="#cb4-68"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span> <span class="co">/* stack-pen-size */</span></span>
|
||||
<span id="cb4-69"><a href="#cb4-69"></a> <span class="op">}</span></span>
|
||||
<span id="cb4-70"><a href="#cb4-70"></a></span>
|
||||
<span id="cb4-71"><a href="#cb4-71"></a> <span class="co">// Draw the analog hands</span></span>
|
||||
<span id="cb4-72"><a href="#cb4-72"></a></span>
|
||||
<span id="cb4-73"><a href="#cb4-73"></a> <span class="co">// Get the current Unix time, convert to the local time and break into time</span></span>
|
||||
<span id="cb4-74"><a href="#cb4-74"></a> <span class="co">// structure to read various time parts.</span></span>
|
||||
<span id="cb4-75"><a href="#cb4-75"></a> <span class="dt">time_t</span> rawtime;</span>
|
||||
<span id="cb4-76"><a href="#cb4-76"></a> time(&rawtime);</span>
|
||||
<span id="cb4-77"><a href="#cb4-77"></a> <span class="kw">struct</span> tm * timeinfo = localtime (&rawtime);</span>
|
||||
<span id="cb4-75"><a href="#cb4-75"></a> <span class="dt">time_t</span> rawtime<span class="op">;</span></span>
|
||||
<span id="cb4-76"><a href="#cb4-76"></a> time<span class="op">(&</span>rawtime<span class="op">);</span></span>
|
||||
<span id="cb4-77"><a href="#cb4-77"></a> <span class="kw">struct</span> tm <span class="op">*</span> timeinfo <span class="op">=</span> localtime <span class="op">(&</span>rawtime<span class="op">);</span></span>
|
||||
<span id="cb4-78"><a href="#cb4-78"></a></span>
|
||||
<span id="cb4-79"><a href="#cb4-79"></a> <span class="co">// Calculate the angles of the hands of our clock</span></span>
|
||||
<span id="cb4-80"><a href="#cb4-80"></a> <span class="dt">double</span> hours = timeinfo->tm_hour * M_PI / <span class="fl">6.0</span>;</span>
|
||||
<span id="cb4-81"><a href="#cb4-81"></a> <span class="dt">double</span> minutes = timeinfo->tm_min * M_PI / <span class="fl">30.0</span>;</span>
|
||||
<span id="cb4-82"><a href="#cb4-82"></a> <span class="dt">double</span> seconds = timeinfo->tm_sec * M_PI / <span class="fl">30.0</span>;</span>
|
||||
<span id="cb4-80"><a href="#cb4-80"></a> <span class="dt">double</span> hours <span class="op">=</span> timeinfo<span class="op">-></span>tm_hour <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">6.0</span><span class="op">;</span></span>
|
||||
<span id="cb4-81"><a href="#cb4-81"></a> <span class="dt">double</span> minutes <span class="op">=</span> timeinfo<span class="op">-></span>tm_min <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">30.0</span><span class="op">;</span></span>
|
||||
<span id="cb4-82"><a href="#cb4-82"></a> <span class="dt">double</span> seconds <span class="op">=</span> timeinfo<span class="op">-></span>tm_sec <span class="op">*</span> M_PI <span class="op">/</span> <span class="fl">30.0</span><span class="op">;</span></span>
|
||||
<span id="cb4-83"><a href="#cb4-83"></a></span>
|
||||
<span id="cb4-84"><a href="#cb4-84"></a> <span class="co">// Save the graphics state</span></span>
|
||||
<span id="cb4-85"><a href="#cb4-85"></a> cairo_save(cr);</span>
|
||||
<span id="cb4-86"><a href="#cb4-86"></a> cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);</span>
|
||||
<span id="cb4-85"><a href="#cb4-85"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-86"><a href="#cb4-86"></a> cairo_set_line_cap<span class="op">(</span>cr<span class="op">,</span> CAIRO_LINE_CAP_ROUND<span class="op">);</span></span>
|
||||
<span id="cb4-87"><a href="#cb4-87"></a></span>
|
||||
<span id="cb4-88"><a href="#cb4-88"></a> cairo_save(cr);</span>
|
||||
<span id="cb4-88"><a href="#cb4-88"></a> cairo_save<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-89"><a href="#cb4-89"></a></span>
|
||||
<span id="cb4-90"><a href="#cb4-90"></a> <span class="co">// Draw the seconds hand</span></span>
|
||||
<span id="cb4-91"><a href="#cb4-91"></a> cairo_set_line_width(cr, m_line_width / <span class="fl">3.0</span>);</span>
|
||||
<span id="cb4-92"><a href="#cb4-92"></a> cairo_set_source_rgba(cr, <span class="fl">0.7</span>, <span class="fl">0.7</span>, <span class="fl">0.7</span>, <span class="fl">0.8</span>); <span class="co">// gray</span></span>
|
||||
<span id="cb4-93"><a href="#cb4-93"></a> cairo_move_to(cr, <span class="fl">0.0</span>, <span class="fl">0.0</span>);</span>
|
||||
<span id="cb4-94"><a href="#cb4-94"></a> cairo_line_to(cr,</span>
|
||||
<span id="cb4-95"><a href="#cb4-95"></a> sin(seconds) * (m_radius * <span class="fl">0.9</span>),</span>
|
||||
<span id="cb4-96"><a href="#cb4-96"></a> -cos(seconds) * (m_radius * <span class="fl">0.9</span>));</span>
|
||||
<span id="cb4-97"><a href="#cb4-97"></a> cairo_stroke(cr);</span>
|
||||
<span id="cb4-98"><a href="#cb4-98"></a> cairo_restore(cr);</span>
|
||||
<span id="cb4-91"><a href="#cb4-91"></a> cairo_set_line_width<span class="op">(</span>cr<span class="op">,</span> m_line_width <span class="op">/</span> <span class="fl">3.0</span><span class="op">);</span></span>
|
||||
<span id="cb4-92"><a href="#cb4-92"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.7</span><span class="op">,</span> <span class="fl">0.7</span><span class="op">,</span> <span class="fl">0.7</span><span class="op">,</span> <span class="fl">0.8</span><span class="op">);</span> <span class="co">// gray</span></span>
|
||||
<span id="cb4-93"><a href="#cb4-93"></a> cairo_move_to<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">);</span></span>
|
||||
<span id="cb4-94"><a href="#cb4-94"></a> cairo_line_to<span class="op">(</span>cr<span class="op">,</span></span>
|
||||
<span id="cb4-95"><a href="#cb4-95"></a> sin<span class="op">(</span>seconds<span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.9</span><span class="op">),</span></span>
|
||||
<span id="cb4-96"><a href="#cb4-96"></a> <span class="op">-</span>cos<span class="op">(</span>seconds<span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.9</span><span class="op">));</span></span>
|
||||
<span id="cb4-97"><a href="#cb4-97"></a> cairo_stroke<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-98"><a href="#cb4-98"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-99"><a href="#cb4-99"></a></span>
|
||||
<span id="cb4-100"><a href="#cb4-100"></a> <span class="co">// Draw the minutes hand</span></span>
|
||||
<span id="cb4-101"><a href="#cb4-101"></a> cairo_set_source_rgba(cr, <span class="fl">0.117</span>, <span class="fl">0.337</span>, <span class="fl">0.612</span>, <span class="fl">0.9</span>); <span class="co">// blue</span></span>
|
||||
<span id="cb4-102"><a href="#cb4-102"></a> cairo_move_to(cr, <span class="dv">0</span>, <span class="dv">0</span>);</span>
|
||||
<span id="cb4-103"><a href="#cb4-103"></a> cairo_line_to(cr,</span>
|
||||
<span id="cb4-104"><a href="#cb4-104"></a> sin(minutes + seconds / <span class="dv">60</span>) * (m_radius * <span class="fl">0.8</span>),</span>
|
||||
<span id="cb4-105"><a href="#cb4-105"></a> -cos(minutes + seconds / <span class="dv">60</span>) * (m_radius * <span class="fl">0.8</span>));</span>
|
||||
<span id="cb4-106"><a href="#cb4-106"></a> cairo_stroke(cr);</span>
|
||||
<span id="cb4-101"><a href="#cb4-101"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.117</span><span class="op">,</span> <span class="fl">0.337</span><span class="op">,</span> <span class="fl">0.612</span><span class="op">,</span> <span class="fl">0.9</span><span class="op">);</span> <span class="co">// blue</span></span>
|
||||
<span id="cb4-102"><a href="#cb4-102"></a> cairo_move_to<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>
|
||||
<span id="cb4-103"><a href="#cb4-103"></a> cairo_line_to<span class="op">(</span>cr<span class="op">,</span></span>
|
||||
<span id="cb4-104"><a href="#cb4-104"></a> sin<span class="op">(</span>minutes <span class="op">+</span> seconds <span class="op">/</span> <span class="dv">60</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.8</span><span class="op">),</span></span>
|
||||
<span id="cb4-105"><a href="#cb4-105"></a> <span class="op">-</span>cos<span class="op">(</span>minutes <span class="op">+</span> seconds <span class="op">/</span> <span class="dv">60</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.8</span><span class="op">));</span></span>
|
||||
<span id="cb4-106"><a href="#cb4-106"></a> cairo_stroke<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-107"><a href="#cb4-107"></a></span>
|
||||
<span id="cb4-108"><a href="#cb4-108"></a> <span class="co">// draw the hours hand</span></span>
|
||||
<span id="cb4-109"><a href="#cb4-109"></a> cairo_set_source_rgba(cr, <span class="fl">0.337</span>, <span class="fl">0.612</span>, <span class="fl">0.117</span>, <span class="fl">0.9</span>); <span class="co">// green</span></span>
|
||||
<span id="cb4-110"><a href="#cb4-110"></a> cairo_move_to(cr, <span class="fl">0.0</span>, <span class="fl">0.0</span>);</span>
|
||||
<span id="cb4-111"><a href="#cb4-111"></a> cairo_line_to(cr,</span>
|
||||
<span id="cb4-112"><a href="#cb4-112"></a> sin(hours + minutes / <span class="fl">12.0</span>) * (m_radius * <span class="fl">0.5</span>),</span>
|
||||
<span id="cb4-113"><a href="#cb4-113"></a> -cos(hours + minutes / <span class="fl">12.0</span>) * (m_radius * <span class="fl">0.5</span>));</span>
|
||||
<span id="cb4-114"><a href="#cb4-114"></a> cairo_stroke(cr);</span>
|
||||
<span id="cb4-115"><a href="#cb4-115"></a> cairo_restore(cr);</span>
|
||||
<span id="cb4-109"><a href="#cb4-109"></a> cairo_set_source_rgba<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.337</span><span class="op">,</span> <span class="fl">0.612</span><span class="op">,</span> <span class="fl">0.117</span><span class="op">,</span> <span class="fl">0.9</span><span class="op">);</span> <span class="co">// green</span></span>
|
||||
<span id="cb4-110"><a href="#cb4-110"></a> cairo_move_to<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">);</span></span>
|
||||
<span id="cb4-111"><a href="#cb4-111"></a> cairo_line_to<span class="op">(</span>cr<span class="op">,</span></span>
|
||||
<span id="cb4-112"><a href="#cb4-112"></a> sin<span class="op">(</span>hours <span class="op">+</span> minutes <span class="op">/</span> <span class="fl">12.0</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.5</span><span class="op">),</span></span>
|
||||
<span id="cb4-113"><a href="#cb4-113"></a> <span class="op">-</span>cos<span class="op">(</span>hours <span class="op">+</span> minutes <span class="op">/</span> <span class="fl">12.0</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>m_radius <span class="op">*</span> <span class="fl">0.5</span><span class="op">));</span></span>
|
||||
<span id="cb4-114"><a href="#cb4-114"></a> cairo_stroke<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-115"><a href="#cb4-115"></a> cairo_restore<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-116"><a href="#cb4-116"></a></span>
|
||||
<span id="cb4-117"><a href="#cb4-117"></a> <span class="co">// Draw a little dot in the middle</span></span>
|
||||
<span id="cb4-118"><a href="#cb4-118"></a> cairo_arc(cr, <span class="fl">0.0</span>, <span class="fl">0.0</span>, m_line_width / <span class="fl">3.0</span>, <span class="fl">0.0</span>, <span class="fl">2.0</span> * M_PI);</span>
|
||||
<span id="cb4-119"><a href="#cb4-119"></a> cairo_fill(cr);</span>
|
||||
<span id="cb4-120"><a href="#cb4-120"></a>}</span>
|
||||
<span id="cb4-118"><a href="#cb4-118"></a> cairo_arc<span class="op">(</span>cr<span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> m_line_width <span class="op">/</span> <span class="fl">3.0</span><span class="op">,</span> <span class="fl">0.0</span><span class="op">,</span> <span class="fl">2.0</span> <span class="op">*</span> M_PI<span class="op">);</span></span>
|
||||
<span id="cb4-119"><a href="#cb4-119"></a> cairo_fill<span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-120"><a href="#cb4-120"></a><span class="op">}</span></span>
|
||||
<span id="cb4-121"><a href="#cb4-121"></a></span>
|
||||
<span id="cb4-122"><a href="#cb4-122"></a></span>
|
||||
<span id="cb4-123"><a href="#cb4-123"></a>gboolean</span>
|
||||
<span id="cb4-124"><a href="#cb4-124"></a>time_handler(GtkWidget* widget) {</span>
|
||||
<span id="cb4-125"><a href="#cb4-125"></a> gtk_widget_queue_draw(widget);</span>
|
||||
<span id="cb4-124"><a href="#cb4-124"></a>time_handler<span class="op">(</span>GtkWidget<span class="op">*</span> widget<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-125"><a href="#cb4-125"></a> gtk_widget_queue_draw<span class="op">(</span>widget<span class="op">);</span></span>
|
||||
<span id="cb4-126"><a href="#cb4-126"></a></span>
|
||||
<span id="cb4-127"><a href="#cb4-127"></a> <span class="cf">return</span> TRUE;</span>
|
||||
<span id="cb4-128"><a href="#cb4-128"></a>}</span>
|
||||
<span id="cb4-127"><a href="#cb4-127"></a> <span class="cf">return</span> TRUE<span class="op">;</span></span>
|
||||
<span id="cb4-128"><a href="#cb4-128"></a><span class="op">}</span></span>
|
||||
<span id="cb4-129"><a href="#cb4-129"></a></span>
|
||||
<span id="cb4-130"><a href="#cb4-130"></a></span>
|
||||
<span id="cb4-131"><a href="#cb4-131"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb4-132"><a href="#cb4-132"></a>app_activate (GApplication *app, gpointer user_data) {</span>
|
||||
<span id="cb4-133"><a href="#cb4-133"></a> GtkWidget *win;</span>
|
||||
<span id="cb4-134"><a href="#cb4-134"></a> GtkWidget *clock;</span>
|
||||
<span id="cb4-135"><a href="#cb4-135"></a> GtkBuilder *build;</span>
|
||||
<span id="cb4-132"><a href="#cb4-132"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-133"><a href="#cb4-133"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
||||
<span id="cb4-134"><a href="#cb4-134"></a> GtkWidget <span class="op">*</span>clock<span class="op">;</span></span>
|
||||
<span id="cb4-135"><a href="#cb4-135"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
|
||||
<span id="cb4-136"><a href="#cb4-136"></a></span>
|
||||
<span id="cb4-137"><a href="#cb4-137"></a> build = gtk_builder_new_from_resource (<span class="st">"/com/github/ToshioCP/tfc/tfc.ui"</span>);</span>
|
||||
<span id="cb4-138"><a href="#cb4-138"></a> win = GTK_WIDGET (gtk_builder_get_object (build, <span class="st">"win"</span>));</span>
|
||||
<span id="cb4-139"><a href="#cb4-139"></a> gtk_window_set_application (GTK_WINDOW (win), GTK_APPLICATION (app));</span>
|
||||
<span id="cb4-137"><a href="#cb4-137"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">"/com/github/ToshioCP/tfc/tfc.ui"</span><span class="op">);</span></span>
|
||||
<span id="cb4-138"><a href="#cb4-138"></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="cb4-139"><a href="#cb4-139"></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="cb4-140"><a href="#cb4-140"></a></span>
|
||||
<span id="cb4-141"><a href="#cb4-141"></a> clock = GTK_WIDGET (gtk_builder_get_object (build, <span class="st">"clock"</span>));</span>
|
||||
<span id="cb4-142"><a href="#cb4-142"></a> g_object_unref(build);</span>
|
||||
<span id="cb4-141"><a href="#cb4-141"></a> clock <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">"clock"</span><span class="op">));</span></span>
|
||||
<span id="cb4-142"><a href="#cb4-142"></a> g_object_unref<span class="op">(</span>build<span class="op">);</span></span>
|
||||
<span id="cb4-143"><a href="#cb4-143"></a></span>
|
||||
<span id="cb4-144"><a href="#cb4-144"></a> gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA (clock), draw_clock, NULL, NULL);</span>
|
||||
<span id="cb4-145"><a href="#cb4-145"></a> g_timeout_add(<span class="dv">1000</span>, (GSourceFunc) time_handler, (gpointer) clock);</span>
|
||||
<span id="cb4-146"><a href="#cb4-146"></a> gtk_widget_show(win);</span>
|
||||
<span id="cb4-144"><a href="#cb4-144"></a> gtk_drawing_area_set_draw_func<span class="op">(</span>GTK_DRAWING_AREA <span class="op">(</span>clock<span class="op">),</span> draw_clock<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb4-145"><a href="#cb4-145"></a> g_timeout_add<span class="op">(</span><span class="dv">1000</span><span class="op">,</span> <span class="op">(</span>GSourceFunc<span class="op">)</span> time_handler<span class="op">,</span> <span class="op">(</span>gpointer<span class="op">)</span> clock<span class="op">);</span></span>
|
||||
<span id="cb4-146"><a href="#cb4-146"></a> gtk_widget_show<span class="op">(</span>win<span class="op">);</span></span>
|
||||
<span id="cb4-147"><a href="#cb4-147"></a></span>
|
||||
<span id="cb4-148"><a href="#cb4-148"></a>}</span>
|
||||
<span id="cb4-148"><a href="#cb4-148"></a><span class="op">}</span></span>
|
||||
<span id="cb4-149"><a href="#cb4-149"></a></span>
|
||||
<span id="cb4-150"><a href="#cb4-150"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb4-151"><a href="#cb4-151"></a>app_open (GApplication *app, GFile **files, gint n_files, gchar *hint, gpointer user_data) {</span>
|
||||
<span id="cb4-152"><a href="#cb4-152"></a> app_activate(app,user_data);</span>
|
||||
<span id="cb4-153"><a href="#cb4-153"></a>}</span>
|
||||
<span id="cb4-151"><a href="#cb4-151"></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> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-152"><a href="#cb4-152"></a> app_activate<span class="op">(</span>app<span class="op">,</span>user_data<span class="op">);</span></span>
|
||||
<span id="cb4-153"><a href="#cb4-153"></a><span class="op">}</span></span>
|
||||
<span id="cb4-154"><a href="#cb4-154"></a></span>
|
||||
<span id="cb4-155"><a href="#cb4-155"></a><span class="dt">int</span></span>
|
||||
<span id="cb4-156"><a href="#cb4-156"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb4-157"><a href="#cb4-157"></a> GtkApplication *app;</span>
|
||||
<span id="cb4-158"><a href="#cb4-158"></a> <span class="dt">int</span> stat;</span>
|
||||
<span id="cb4-156"><a href="#cb4-156"></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="cb4-157"><a href="#cb4-157"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb4-158"><a href="#cb4-158"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb4-159"><a href="#cb4-159"></a></span>
|
||||
<span id="cb4-160"><a href="#cb4-160"></a> app = gtk_application_new (<span class="st">"com.github.ToshioCP.tfc"</span>, G_APPLICATION_HANDLES_OPEN);</span>
|
||||
<span id="cb4-161"><a href="#cb4-161"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</span>
|
||||
<span id="cb4-162"><a href="#cb4-162"></a> g_signal_connect (app, <span class="st">"open"</span>, G_CALLBACK (app_open), NULL);</span>
|
||||
<span id="cb4-163"><a href="#cb4-163"></a> stat = g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb4-164"><a href="#cb4-164"></a> g_object_unref (app);</span>
|
||||
<span id="cb4-165"><a href="#cb4-165"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb4-166"><a href="#cb4-166"></a>}</span></code></pre></div>
|
||||
<span id="cb4-160"><a href="#cb4-160"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span><span class="st">"com.github.ToshioCP.tfc"</span><span class="op">,</span> G_APPLICATION_HANDLES_OPEN<span class="op">);</span></span>
|
||||
<span id="cb4-161"><a href="#cb4-161"></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="cb4-162"><a href="#cb4-162"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"open"</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="cb4-163"><a href="#cb4-163"></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="cb4-164"><a href="#cb4-164"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb4-165"><a href="#cb4-165"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb4-166"><a href="#cb4-166"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p><code>tfc.ui</code></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="kw"><?xml</span> version="1.0" encoding="UTF-8"<span class="kw">?></span></span>
|
||||
<span id="cb5-2"><a href="#cb5-2"></a><span class="kw"><interface></span></span>
|
||||
<span id="cb5-3"><a href="#cb5-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 class="kw">></span></span>
|
||||
<span id="cb5-4"><a href="#cb5-4"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"title"</span><span class="kw">></span>Clock<span class="kw"></property></span></span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"default-width"</span><span class="kw">></span>200<span class="kw"></property></span></span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"default-height"</span><span class="kw">></span>200<span class="kw"></property></span></span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkDrawingArea"</span><span class="ot"> id=</span><span class="st">"clock"</span><span class="kw">></span></span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"hexpand"</span><span class="kw">></span>TRUE<span class="kw"></property></span></span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"vexpand"</span><span class="kw">></span>TRUE<span class="kw"></property></span></span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb5-12"><a href="#cb5-12"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a><span class="kw"></interface></span></span></code></pre></div>
|
||||
<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"><?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="cb5-2"><a href="#cb5-2"></a><<span class="kw">interface</span>></span>
|
||||
<span id="cb5-3"><a href="#cb5-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="cb5-4"><a href="#cb5-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"title"</span>>Clock</<span class="kw">property</span>></span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-width"</span>>200</<span class="kw">property</span>></span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-height"</span>>200</<span class="kw">property</span>></span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkDrawingArea"</span><span class="ot"> id=</span><span class="st">"clock"</span>></span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></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="cb5-10"><a href="#cb5-10"></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="cb5-11"><a href="#cb5-11"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb5-12"><a href="#cb5-12"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||
<p><code>tfc.gresource.xml</code></p>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw"><?xml</span> version="1.0" encoding="UTF-8"<span class="kw">?></span></span>
|
||||
<span id="cb6-2"><a href="#cb6-2"></a><span class="kw"><gresources></span></span>
|
||||
<span id="cb6-3"><a href="#cb6-3"></a> <span class="kw"><gresource</span><span class="ot"> prefix=</span><span class="st">"/com/github/ToshioCP/tfc"</span><span class="kw">></span></span>
|
||||
<span id="cb6-4"><a href="#cb6-4"></a> <span class="kw"><file></span>tfc.ui<span class="kw"></file></span></span>
|
||||
<span id="cb6-5"><a href="#cb6-5"></a> <span class="kw"></gresource></span></span>
|
||||
<span id="cb6-6"><a href="#cb6-6"></a><span class="kw"></gresources></span></span></code></pre></div>
|
||||
<div class="sourceCode" id="cb6"><pre
|
||||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb6-1"><a href="#cb6-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="cb6-2"><a href="#cb6-2"></a><<span class="kw">gresources</span>></span>
|
||||
<span id="cb6-3"><a href="#cb6-3"></a> <<span class="kw">gresource</span><span class="ot"> prefix=</span><span class="st">"/com/github/ToshioCP/tfc"</span>></span>
|
||||
<span id="cb6-4"><a href="#cb6-4"></a> <<span class="kw">file</span>>tfc.ui</<span class="kw">file</span>></span>
|
||||
<span id="cb6-5"><a href="#cb6-5"></a> </<span class="kw">gresource</span>></span>
|
||||
<span id="cb6-6"><a href="#cb6-6"></a></<span class="kw">gresources</span>></span></code></pre></div>
|
||||
<p><code>comp</code></p>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb7-1"><a href="#cb7-1"></a>glib-compile-resources $1.gresource.xml --target=$1.gresource.c --generate-source</span>
|
||||
<div class="sourceCode" id="cb7"><pre
|
||||
class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb7-1"><a href="#cb7-1"></a>glib-compile-resources $1.gresource.xml --target=$1.gresource.c --generate-source</span>
|
||||
<span id="cb7-2"><a href="#cb7-2"></a>gcc `pkg-config --cflags gtk4` $1.gresource.c $1.c `pkg-config --libs gtk4` -lm</span></code></pre></div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
||||
|
|
409
docs/sec26.html
409
docs/sec26.html
|
@ -132,13 +132,13 @@ point. So, each item can be referred by the index of the item (first
|
|||
item, second item, …, nth item, …). There are two cases. One is the
|
||||
index starts from one (one-based) and the other is from zero
|
||||
(zero-based).</p>
|
||||
<p>Gio provides GListModel interface. It is a zero-based list of the
|
||||
same type of GObject descendants, or objects that implement the same
|
||||
interface. An object implements GListModel is not a widget. So, the list
|
||||
is not displayed on the screen directly. There’s another object
|
||||
GtkListView which is a widget to display the list. The items in the list
|
||||
need to be connected to the items in GtkListView. GtkListItemFactory
|
||||
object maps items in the list to GListView.</p>
|
||||
<p>Gio provides GListModel interface. It is a zero-based list and its
|
||||
items are the same type of GObject descendants, or objects that
|
||||
implement the same interface. An object implements GListModel is not a
|
||||
widget. So, the list is not displayed on the screen directly. There’s
|
||||
another object GtkListView which is a widget to display the list. The
|
||||
items in the list need to be connected to the items in GtkListView.
|
||||
GtkListItemFactory instance maps items in the list to GListView.</p>
|
||||
<figure>
|
||||
<img src="image/list.png" alt="List" />
|
||||
<figcaption aria-hidden="true">List</figcaption>
|
||||
|
@ -172,8 +172,8 @@ API Reference – GtkStringList</a> for further information.</p>
|
|||
to this model, user can select items by clicking on them. It is
|
||||
implemented by GtkMultiSelection, GtkNoSelection and GtkSingleSelection
|
||||
objects. These three objects are usually enough to build an application.
|
||||
They are created with GListModel. You can also create them alone and add
|
||||
GListModel later.</p>
|
||||
They are created with another GListModel. You can also create them alone
|
||||
and add a GListModel later.</p>
|
||||
<ul>
|
||||
<li>GtkMultiSelection supports multiple selection.</li>
|
||||
<li>GtkNoSelection supports no selection. This is a wrapper to
|
||||
|
@ -199,7 +199,7 @@ growth of memory consumption so that GListModel can contain lots of
|
|||
items, for example, more than a million items.</p>
|
||||
<h2 id="gtklistitemfactory">GtkListItemFactory</h2>
|
||||
<p>GtkListItemFactory creates or recycles GtkListItem and connects it
|
||||
with an item of the list model. There are two child objects of this
|
||||
with an item of the list model. There are two child classes of this
|
||||
factory, GtkSignalListItemFactory and GtkBuilderListItemFactory.</p>
|
||||
<h3 id="gtksignallistitemfactory">GtkSignalListItemFactory</h3>
|
||||
<p>GtkSignalListItemFactory provides signals for users to configure a
|
||||
|
@ -207,7 +207,7 @@ GtkListItem object. There are four signals.</p>
|
|||
<ol type="1">
|
||||
<li>“setup” is emitted to set up GtkListItem object. A user sets its
|
||||
child widget in the handler. For example, creates a GtkLabel widget and
|
||||
sets the child property of GtkListItem with it. This setting is kept
|
||||
sets the child property of the GtkListItem to it. This setting is kept
|
||||
even the GtkListItem instance is recycled (to bind to another item of
|
||||
GListModel).</li>
|
||||
<li>“bind” is emitted to bind an item in the list model to the widget.
|
||||
|
@ -233,16 +233,16 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
|||
<span id="cb2-4"><a href="#cb2-4"></a>setup_cb <span class="op">(</span>GtkSignalListItemFactory <span class="op">*</span>self<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a> GtkWidget <span class="op">*</span>lb <span class="op">=</span> gtk_label_new <span class="op">(</span>NULL<span class="op">);</span></span>
|
||||
<span id="cb2-6"><a href="#cb2-6"></a> gtk_list_item_set_child <span class="op">(</span>listitem<span class="op">,</span> lb<span class="op">);</span></span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a><span class="op">}</span></span>
|
||||
<span id="cb2-8"><a href="#cb2-8"></a></span>
|
||||
<span id="cb2-9"><a href="#cb2-9"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-10"><a href="#cb2-10"></a>bind_cb <span class="op">(</span>GtkSignalListItemFactory <span class="op">*</span>self<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-11"><a href="#cb2-11"></a> GtkWidget <span class="op">*</span>lb <span class="op">=</span> gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">);</span></span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> <span class="co">/* Strobj is owned by the instance. Caller mustn't change or destroy it. */</span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13"></a> GtkStringObject <span class="op">*</span>strobj <span class="op">=</span> gtk_list_item_get_item <span class="op">(</span>listitem<span class="op">);</span></span>
|
||||
<span id="cb2-14"><a href="#cb2-14"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>text <span class="op">=</span> gtk_string_object_get_string <span class="op">(</span>strobj<span class="op">);</span></span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a></span>
|
||||
<span id="cb2-16"><a href="#cb2-16"></a> gtk_label_set_text <span class="op">(</span>GTK_LABEL <span class="op">(</span>lb<span class="op">),</span> text<span class="op">);</span></span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a> <span class="co">/* Because gtk_list_item_set_child sunk the floating reference of lb, releasing (unref) isn't necessary for lb. */</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><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-11"><a href="#cb2-11"></a>bind_cb <span class="op">(</span>GtkSignalListItemFactory <span class="op">*</span>self<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> GtkWidget <span class="op">*</span>lb <span class="op">=</span> gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">);</span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13"></a> <span class="co">/* Strobj is owned by the instance. Caller mustn't change or destroy it. */</span></span>
|
||||
<span id="cb2-14"><a href="#cb2-14"></a> GtkStringObject <span class="op">*</span>strobj <span class="op">=</span> gtk_list_item_get_item <span class="op">(</span>listitem<span class="op">);</span></span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a> <span class="co">/* The string returned by gtk_string_object_get_string is owned by the instance. */</span></span>
|
||||
<span id="cb2-16"><a href="#cb2-16"></a> gtk_label_set_text <span class="op">(</span>GTK_LABEL <span class="op">(</span>lb<span class="op">),</span> gtk_string_object_get_string <span class="op">(</span>strobj<span class="op">));</span></span>
|
||||
<span id="cb2-17"><a href="#cb2-17"></a><span class="op">}</span></span>
|
||||
<span id="cb2-18"><a href="#cb2-18"></a></span>
|
||||
<span id="cb2-19"><a href="#cb2-19"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
|
@ -252,8 +252,8 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
|||
<span id="cb2-23"><a href="#cb2-23"></a></span>
|
||||
<span id="cb2-24"><a href="#cb2-24"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-25"><a href="#cb2-25"></a>teardown_cb <span class="op">(</span>GtkSignalListItemFactory <span class="op">*</span>self<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-26"><a href="#cb2-26"></a> gtk_list_item_set_child <span class="op">(</span>listitem<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-27"><a href="#cb2-27"></a> <span class="co">/* The previous child is destroyed automatically. */</span></span>
|
||||
<span id="cb2-26"><a href="#cb2-26"></a> <span class="co">/* There's nothing to do here. */</span></span>
|
||||
<span id="cb2-27"><a href="#cb2-27"></a> <span class="co">/* GtkListItem instance will be destroyed soon. You don't need to set the child to NULL. */</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><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
|
@ -276,30 +276,31 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
|||
<span id="cb2-47"><a href="#cb2-47"></a> GtkListItemFactory <span class="op">*</span>factory <span class="op">=</span> gtk_signal_list_item_factory_new <span class="op">();</span></span>
|
||||
<span id="cb2-48"><a href="#cb2-48"></a> g_signal_connect <span class="op">(</span>factory<span class="op">,</span> <span class="st">"setup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>setup_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-49"><a href="#cb2-49"></a> g_signal_connect <span class="op">(</span>factory<span class="op">,</span> <span class="st">"bind"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>bind_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-50"><a href="#cb2-50"></a> g_signal_connect <span class="op">(</span>factory<span class="op">,</span> <span class="st">"unbind"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>unbind_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-51"><a href="#cb2-51"></a> g_signal_connect <span class="op">(</span>factory<span class="op">,</span> <span class="st">"teardown"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>teardown_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-52"><a href="#cb2-52"></a></span>
|
||||
<span id="cb2-53"><a href="#cb2-53"></a> GtkWidget <span class="op">*</span>lv <span class="op">=</span> gtk_list_view_new <span class="op">(</span>GTK_SELECTION_MODEL <span class="op">(</span>ns<span class="op">),</span> factory<span class="op">);</span></span>
|
||||
<span id="cb2-54"><a href="#cb2-54"></a> gtk_scrolled_window_set_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">),</span> lv<span class="op">);</span></span>
|
||||
<span id="cb2-55"><a href="#cb2-55"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb2-56"><a href="#cb2-56"></a><span class="op">}</span></span>
|
||||
<span id="cb2-57"><a href="#cb2-57"></a></span>
|
||||
<span id="cb2-58"><a href="#cb2-58"></a><span class="co">/* ----- main ----- */</span></span>
|
||||
<span id="cb2-59"><a href="#cb2-59"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.list1"</span></span>
|
||||
<span id="cb2-60"><a href="#cb2-60"></a></span>
|
||||
<span id="cb2-61"><a href="#cb2-61"></a><span class="dt">int</span></span>
|
||||
<span id="cb2-62"><a href="#cb2-62"></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="cb2-63"><a href="#cb2-63"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb2-64"><a href="#cb2-64"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb2-65"><a href="#cb2-65"></a></span>
|
||||
<span id="cb2-66"><a href="#cb2-66"></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="cb2-67"><a href="#cb2-67"></a></span>
|
||||
<span id="cb2-68"><a href="#cb2-68"></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="cb2-69"><a href="#cb2-69"></a></span>
|
||||
<span id="cb2-70"><a href="#cb2-70"></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="cb2-71"><a href="#cb2-71"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb2-72"><a href="#cb2-72"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb2-73"><a href="#cb2-73"></a><span class="op">}</span></span></code></pre></div>
|
||||
<span id="cb2-50"><a href="#cb2-50"></a> <span class="co">/* The following two lines can be left out. The handlers do nothing. */</span></span>
|
||||
<span id="cb2-51"><a href="#cb2-51"></a> g_signal_connect <span class="op">(</span>factory<span class="op">,</span> <span class="st">"unbind"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>unbind_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-52"><a href="#cb2-52"></a> g_signal_connect <span class="op">(</span>factory<span class="op">,</span> <span class="st">"teardown"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>teardown_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-53"><a href="#cb2-53"></a></span>
|
||||
<span id="cb2-54"><a href="#cb2-54"></a> GtkWidget <span class="op">*</span>lv <span class="op">=</span> gtk_list_view_new <span class="op">(</span>GTK_SELECTION_MODEL <span class="op">(</span>ns<span class="op">),</span> factory<span class="op">);</span></span>
|
||||
<span id="cb2-55"><a href="#cb2-55"></a> gtk_scrolled_window_set_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">),</span> lv<span class="op">);</span></span>
|
||||
<span id="cb2-56"><a href="#cb2-56"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb2-57"><a href="#cb2-57"></a><span class="op">}</span></span>
|
||||
<span id="cb2-58"><a href="#cb2-58"></a></span>
|
||||
<span id="cb2-59"><a href="#cb2-59"></a><span class="co">/* ----- main ----- */</span></span>
|
||||
<span id="cb2-60"><a href="#cb2-60"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.list1"</span></span>
|
||||
<span id="cb2-61"><a href="#cb2-61"></a></span>
|
||||
<span id="cb2-62"><a href="#cb2-62"></a><span class="dt">int</span></span>
|
||||
<span id="cb2-63"><a href="#cb2-63"></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="cb2-64"><a href="#cb2-64"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb2-65"><a href="#cb2-65"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb2-66"><a href="#cb2-66"></a></span>
|
||||
<span id="cb2-67"><a href="#cb2-67"></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="cb2-68"><a href="#cb2-68"></a></span>
|
||||
<span id="cb2-69"><a href="#cb2-69"></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="cb2-70"><a href="#cb2-70"></a></span>
|
||||
<span id="cb2-71"><a href="#cb2-71"></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="cb2-72"><a href="#cb2-72"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb2-73"><a href="#cb2-73"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb2-74"><a href="#cb2-74"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>The file <code>list1.c</code> is located under the directory
|
||||
src/misc. Make a shell script below and save it to your bin directory,
|
||||
for example <code>$HOME/bin</code>.</p>
|
||||
|
@ -339,13 +340,13 @@ class="sourceCode xml"><code class="sourceCode xml"><span id="cb5-1"><a href="#c
|
|||
GtkLabel object. The factory sees this template and creates GtkLabel and
|
||||
sets the child property of GtkListItem. This is the same as what setup
|
||||
handler of GtkSignalListItemFactory did.</p>
|
||||
<p>Then, bind the label property of GtkLabel to string property of
|
||||
GtkStringObject. The string object is referred to by item property of
|
||||
GtkListItem. So, the lookup tag is like this:</p>
|
||||
<pre><code>string <- GtkStringObject <- item <- GtkListItem</code></pre>
|
||||
<p>Then, bind the label property of the GtkLabel to the string property
|
||||
of a GtkStringObject. The string object refers to the item property of
|
||||
the GtkListItem. So, the lookup tag is like this:</p>
|
||||
<pre><code>label <- string <- GtkStringObject <- item <- GtkListItem</code></pre>
|
||||
<p>The last lookup tag has a content <code>GtkListItem</code>. Usually,
|
||||
C type like <code>GtkListItem</code> doesn’t appear in the content of
|
||||
tags. This is a special case. There is an explanation about it in the <a
|
||||
tags. This is a special case. There is an explanation in the <a
|
||||
href="https://blog.gtk.org/2020/09/05/a-primer-on-gtklistview/">GTK
|
||||
Development Blog</a> by Matthias Clasen.</p>
|
||||
<blockquote>
|
||||
|
@ -361,60 +362,65 @@ located under src/misc directory.</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="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2"></a></span>
|
||||
<span id="cb7-3"><a href="#cb7-3"></a><span class="co">/* ----- activate, open, startup handlers ----- */</span></span>
|
||||
<span id="cb7-4"><a href="#cb7-4"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-5"><a href="#cb7-5"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb7-6"><a href="#cb7-6"></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="cb7-7"><a href="#cb7-7"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> gtk_application_window_new <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb7-8"><a href="#cb7-8"></a> gtk_window_set_default_size <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> <span class="dv">600</span><span class="op">,</span> <span class="dv">400</span><span class="op">);</span></span>
|
||||
<span id="cb7-9"><a href="#cb7-9"></a> GtkWidget <span class="op">*</span>scr <span class="op">=</span> gtk_scrolled_window_new <span class="op">();</span></span>
|
||||
<span id="cb7-10"><a href="#cb7-10"></a> gtk_window_set_child <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> scr<span class="op">);</span></span>
|
||||
<span id="cb7-11"><a href="#cb7-11"></a></span>
|
||||
<span id="cb7-12"><a href="#cb7-12"></a> <span class="dt">char</span> <span class="op">*</span>array<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span></span>
|
||||
<span id="cb7-13"><a href="#cb7-13"></a> <span class="st">"one"</span><span class="op">,</span> <span class="st">"two"</span><span class="op">,</span> <span class="st">"three"</span><span class="op">,</span> <span class="st">"four"</span><span class="op">,</span> NULL</span>
|
||||
<span id="cb7-14"><a href="#cb7-14"></a> <span class="op">};</span></span>
|
||||
<span id="cb7-15"><a href="#cb7-15"></a> GtkStringList <span class="op">*</span>sl <span class="op">=</span> gtk_string_list_new <span class="op">((</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span> <span class="dt">const</span> <span class="op">*)</span> array<span class="op">);</span></span>
|
||||
<span id="cb7-16"><a href="#cb7-16"></a> GtkSingleSelection <span class="op">*</span>ss <span class="op">=</span> gtk_single_selection_new <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>sl<span class="op">));</span></span>
|
||||
<span id="cb7-17"><a href="#cb7-17"></a></span>
|
||||
<span id="cb7-18"><a href="#cb7-18"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>ui_string <span class="op">=</span></span>
|
||||
<span id="cb7-19"><a href="#cb7-19"></a><span class="st">"<interface>"</span></span>
|
||||
<span id="cb7-20"><a href="#cb7-20"></a> <span class="st">"<template class=</span><span class="sc">\"</span><span class="st">GtkListItem</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-21"><a href="#cb7-21"></a> <span class="st">"<property name=</span><span class="sc">\"</span><span class="st">child</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-22"><a href="#cb7-22"></a> <span class="st">"<object class=</span><span class="sc">\"</span><span class="st">GtkLabel</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-23"><a href="#cb7-23"></a> <span class="st">"<binding name=</span><span class="sc">\"</span><span class="st">label</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-24"><a href="#cb7-24"></a> <span class="st">"<lookup name=</span><span class="sc">\"</span><span class="st">string</span><span class="sc">\"</span><span class="st"> type=</span><span class="sc">\"</span><span class="st">GtkStringObject</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-25"><a href="#cb7-25"></a> <span class="st">"<lookup name=</span><span class="sc">\"</span><span class="st">item</span><span class="sc">\"</span><span class="st">>GtkListItem</lookup>"</span></span>
|
||||
<span id="cb7-26"><a href="#cb7-26"></a> <span class="st">"</lookup>"</span></span>
|
||||
<span id="cb7-27"><a href="#cb7-27"></a> <span class="st">"</binding>"</span></span>
|
||||
<span id="cb7-28"><a href="#cb7-28"></a> <span class="st">"</object>"</span></span>
|
||||
<span id="cb7-29"><a href="#cb7-29"></a> <span class="st">"</property>"</span></span>
|
||||
<span id="cb7-30"><a href="#cb7-30"></a> <span class="st">"</template>"</span></span>
|
||||
<span id="cb7-31"><a href="#cb7-31"></a><span class="st">"</interface>"</span></span>
|
||||
<span id="cb7-32"><a href="#cb7-32"></a><span class="op">;</span></span>
|
||||
<span id="cb7-33"><a href="#cb7-33"></a> GBytes <span class="op">*</span>gbytes <span class="op">=</span> g_bytes_new_static <span class="op">(</span>ui_string<span class="op">,</span> strlen <span class="op">(</span>ui_string<span class="op">));</span></span>
|
||||
<span id="cb7-34"><a href="#cb7-34"></a> GtkListItemFactory <span class="op">*</span>factory <span class="op">=</span> gtk_builder_list_item_factory_new_from_bytes <span class="op">(</span>NULL<span class="op">,</span> gbytes<span class="op">);</span></span>
|
||||
<span id="cb7-35"><a href="#cb7-35"></a></span>
|
||||
<span id="cb7-36"><a href="#cb7-36"></a> GtkWidget <span class="op">*</span>lv <span class="op">=</span> gtk_list_view_new <span class="op">(</span>GTK_SELECTION_MODEL <span class="op">(</span>ss<span class="op">),</span> factory<span class="op">);</span></span>
|
||||
<span id="cb7-37"><a href="#cb7-37"></a> gtk_scrolled_window_set_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">),</span> lv<span class="op">);</span></span>
|
||||
<span id="cb7-38"><a href="#cb7-38"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb7-39"><a href="#cb7-39"></a><span class="op">}</span></span>
|
||||
<span id="cb7-3"><a href="#cb7-3"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-4"><a href="#cb7-4"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb7-5"><a href="#cb7-5"></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="cb7-6"><a href="#cb7-6"></a> gtk_window_present <span class="op">(</span>gtk_application_get_active_window<span class="op">(</span>app<span class="op">));</span></span>
|
||||
<span id="cb7-7"><a href="#cb7-7"></a><span class="op">}</span></span>
|
||||
<span id="cb7-8"><a href="#cb7-8"></a></span>
|
||||
<span id="cb7-9"><a href="#cb7-9"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-10"><a href="#cb7-10"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb7-11"><a href="#cb7-11"></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="cb7-12"><a href="#cb7-12"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> gtk_application_window_new <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb7-13"><a href="#cb7-13"></a> gtk_window_set_default_size <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> <span class="dv">600</span><span class="op">,</span> <span class="dv">400</span><span class="op">);</span></span>
|
||||
<span id="cb7-14"><a href="#cb7-14"></a> GtkWidget <span class="op">*</span>scr <span class="op">=</span> gtk_scrolled_window_new <span class="op">();</span></span>
|
||||
<span id="cb7-15"><a href="#cb7-15"></a> gtk_window_set_child <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> scr<span class="op">);</span></span>
|
||||
<span id="cb7-16"><a href="#cb7-16"></a></span>
|
||||
<span id="cb7-17"><a href="#cb7-17"></a> <span class="dt">char</span> <span class="op">*</span>array<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span></span>
|
||||
<span id="cb7-18"><a href="#cb7-18"></a> <span class="st">"one"</span><span class="op">,</span> <span class="st">"two"</span><span class="op">,</span> <span class="st">"three"</span><span class="op">,</span> <span class="st">"four"</span><span class="op">,</span> NULL</span>
|
||||
<span id="cb7-19"><a href="#cb7-19"></a> <span class="op">};</span></span>
|
||||
<span id="cb7-20"><a href="#cb7-20"></a> GtkStringList <span class="op">*</span>sl <span class="op">=</span> gtk_string_list_new <span class="op">((</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span> <span class="dt">const</span> <span class="op">*)</span> array<span class="op">);</span></span>
|
||||
<span id="cb7-21"><a href="#cb7-21"></a> GtkSingleSelection <span class="op">*</span>ss <span class="op">=</span> gtk_single_selection_new <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>sl<span class="op">));</span></span>
|
||||
<span id="cb7-22"><a href="#cb7-22"></a></span>
|
||||
<span id="cb7-23"><a href="#cb7-23"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>ui_string <span class="op">=</span></span>
|
||||
<span id="cb7-24"><a href="#cb7-24"></a><span class="st">"<interface>"</span></span>
|
||||
<span id="cb7-25"><a href="#cb7-25"></a> <span class="st">"<template class=</span><span class="sc">\"</span><span class="st">GtkListItem</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-26"><a href="#cb7-26"></a> <span class="st">"<property name=</span><span class="sc">\"</span><span class="st">child</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-27"><a href="#cb7-27"></a> <span class="st">"<object class=</span><span class="sc">\"</span><span class="st">GtkLabel</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-28"><a href="#cb7-28"></a> <span class="st">"<binding name=</span><span class="sc">\"</span><span class="st">label</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-29"><a href="#cb7-29"></a> <span class="st">"<lookup name=</span><span class="sc">\"</span><span class="st">string</span><span class="sc">\"</span><span class="st"> type=</span><span class="sc">\"</span><span class="st">GtkStringObject</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb7-30"><a href="#cb7-30"></a> <span class="st">"<lookup name=</span><span class="sc">\"</span><span class="st">item</span><span class="sc">\"</span><span class="st">>GtkListItem</lookup>"</span></span>
|
||||
<span id="cb7-31"><a href="#cb7-31"></a> <span class="st">"</lookup>"</span></span>
|
||||
<span id="cb7-32"><a href="#cb7-32"></a> <span class="st">"</binding>"</span></span>
|
||||
<span id="cb7-33"><a href="#cb7-33"></a> <span class="st">"</object>"</span></span>
|
||||
<span id="cb7-34"><a href="#cb7-34"></a> <span class="st">"</property>"</span></span>
|
||||
<span id="cb7-35"><a href="#cb7-35"></a> <span class="st">"</template>"</span></span>
|
||||
<span id="cb7-36"><a href="#cb7-36"></a><span class="st">"</interface>"</span></span>
|
||||
<span id="cb7-37"><a href="#cb7-37"></a><span class="op">;</span></span>
|
||||
<span id="cb7-38"><a href="#cb7-38"></a> GBytes <span class="op">*</span>gbytes <span class="op">=</span> g_bytes_new_static <span class="op">(</span>ui_string<span class="op">,</span> strlen <span class="op">(</span>ui_string<span class="op">));</span></span>
|
||||
<span id="cb7-39"><a href="#cb7-39"></a> GtkListItemFactory <span class="op">*</span>factory <span class="op">=</span> gtk_builder_list_item_factory_new_from_bytes <span class="op">(</span>NULL<span class="op">,</span> gbytes<span class="op">);</span></span>
|
||||
<span id="cb7-40"><a href="#cb7-40"></a></span>
|
||||
<span id="cb7-41"><a href="#cb7-41"></a><span class="co">/* ----- main ----- */</span></span>
|
||||
<span id="cb7-42"><a href="#cb7-42"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.list2"</span></span>
|
||||
<span id="cb7-43"><a href="#cb7-43"></a></span>
|
||||
<span id="cb7-44"><a href="#cb7-44"></a><span class="dt">int</span></span>
|
||||
<span id="cb7-45"><a href="#cb7-45"></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="cb7-46"><a href="#cb7-46"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb7-47"><a href="#cb7-47"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb7-48"><a href="#cb7-48"></a></span>
|
||||
<span id="cb7-49"><a href="#cb7-49"></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="cb7-50"><a href="#cb7-50"></a></span>
|
||||
<span id="cb7-51"><a href="#cb7-51"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb7-41"><a href="#cb7-41"></a> GtkWidget <span class="op">*</span>lv <span class="op">=</span> gtk_list_view_new <span class="op">(</span>GTK_SELECTION_MODEL <span class="op">(</span>ss<span class="op">),</span> factory<span class="op">);</span></span>
|
||||
<span id="cb7-42"><a href="#cb7-42"></a> gtk_scrolled_window_set_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">),</span> lv<span class="op">);</span></span>
|
||||
<span id="cb7-43"><a href="#cb7-43"></a><span class="op">}</span></span>
|
||||
<span id="cb7-44"><a href="#cb7-44"></a></span>
|
||||
<span id="cb7-45"><a href="#cb7-45"></a><span class="co">/* ----- main ----- */</span></span>
|
||||
<span id="cb7-46"><a href="#cb7-46"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.list2"</span></span>
|
||||
<span id="cb7-47"><a href="#cb7-47"></a></span>
|
||||
<span id="cb7-48"><a href="#cb7-48"></a><span class="dt">int</span></span>
|
||||
<span id="cb7-49"><a href="#cb7-49"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb7-50"><a href="#cb7-50"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb7-51"><a href="#cb7-51"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb7-52"><a href="#cb7-52"></a></span>
|
||||
<span id="cb7-53"><a href="#cb7-53"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
||||
<span id="cb7-54"><a href="#cb7-54"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb7-55"><a href="#cb7-55"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb7-56"><a href="#cb7-56"></a><span class="op">}</span></span></code></pre></div>
|
||||
<span id="cb7-53"><a href="#cb7-53"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
|
||||
<span id="cb7-54"><a href="#cb7-54"></a></span>
|
||||
<span id="cb7-55"><a href="#cb7-55"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb7-56"><a href="#cb7-56"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb7-57"><a href="#cb7-57"></a></span>
|
||||
<span id="cb7-58"><a href="#cb7-58"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
||||
<span id="cb7-59"><a href="#cb7-59"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb7-60"><a href="#cb7-60"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb7-61"><a href="#cb7-61"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>No signal handler is needed for GtkBulderListItemFactory.
|
||||
GtkSingleSelection is used, so user can select one item at a time.</p>
|
||||
<p>Because this is a small program, the ui data is given as a
|
||||
|
@ -482,37 +488,33 @@ closure tag is appropriate in this case. Closure tag specifies a
|
|||
function and the type of the return value of the function.</p>
|
||||
<div class="sourceCode" id="cb10"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span></span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>get_file_name <span class="op">(</span>GtkListItem <span class="op">*</span>item<span class="op">,</span> GFileInfo <span class="op">*</span>info<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(!</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">))</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">else</span></span>
|
||||
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> g_strdup <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">));</span></span>
|
||||
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="st">"<interface>"</span></span>
|
||||
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a> <span class="st">"<template class=</span><span class="sc">\"</span><span class="st">GtkListItem</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a> <span class="st">"<property name=</span><span class="sc">\"</span><span class="st">child</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a> <span class="st">"<object class=</span><span class="sc">\"</span><span class="st">GtkLabel</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a> <span class="st">"<binding name=</span><span class="sc">\"</span><span class="st">label</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a> <span class="st">"<closure type=</span><span class="sc">\"</span><span class="st">gchararray</span><span class="sc">\"</span><span class="st"> function=</span><span class="sc">\"</span><span class="st">get_file_name</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a> <span class="st">"<lookup name=</span><span class="sc">\"</span><span class="st">item</span><span class="sc">\"</span><span class="st">>GtkListItem</lookup>"</span></span>
|
||||
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a> <span class="st">"</closure>"</span></span>
|
||||
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a> <span class="st">"</binding>"</span></span>
|
||||
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a> <span class="st">"</object>"</span></span>
|
||||
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a> <span class="st">"</property>"</span></span>
|
||||
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a> <span class="st">"</template>"</span></span>
|
||||
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a><span class="st">"</interface>"</span></span></code></pre></div>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">)</span> <span class="op">?</span> g_strdup <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">))</span> <span class="op">:</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="st">"<interface>"</span></span>
|
||||
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a> <span class="st">"<template class=</span><span class="sc">\"</span><span class="st">GtkListItem</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a> <span class="st">"<property name=</span><span class="sc">\"</span><span class="st">child</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a> <span class="st">"<object class=</span><span class="sc">\"</span><span class="st">GtkLabel</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a> <span class="st">"<binding name=</span><span class="sc">\"</span><span class="st">label</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a> <span class="st">"<closure type=</span><span class="sc">\"</span><span class="st">gchararray</span><span class="sc">\"</span><span class="st"> function=</span><span class="sc">\"</span><span class="st">get_file_name</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a> <span class="st">"<lookup name=</span><span class="sc">\"</span><span class="st">item</span><span class="sc">\"</span><span class="st">>GtkListItem</lookup>"</span></span>
|
||||
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a> <span class="st">"</closure>"</span></span>
|
||||
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a> <span class="st">"</binding>"</span></span>
|
||||
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a> <span class="st">"</object>"</span></span>
|
||||
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a> <span class="st">"</property>"</span></span>
|
||||
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a> <span class="st">"</template>"</span></span>
|
||||
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a><span class="st">"</interface>"</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>The string “gchararray” is the type name of strings. The type
|
||||
“gchar” is the same as “char”. Therefore, “gchararray” is “an array of
|
||||
char type”, which is the same as string type. It is used to get the type
|
||||
of GValue object. GValue is a generic value and it can contain various
|
||||
type of values. For example, the type name can be gboolean, gchar
|
||||
(char), gint (int), gfloat (float), gdouble (double), gchararray (char
|
||||
*) and so on. These type names are the names of the fundamental types
|
||||
that are registered to the type system. See <a
|
||||
<li>The string “gchararray” is a type name. The type “gchar” is a type
|
||||
name and it is the same as C type “char”. Therefore, “gchararray” is “an
|
||||
array of char type”, which is the same as string type. It is used to get
|
||||
the type of GValue object. GValue is a generic value and it can contain
|
||||
various type of values. For example, the type name can be gboolean,
|
||||
gchar (char), gint (int), gfloat (float), gdouble (double), gchararray
|
||||
(char *) and so on. These type names are the names of the fundamental
|
||||
types that are registered to the type system. See <a
|
||||
href="https://github.com/ToshioCP/Gobject-tutorial/blob/main/gfm/sec5.md#gvalue">GObject
|
||||
tutorial</a>.</li>
|
||||
<li>Closure tag has type attribute and function attribute. Function
|
||||
|
@ -523,14 +525,16 @@ the function.
|
|||
<code><lookup name="item">GtkListItem</lookup></code> gives
|
||||
the value of the item property of the GtkListItem. This will be the
|
||||
second argument of the function. The first parameter is always the
|
||||
GListItem instance.</li>
|
||||
<li><code>gtk_file_name</code> function first checks the
|
||||
<code>info</code> parameter. Because it can be NULL when GListItem
|
||||
<code>item</code> is unbounded. If it’s GFileInfo, it returns the
|
||||
filename. The filename is owned by GFileInfo object. So, the function
|
||||
<code>get_file_name</code> duplicates the string to own the newly
|
||||
created one. Closure tag binds the property of the outer tag (GtkLabel)
|
||||
to the filename.</li>
|
||||
GListItem instance, which is a ‘this’ object. The ‘this’ object is
|
||||
explained in section 28.</li>
|
||||
<li><code>gtk_file_name</code> function is the callback function for the
|
||||
closure tag. It first checks the <code>info</code> parameter. Because it
|
||||
can be NULL when GListItem <code>item</code> is unbounded. If it’s
|
||||
GFileInfo, it returns the copied filename. Because the return value
|
||||
(filename) of <code>g_file_info_get_name</code> is owned by GFileInfo
|
||||
object. So, the the string needs to be duplicated to give the ownership
|
||||
to the caller. Binding tag binds the “label” property of the GtkLabel to
|
||||
the closure tag.</li>
|
||||
</ul>
|
||||
<p>The whole program (<code>list3.c</code>) is as follows. The program
|
||||
is located in src/misc directory.</p>
|
||||
|
@ -539,70 +543,67 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
|||
<span id="cb11-2"><a href="#cb11-2"></a></span>
|
||||
<span id="cb11-3"><a href="#cb11-3"></a><span class="dt">char</span> <span class="op">*</span></span>
|
||||
<span id="cb11-4"><a href="#cb11-4"></a>get_file_name <span class="op">(</span>GtkListItem <span class="op">*</span>item<span class="op">,</span> GFileInfo <span class="op">*</span>info<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-5"><a href="#cb11-5"></a> <span class="cf">if</span> <span class="op">(!</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">))</span></span>
|
||||
<span id="cb11-6"><a href="#cb11-6"></a> <span class="cf">return</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb11-7"><a href="#cb11-7"></a> <span class="cf">else</span></span>
|
||||
<span id="cb11-8"><a href="#cb11-8"></a> <span class="cf">return</span> g_strdup <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">));</span></span>
|
||||
<span id="cb11-9"><a href="#cb11-9"></a><span class="op">}</span></span>
|
||||
<span id="cb11-10"><a href="#cb11-10"></a></span>
|
||||
<span id="cb11-11"><a href="#cb11-11"></a><span class="co">/* ----- activate, open, startup handlers ----- */</span></span>
|
||||
<span id="cb11-12"><a href="#cb11-12"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb11-13"><a href="#cb11-13"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-14"><a href="#cb11-14"></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="cb11-15"><a href="#cb11-15"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> gtk_application_window_new <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb11-16"><a href="#cb11-16"></a> gtk_window_set_default_size <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> <span class="dv">600</span><span class="op">,</span> <span class="dv">400</span><span class="op">);</span></span>
|
||||
<span id="cb11-17"><a href="#cb11-17"></a> GtkWidget <span class="op">*</span>scr <span class="op">=</span> gtk_scrolled_window_new <span class="op">();</span></span>
|
||||
<span id="cb11-18"><a href="#cb11-18"></a> gtk_window_set_child <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> scr<span class="op">);</span></span>
|
||||
<span id="cb11-19"><a href="#cb11-19"></a></span>
|
||||
<span id="cb11-20"><a href="#cb11-20"></a> GFile <span class="op">*</span>file <span class="op">=</span> g_file_new_for_path <span class="op">(</span><span class="st">"."</span><span class="op">);</span></span>
|
||||
<span id="cb11-21"><a href="#cb11-21"></a> GtkDirectoryList <span class="op">*</span>dl <span class="op">=</span> gtk_directory_list_new <span class="op">(</span><span class="st">"standard::name"</span><span class="op">,</span> file<span class="op">);</span></span>
|
||||
<span id="cb11-22"><a href="#cb11-22"></a> g_object_unref <span class="op">(</span>file<span class="op">);</span></span>
|
||||
<span id="cb11-23"><a href="#cb11-23"></a> GtkNoSelection <span class="op">*</span>ns <span class="op">=</span> gtk_no_selection_new <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>dl<span class="op">));</span></span>
|
||||
<span id="cb11-24"><a href="#cb11-24"></a></span>
|
||||
<span id="cb11-25"><a href="#cb11-25"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>ui_string <span class="op">=</span></span>
|
||||
<span id="cb11-26"><a href="#cb11-26"></a><span class="st">"<interface>"</span></span>
|
||||
<span id="cb11-27"><a href="#cb11-27"></a> <span class="st">"<template class=</span><span class="sc">\"</span><span class="st">GtkListItem</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-28"><a href="#cb11-28"></a> <span class="st">"<property name=</span><span class="sc">\"</span><span class="st">child</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-29"><a href="#cb11-29"></a> <span class="st">"<object class=</span><span class="sc">\"</span><span class="st">GtkLabel</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-30"><a href="#cb11-30"></a> <span class="st">"<binding name=</span><span class="sc">\"</span><span class="st">label</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-31"><a href="#cb11-31"></a> <span class="st">"<closure type=</span><span class="sc">\"</span><span class="st">gchararray</span><span class="sc">\"</span><span class="st"> function=</span><span class="sc">\"</span><span class="st">get_file_name</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-32"><a href="#cb11-32"></a> <span class="st">"<lookup name=</span><span class="sc">\"</span><span class="st">item</span><span class="sc">\"</span><span class="st">>GtkListItem</lookup>"</span></span>
|
||||
<span id="cb11-33"><a href="#cb11-33"></a> <span class="st">"</closure>"</span></span>
|
||||
<span id="cb11-34"><a href="#cb11-34"></a> <span class="st">"</binding>"</span></span>
|
||||
<span id="cb11-35"><a href="#cb11-35"></a> <span class="st">"</object>"</span></span>
|
||||
<span id="cb11-36"><a href="#cb11-36"></a> <span class="st">"</property>"</span></span>
|
||||
<span id="cb11-37"><a href="#cb11-37"></a> <span class="st">"</template>"</span></span>
|
||||
<span id="cb11-38"><a href="#cb11-38"></a><span class="st">"</interface>"</span></span>
|
||||
<span id="cb11-39"><a href="#cb11-39"></a><span class="op">;</span></span>
|
||||
<span id="cb11-40"><a href="#cb11-40"></a> GBytes <span class="op">*</span>gbytes <span class="op">=</span> g_bytes_new_static <span class="op">(</span>ui_string<span class="op">,</span> strlen <span class="op">(</span>ui_string<span class="op">));</span></span>
|
||||
<span id="cb11-41"><a href="#cb11-41"></a> GtkListItemFactory <span class="op">*</span>factory <span class="op">=</span> gtk_builder_list_item_factory_new_from_bytes <span class="op">(</span>NULL<span class="op">,</span> gbytes<span class="op">);</span></span>
|
||||
<span id="cb11-42"><a href="#cb11-42"></a></span>
|
||||
<span id="cb11-43"><a href="#cb11-43"></a> GtkWidget <span class="op">*</span>lv <span class="op">=</span> gtk_list_view_new <span class="op">(</span>GTK_SELECTION_MODEL <span class="op">(</span>ns<span class="op">),</span> factory<span class="op">);</span></span>
|
||||
<span id="cb11-44"><a href="#cb11-44"></a> gtk_scrolled_window_set_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">),</span> lv<span class="op">);</span></span>
|
||||
<span id="cb11-45"><a href="#cb11-45"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb11-49"><a href="#cb11-49"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-50"><a href="#cb11-50"></a><span class="op">}</span></span>
|
||||
<span id="cb11-5"><a href="#cb11-5"></a> <span class="cf">return</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">)</span> <span class="op">?</span> g_strdup <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">))</span> <span class="op">:</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb11-6"><a href="#cb11-6"></a><span class="op">}</span></span>
|
||||
<span id="cb11-7"><a href="#cb11-7"></a></span>
|
||||
<span id="cb11-8"><a href="#cb11-8"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb11-9"><a href="#cb11-9"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-10"><a href="#cb11-10"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
||||
<span id="cb11-11"><a href="#cb11-11"></a> gtk_window_present <span class="op">(</span>gtk_application_get_active_window<span class="op">(</span>app<span class="op">));</span></span>
|
||||
<span id="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><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb11-15"><a href="#cb11-15"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-16"><a href="#cb11-16"></a> GtkApplication <span class="op">*</span>app <span class="op">=</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">);</span></span>
|
||||
<span id="cb11-17"><a href="#cb11-17"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> gtk_application_window_new <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb11-18"><a href="#cb11-18"></a> gtk_window_set_default_size <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> <span class="dv">600</span><span class="op">,</span> <span class="dv">400</span><span class="op">);</span></span>
|
||||
<span id="cb11-19"><a href="#cb11-19"></a> GtkWidget <span class="op">*</span>scr <span class="op">=</span> gtk_scrolled_window_new <span class="op">();</span></span>
|
||||
<span id="cb11-20"><a href="#cb11-20"></a> gtk_window_set_child <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> scr<span class="op">);</span></span>
|
||||
<span id="cb11-21"><a href="#cb11-21"></a></span>
|
||||
<span id="cb11-22"><a href="#cb11-22"></a> GFile <span class="op">*</span>file <span class="op">=</span> g_file_new_for_path <span class="op">(</span><span class="st">"."</span><span class="op">);</span></span>
|
||||
<span id="cb11-23"><a href="#cb11-23"></a> GtkDirectoryList <span class="op">*</span>dl <span class="op">=</span> gtk_directory_list_new <span class="op">(</span><span class="st">"standard::name"</span><span class="op">,</span> file<span class="op">);</span></span>
|
||||
<span id="cb11-24"><a href="#cb11-24"></a> g_object_unref <span class="op">(</span>file<span class="op">);</span></span>
|
||||
<span id="cb11-25"><a href="#cb11-25"></a> GtkNoSelection <span class="op">*</span>ns <span class="op">=</span> gtk_no_selection_new <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>dl<span class="op">));</span></span>
|
||||
<span id="cb11-26"><a href="#cb11-26"></a></span>
|
||||
<span id="cb11-27"><a href="#cb11-27"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>ui_string <span class="op">=</span></span>
|
||||
<span id="cb11-28"><a href="#cb11-28"></a><span class="st">"<interface>"</span></span>
|
||||
<span id="cb11-29"><a href="#cb11-29"></a> <span class="st">"<template class=</span><span class="sc">\"</span><span class="st">GtkListItem</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-30"><a href="#cb11-30"></a> <span class="st">"<property name=</span><span class="sc">\"</span><span class="st">child</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-31"><a href="#cb11-31"></a> <span class="st">"<object class=</span><span class="sc">\"</span><span class="st">GtkLabel</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-32"><a href="#cb11-32"></a> <span class="st">"<binding name=</span><span class="sc">\"</span><span class="st">label</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-33"><a href="#cb11-33"></a> <span class="st">"<closure type=</span><span class="sc">\"</span><span class="st">gchararray</span><span class="sc">\"</span><span class="st"> function=</span><span class="sc">\"</span><span class="st">get_file_name</span><span class="sc">\"</span><span class="st">>"</span></span>
|
||||
<span id="cb11-34"><a href="#cb11-34"></a> <span class="st">"<lookup name=</span><span class="sc">\"</span><span class="st">item</span><span class="sc">\"</span><span class="st">>GtkListItem</lookup>"</span></span>
|
||||
<span id="cb11-35"><a href="#cb11-35"></a> <span class="st">"</closure>"</span></span>
|
||||
<span id="cb11-36"><a href="#cb11-36"></a> <span class="st">"</binding>"</span></span>
|
||||
<span id="cb11-37"><a href="#cb11-37"></a> <span class="st">"</object>"</span></span>
|
||||
<span id="cb11-38"><a href="#cb11-38"></a> <span class="st">"</property>"</span></span>
|
||||
<span id="cb11-39"><a href="#cb11-39"></a> <span class="st">"</template>"</span></span>
|
||||
<span id="cb11-40"><a href="#cb11-40"></a><span class="st">"</interface>"</span></span>
|
||||
<span id="cb11-41"><a href="#cb11-41"></a><span class="op">;</span></span>
|
||||
<span id="cb11-42"><a href="#cb11-42"></a> GBytes <span class="op">*</span>gbytes <span class="op">=</span> g_bytes_new_static <span class="op">(</span>ui_string<span class="op">,</span> strlen <span class="op">(</span>ui_string<span class="op">));</span></span>
|
||||
<span id="cb11-43"><a href="#cb11-43"></a> GtkListItemFactory <span class="op">*</span>factory <span class="op">=</span> gtk_builder_list_item_factory_new_from_bytes <span class="op">(</span>NULL<span class="op">,</span> gbytes<span class="op">);</span></span>
|
||||
<span id="cb11-44"><a href="#cb11-44"></a></span>
|
||||
<span id="cb11-45"><a href="#cb11-45"></a> GtkWidget <span class="op">*</span>lv <span class="op">=</span> gtk_list_view_new <span class="op">(</span>GTK_SELECTION_MODEL <span class="op">(</span>ns<span class="op">),</span> factory<span class="op">);</span></span>
|
||||
<span id="cb11-46"><a href="#cb11-46"></a> gtk_scrolled_window_set_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">),</span> lv<span class="op">);</span></span>
|
||||
<span id="cb11-47"><a href="#cb11-47"></a><span class="op">}</span></span>
|
||||
<span id="cb11-48"><a href="#cb11-48"></a></span>
|
||||
<span id="cb11-49"><a href="#cb11-49"></a><span class="co">/* ----- main ----- */</span></span>
|
||||
<span id="cb11-50"><a href="#cb11-50"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.list3"</span></span>
|
||||
<span id="cb11-51"><a href="#cb11-51"></a></span>
|
||||
<span id="cb11-52"><a href="#cb11-52"></a><span class="co">/* ----- main ----- */</span></span>
|
||||
<span id="cb11-53"><a href="#cb11-53"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.list3"</span></span>
|
||||
<span id="cb11-54"><a href="#cb11-54"></a></span>
|
||||
<span id="cb11-55"><a href="#cb11-55"></a><span class="dt">int</span></span>
|
||||
<span id="cb11-56"><a href="#cb11-56"></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="cb11-57"><a href="#cb11-57"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb11-58"><a href="#cb11-58"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb11-59"><a href="#cb11-59"></a></span>
|
||||
<span id="cb11-60"><a href="#cb11-60"></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="cb11-52"><a href="#cb11-52"></a><span class="dt">int</span></span>
|
||||
<span id="cb11-53"><a href="#cb11-53"></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="cb11-54"><a href="#cb11-54"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb11-55"><a href="#cb11-55"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb11-56"><a href="#cb11-56"></a></span>
|
||||
<span id="cb11-57"><a href="#cb11-57"></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="cb11-58"><a href="#cb11-58"></a></span>
|
||||
<span id="cb11-59"><a href="#cb11-59"></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="cb11-60"><a href="#cb11-60"></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="cb11-61"><a href="#cb11-61"></a></span>
|
||||
<span id="cb11-62"><a href="#cb11-62"></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="cb11-63"><a href="#cb11-63"></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="cb11-64"><a href="#cb11-64"></a></span>
|
||||
<span id="cb11-65"><a href="#cb11-65"></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="cb11-66"><a href="#cb11-66"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb11-67"><a href="#cb11-67"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb11-68"><a href="#cb11-68"></a><span class="op">}</span></span></code></pre></div>
|
||||
<span id="cb11-62"><a href="#cb11-62"></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="cb11-63"><a href="#cb11-63"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb11-64"><a href="#cb11-64"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb11-65"><a href="#cb11-65"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>The ui data (xml data above) is used to build the GListItem template
|
||||
at runtime. GtkBuilder refers to the symbol table to find the function
|
||||
<code>get_file_name</code>.</p>
|
||||
|
|
|
@ -396,26 +396,18 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
|||
<span id="cb8-2"><a href="#cb8-2"></a>get_icon <span class="op">(</span>GtkListItem <span class="op">*</span>item<span class="op">,</span> GFileInfo <span class="op">*</span>info<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb8-3"><a href="#cb8-3"></a> GIcon <span class="op">*</span>icon<span class="op">;</span></span>
|
||||
<span id="cb8-4"><a href="#cb8-4"></a></span>
|
||||
<span id="cb8-5"><a href="#cb8-5"></a> <span class="cf">if</span> <span class="op">(!</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">))</span></span>
|
||||
<span id="cb8-6"><a href="#cb8-6"></a> <span class="cf">return</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb8-7"><a href="#cb8-7"></a> <span class="cf">else</span> <span class="op">{</span></span>
|
||||
<span id="cb8-8"><a href="#cb8-8"></a> icon <span class="op">=</span> g_file_info_get_icon <span class="op">(</span>info<span class="op">);</span></span>
|
||||
<span id="cb8-9"><a href="#cb8-9"></a> g_object_ref <span class="op">(</span>icon<span class="op">);</span></span>
|
||||
<span id="cb8-10"><a href="#cb8-10"></a> <span class="cf">return</span> icon<span class="op">;</span></span>
|
||||
<span id="cb8-11"><a href="#cb8-11"></a> <span class="op">}</span></span>
|
||||
<span id="cb8-12"><a href="#cb8-12"></a><span class="op">}</span></span>
|
||||
<span id="cb8-13"><a href="#cb8-13"></a></span>
|
||||
<span id="cb8-14"><a href="#cb8-14"></a><span class="dt">char</span> <span class="op">*</span></span>
|
||||
<span id="cb8-15"><a href="#cb8-15"></a>get_file_name <span class="op">(</span>GtkListItem <span class="op">*</span>item<span class="op">,</span> GFileInfo <span class="op">*</span>info<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb8-16"><a href="#cb8-16"></a> <span class="cf">if</span> <span class="op">(!</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">))</span></span>
|
||||
<span id="cb8-17"><a href="#cb8-17"></a> <span class="cf">return</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb8-18"><a href="#cb8-18"></a> <span class="cf">else</span></span>
|
||||
<span id="cb8-19"><a href="#cb8-19"></a> <span class="cf">return</span> g_strdup <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">));</span></span>
|
||||
<span id="cb8-20"><a href="#cb8-20"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>One important thing is the ownership of the return values. When
|
||||
GtkExpression (closure tag creates a GtkCClosureExpression – a child
|
||||
class of GtkExpression) is evaluated, the value is owned by the caller.
|
||||
So, <code>g_obect_ref</code> or <code>g_strdup</code> is necessary.</p>
|
||||
<span id="cb8-5"><a href="#cb8-5"></a> <span class="co">/* g_file_info_get_icon can return NULL */</span></span>
|
||||
<span id="cb8-6"><a href="#cb8-6"></a> icon <span class="op">=</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">)</span> <span class="op">?</span> g_file_info_get_icon <span class="op">(</span>info<span class="op">)</span> <span class="op">:</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb8-7"><a href="#cb8-7"></a> <span class="cf">return</span> icon <span class="op">?</span> g_object_ref <span class="op">(</span>icon<span class="op">)</span> <span class="op">:</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb8-8"><a href="#cb8-8"></a><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">char</span> <span class="op">*</span></span>
|
||||
<span id="cb8-11"><a href="#cb8-11"></a>get_file_name <span class="op">(</span>GtkListItem <span class="op">*</span>item<span class="op">,</span> GFileInfo <span class="op">*</span>info<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb8-12"><a href="#cb8-12"></a> <span class="cf">return</span> G_IS_FILE_INFO <span class="op">(</span>info<span class="op">)</span> <span class="op">?</span> g_strdup <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">))</span> <span class="op">:</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb8-13"><a href="#cb8-13"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>One important thing is the ownership of the return values. The return
|
||||
value is owned by the caller. So, <code>g_obect_ref</code> or
|
||||
<code>g_strdup</code> is necessary.</p>
|
||||
<h2 id="an-activate-signal-handler-of-the-button-action">An activate
|
||||
signal handler of the button action</h2>
|
||||
<p>An activate signal handler <code>view_activate</code> switches the
|
||||
|
|
347
gfm/sec26.md
347
gfm/sec26.md
|
@ -24,12 +24,12 @@ There are two cases.
|
|||
One is the index starts from one (one-based) and the other is from zero (zero-based).
|
||||
|
||||
Gio provides GListModel interface.
|
||||
It is a zero-based list of the same type of GObject descendants, or objects that implement the same interface.
|
||||
It is a zero-based list and its items are the same type of GObject descendants, or objects that implement the same interface.
|
||||
An object implements GListModel is not a widget.
|
||||
So, the list is not displayed on the screen directly.
|
||||
There's another object GtkListView which is a widget to display the list.
|
||||
The items in the list need to be connected to the items in GtkListView.
|
||||
GtkListItemFactory object maps items in the list to GListView.
|
||||
GtkListItemFactory instance maps items in the list to GListView.
|
||||
|
||||
![List](../image/list.png)
|
||||
|
||||
|
@ -64,8 +64,8 @@ GtkSelectionModel is an interface to support for selections.
|
|||
Thanks to this model, user can select items by clicking on them.
|
||||
It is implemented by GtkMultiSelection, GtkNoSelection and GtkSingleSelection objects.
|
||||
These three objects are usually enough to build an application.
|
||||
They are created with GListModel.
|
||||
You can also create them alone and add GListModel later.
|
||||
They are created with another GListModel.
|
||||
You can also create them alone and add a GListModel later.
|
||||
|
||||
- GtkMultiSelection supports multiple selection.
|
||||
- GtkNoSelection supports no selection. This is a wrapper to GListModel when GtkSelectionModel is needed.
|
||||
|
@ -87,7 +87,7 @@ This is very effective to restrain the growth of memory consumption so that GLis
|
|||
## GtkListItemFactory
|
||||
|
||||
GtkListItemFactory creates or recycles GtkListItem and connects it with an item of the list model.
|
||||
There are two child objects of this factory, GtkSignalListItemFactory and GtkBuilderListItemFactory.
|
||||
There are two child classes of this factory, GtkSignalListItemFactory and GtkBuilderListItemFactory.
|
||||
|
||||
### GtkSignalListItemFactory
|
||||
|
||||
|
@ -96,7 +96,7 @@ There are four signals.
|
|||
|
||||
1. "setup" is emitted to set up GtkListItem object.
|
||||
A user sets its child widget in the handler.
|
||||
For example, creates a GtkLabel widget and sets the child property of GtkListItem with it.
|
||||
For example, creates a GtkLabel widget and sets the child property of the GtkListItem to it.
|
||||
This setting is kept even the GtkListItem instance is recycled (to bind to another item of GListModel).
|
||||
2. "bind" is emitted to bind an item in the list model to the widget.
|
||||
For example, a user gets the item from "item" property of the GtkListItem instance.
|
||||
|
@ -119,16 +119,16 @@ GtkNoSelection is used, so user can't select any item.
|
|||
4 setup_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_data) {
|
||||
5 GtkWidget *lb = gtk_label_new (NULL);
|
||||
6 gtk_list_item_set_child (listitem, lb);
|
||||
7 }
|
||||
8
|
||||
9 static void
|
||||
10 bind_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_data) {
|
||||
11 GtkWidget *lb = gtk_list_item_get_child (listitem);
|
||||
12 /* Strobj is owned by the instance. Caller mustn't change or destroy it. */
|
||||
13 GtkStringObject *strobj = gtk_list_item_get_item (listitem);
|
||||
14 const char *text = gtk_string_object_get_string (strobj);
|
||||
15
|
||||
16 gtk_label_set_text (GTK_LABEL (lb), text);
|
||||
7 /* Because gtk_list_item_set_child sunk the floating reference of lb, releasing (unref) isn't necessary for lb. */
|
||||
8 }
|
||||
9
|
||||
10 static void
|
||||
11 bind_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_data) {
|
||||
12 GtkWidget *lb = gtk_list_item_get_child (listitem);
|
||||
13 /* Strobj is owned by the instance. Caller mustn't change or destroy it. */
|
||||
14 GtkStringObject *strobj = gtk_list_item_get_item (listitem);
|
||||
15 /* The string returned by gtk_string_object_get_string is owned by the instance. */
|
||||
16 gtk_label_set_text (GTK_LABEL (lb), gtk_string_object_get_string (strobj));
|
||||
17 }
|
||||
18
|
||||
19 static void
|
||||
|
@ -138,8 +138,8 @@ GtkNoSelection is used, so user can't select any item.
|
|||
23
|
||||
24 static void
|
||||
25 teardown_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_data) {
|
||||
26 gtk_list_item_set_child (listitem, NULL);
|
||||
27 /* The previous child is destroyed automatically. */
|
||||
26 /* There's nothing to do here. */
|
||||
27 /* GtkListItem instance will be destroyed soon. You don't need to set the child to NULL. */
|
||||
28 }
|
||||
29
|
||||
30 static void
|
||||
|
@ -162,30 +162,31 @@ GtkNoSelection is used, so user can't select any item.
|
|||
47 GtkListItemFactory *factory = gtk_signal_list_item_factory_new ();
|
||||
48 g_signal_connect (factory, "setup", G_CALLBACK (setup_cb), NULL);
|
||||
49 g_signal_connect (factory, "bind", G_CALLBACK (bind_cb), NULL);
|
||||
50 g_signal_connect (factory, "unbind", G_CALLBACK (unbind_cb), NULL);
|
||||
51 g_signal_connect (factory, "teardown", G_CALLBACK (teardown_cb), NULL);
|
||||
52
|
||||
53 GtkWidget *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ns), factory);
|
||||
54 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);
|
||||
55 gtk_window_present (GTK_WINDOW (win));
|
||||
56 }
|
||||
57
|
||||
58 /* ----- main ----- */
|
||||
59 #define APPLICATION_ID "com.github.ToshioCP.list1"
|
||||
60
|
||||
61 int
|
||||
62 main (int argc, char **argv) {
|
||||
63 GtkApplication *app;
|
||||
64 int stat;
|
||||
65
|
||||
66 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_DEFAULT_FLAGS);
|
||||
67
|
||||
68 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||
69
|
||||
70 stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||
71 g_object_unref (app);
|
||||
72 return stat;
|
||||
73 }
|
||||
50 /* The following two lines can be left out. The handlers do nothing. */
|
||||
51 g_signal_connect (factory, "unbind", G_CALLBACK (unbind_cb), NULL);
|
||||
52 g_signal_connect (factory, "teardown", G_CALLBACK (teardown_cb), NULL);
|
||||
53
|
||||
54 GtkWidget *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ns), factory);
|
||||
55 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);
|
||||
56 gtk_window_present (GTK_WINDOW (win));
|
||||
57 }
|
||||
58
|
||||
59 /* ----- main ----- */
|
||||
60 #define APPLICATION_ID "com.github.ToshioCP.list1"
|
||||
61
|
||||
62 int
|
||||
63 main (int argc, char **argv) {
|
||||
64 GtkApplication *app;
|
||||
65 int stat;
|
||||
66
|
||||
67 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_DEFAULT_FLAGS);
|
||||
68
|
||||
69 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||
70
|
||||
71 stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||
72 g_object_unref (app);
|
||||
73 return stat;
|
||||
74 }
|
||||
~~~
|
||||
|
||||
The file `list1.c` is located under the directory [src/misc](../src/misc).
|
||||
|
@ -236,18 +237,18 @@ And its child property is GtkLabel object.
|
|||
The factory sees this template and creates GtkLabel and sets the child property of GtkListItem.
|
||||
This is the same as what setup handler of GtkSignalListItemFactory did.
|
||||
|
||||
Then, bind the label property of GtkLabel to string property of GtkStringObject.
|
||||
The string object is referred to by item property of GtkListItem.
|
||||
Then, bind the label property of the GtkLabel to the string property of a GtkStringObject.
|
||||
The string object refers to the item property of the GtkListItem.
|
||||
So, the lookup tag is like this:
|
||||
|
||||
~~~
|
||||
string <- GtkStringObject <- item <- GtkListItem
|
||||
label <- string <- GtkStringObject <- item <- GtkListItem
|
||||
~~~
|
||||
|
||||
The last lookup tag has a content `GtkListItem`.
|
||||
Usually, C type like `GtkListItem` doesn't appear in the content of tags.
|
||||
This is a special case.
|
||||
There is an explanation about it in the [GTK Development Blog](https://blog.gtk.org/2020/09/05/a-primer-on-gtklistview/) by Matthias Clasen.
|
||||
There is an explanation in the [GTK Development Blog](https://blog.gtk.org/2020/09/05/a-primer-on-gtklistview/) by Matthias Clasen.
|
||||
|
||||
> Remember that the classname (GtkListItem) in a ui template is used as the “this” pointer referring to the object that is being instantiated.
|
||||
|
||||
|
@ -260,61 +261,66 @@ Its name is `list2.c` and located under [src/misc](../src/misc) directory.
|
|||
~~~C
|
||||
1 #include <gtk/gtk.h>
|
||||
2
|
||||
3 /* ----- activate, open, startup handlers ----- */
|
||||
4 static void
|
||||
5 app_activate (GApplication *application) {
|
||||
6 GtkApplication *app = GTK_APPLICATION (application);
|
||||
7 GtkWidget *win = gtk_application_window_new (app);
|
||||
8 gtk_window_set_default_size (GTK_WINDOW (win), 600, 400);
|
||||
9 GtkWidget *scr = gtk_scrolled_window_new ();
|
||||
10 gtk_window_set_child (GTK_WINDOW (win), scr);
|
||||
11
|
||||
12 char *array[] = {
|
||||
13 "one", "two", "three", "four", NULL
|
||||
14 };
|
||||
15 GtkStringList *sl = gtk_string_list_new ((const char * const *) array);
|
||||
16 GtkSingleSelection *ss = gtk_single_selection_new (G_LIST_MODEL (sl));
|
||||
17
|
||||
18 const char *ui_string =
|
||||
19 "<interface>"
|
||||
20 "<template class=\"GtkListItem\">"
|
||||
21 "<property name=\"child\">"
|
||||
22 "<object class=\"GtkLabel\">"
|
||||
23 "<binding name=\"label\">"
|
||||
24 "<lookup name=\"string\" type=\"GtkStringObject\">"
|
||||
25 "<lookup name=\"item\">GtkListItem</lookup>"
|
||||
26 "</lookup>"
|
||||
27 "</binding>"
|
||||
28 "</object>"
|
||||
29 "</property>"
|
||||
30 "</template>"
|
||||
31 "</interface>"
|
||||
32 ;
|
||||
33 GBytes *gbytes = g_bytes_new_static (ui_string, strlen (ui_string));
|
||||
34 GtkListItemFactory *factory = gtk_builder_list_item_factory_new_from_bytes (NULL, gbytes);
|
||||
35
|
||||
36 GtkWidget *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ss), factory);
|
||||
37 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);
|
||||
38 gtk_window_present (GTK_WINDOW (win));
|
||||
39 }
|
||||
3 static void
|
||||
4 app_activate (GApplication *application) {
|
||||
5 GtkApplication *app = GTK_APPLICATION (application);
|
||||
6 gtk_window_present (gtk_application_get_active_window(app));
|
||||
7 }
|
||||
8
|
||||
9 static void
|
||||
10 app_startup (GApplication *application) {
|
||||
11 GtkApplication *app = GTK_APPLICATION (application);
|
||||
12 GtkWidget *win = gtk_application_window_new (app);
|
||||
13 gtk_window_set_default_size (GTK_WINDOW (win), 600, 400);
|
||||
14 GtkWidget *scr = gtk_scrolled_window_new ();
|
||||
15 gtk_window_set_child (GTK_WINDOW (win), scr);
|
||||
16
|
||||
17 char *array[] = {
|
||||
18 "one", "two", "three", "four", NULL
|
||||
19 };
|
||||
20 GtkStringList *sl = gtk_string_list_new ((const char * const *) array);
|
||||
21 GtkSingleSelection *ss = gtk_single_selection_new (G_LIST_MODEL (sl));
|
||||
22
|
||||
23 const char *ui_string =
|
||||
24 "<interface>"
|
||||
25 "<template class=\"GtkListItem\">"
|
||||
26 "<property name=\"child\">"
|
||||
27 "<object class=\"GtkLabel\">"
|
||||
28 "<binding name=\"label\">"
|
||||
29 "<lookup name=\"string\" type=\"GtkStringObject\">"
|
||||
30 "<lookup name=\"item\">GtkListItem</lookup>"
|
||||
31 "</lookup>"
|
||||
32 "</binding>"
|
||||
33 "</object>"
|
||||
34 "</property>"
|
||||
35 "</template>"
|
||||
36 "</interface>"
|
||||
37 ;
|
||||
38 GBytes *gbytes = g_bytes_new_static (ui_string, strlen (ui_string));
|
||||
39 GtkListItemFactory *factory = gtk_builder_list_item_factory_new_from_bytes (NULL, gbytes);
|
||||
40
|
||||
41 /* ----- main ----- */
|
||||
42 #define APPLICATION_ID "com.github.ToshioCP.list2"
|
||||
43
|
||||
44 int
|
||||
45 main (int argc, char **argv) {
|
||||
46 GtkApplication *app;
|
||||
47 int stat;
|
||||
48
|
||||
49 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_DEFAULT_FLAGS);
|
||||
50
|
||||
51 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||
41 GtkWidget *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ss), factory);
|
||||
42 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);
|
||||
43 }
|
||||
44
|
||||
45 /* ----- main ----- */
|
||||
46 #define APPLICATION_ID "com.github.ToshioCP.list2"
|
||||
47
|
||||
48 int
|
||||
49 main (int argc, char **argv) {
|
||||
50 GtkApplication *app;
|
||||
51 int stat;
|
||||
52
|
||||
53 stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||
54 g_object_unref (app);
|
||||
55 return stat;
|
||||
56 }
|
||||
53 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_DEFAULT_FLAGS);
|
||||
54
|
||||
55 g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL);
|
||||
56 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||
57
|
||||
58 stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||
59 g_object_unref (app);
|
||||
60 return stat;
|
||||
61 }
|
||||
62
|
||||
~~~
|
||||
|
||||
No signal handler is needed for GtkBulderListItemFactory.
|
||||
|
@ -366,12 +372,8 @@ Closure tag specifies a function and the type of the return value of the functio
|
|||
~~~C
|
||||
const char *
|
||||
get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||
if (! G_IS_FILE_INFO (info))
|
||||
return NULL;
|
||||
else
|
||||
return g_strdup (g_file_info_get_name (info));
|
||||
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||
}
|
||||
|
||||
... ...
|
||||
... ...
|
||||
|
||||
|
@ -390,8 +392,8 @@ get_file_name (GtkListItem *item, GFileInfo *info) {
|
|||
"</interface>"
|
||||
~~~
|
||||
|
||||
- The string "gchararray" is the type name of strings.
|
||||
The type "gchar" is the same as "char".
|
||||
- The string "gchararray" is a type name.
|
||||
The type "gchar" is a type name and it is the same as C type "char".
|
||||
Therefore, "gchararray" is "an array of char type", which is the same as string type.
|
||||
It is used to get the type of GValue object.
|
||||
GValue is a generic value and it can contain various type of values.
|
||||
|
@ -403,13 +405,15 @@ Function attribute specifies the function name and type attribute specifies the
|
|||
The contents of closure tag (it is between \<closure...\> and\</closure\>) is parameters of the function.
|
||||
`<lookup name="item">GtkListItem</lookup>` gives the value of the item property of the GtkListItem.
|
||||
This will be the second argument of the function.
|
||||
The first parameter is always the GListItem instance.
|
||||
- `gtk_file_name` function first checks the `info` parameter.
|
||||
The first parameter is always the GListItem instance, which is a 'this' object.
|
||||
The 'this' object is explained in section 28.
|
||||
- `gtk_file_name` function is the callback function for the closure tag.
|
||||
It first checks the `info` parameter.
|
||||
Because it can be NULL when GListItem `item` is unbounded.
|
||||
If it's GFileInfo, it returns the filename.
|
||||
The filename is owned by GFileInfo object.
|
||||
So, the function `get_file_name` duplicates the string to own the newly created one.
|
||||
Closure tag binds the property of the outer tag (GtkLabel) to the filename.
|
||||
If it's GFileInfo, it returns the copied filename.
|
||||
Because the return value (filename) of `g_file_info_get_name` is owned by GFileInfo object.
|
||||
So, the the string needs to be duplicated to give the ownership to the caller.
|
||||
Binding tag binds the "label" property of the GtkLabel to the closure tag.
|
||||
|
||||
The whole program (`list3.c`) is as follows.
|
||||
The program is located in [src/misc](../src/misc) directory.
|
||||
|
@ -419,70 +423,67 @@ The program is located in [src/misc](../src/misc) directory.
|
|||
2
|
||||
3 char *
|
||||
4 get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||
5 if (! G_IS_FILE_INFO (info))
|
||||
6 return NULL;
|
||||
7 else
|
||||
8 return g_strdup (g_file_info_get_name (info));
|
||||
9 }
|
||||
10
|
||||
11 /* ----- activate, open, startup handlers ----- */
|
||||
12 static void
|
||||
13 app_activate (GApplication *application) {
|
||||
14 GtkApplication *app = GTK_APPLICATION (application);
|
||||
15 GtkWidget *win = gtk_application_window_new (app);
|
||||
16 gtk_window_set_default_size (GTK_WINDOW (win), 600, 400);
|
||||
17 GtkWidget *scr = gtk_scrolled_window_new ();
|
||||
18 gtk_window_set_child (GTK_WINDOW (win), scr);
|
||||
19
|
||||
20 GFile *file = g_file_new_for_path (".");
|
||||
21 GtkDirectoryList *dl = gtk_directory_list_new ("standard::name", file);
|
||||
22 g_object_unref (file);
|
||||
23 GtkNoSelection *ns = gtk_no_selection_new (G_LIST_MODEL (dl));
|
||||
24
|
||||
25 const char *ui_string =
|
||||
26 "<interface>"
|
||||
27 "<template class=\"GtkListItem\">"
|
||||
28 "<property name=\"child\">"
|
||||
29 "<object class=\"GtkLabel\">"
|
||||
30 "<binding name=\"label\">"
|
||||
31 "<closure type=\"gchararray\" function=\"get_file_name\">"
|
||||
32 "<lookup name=\"item\">GtkListItem</lookup>"
|
||||
33 "</closure>"
|
||||
34 "</binding>"
|
||||
35 "</object>"
|
||||
36 "</property>"
|
||||
37 "</template>"
|
||||
38 "</interface>"
|
||||
39 ;
|
||||
40 GBytes *gbytes = g_bytes_new_static (ui_string, strlen (ui_string));
|
||||
41 GtkListItemFactory *factory = gtk_builder_list_item_factory_new_from_bytes (NULL, gbytes);
|
||||
42
|
||||
43 GtkWidget *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ns), factory);
|
||||
44 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);
|
||||
45 gtk_window_present (GTK_WINDOW (win));
|
||||
46 }
|
||||
47
|
||||
48 static void
|
||||
49 app_startup (GApplication *application) {
|
||||
50 }
|
||||
5 return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||
6 }
|
||||
7
|
||||
8 static void
|
||||
9 app_activate (GApplication *application) {
|
||||
10 GtkApplication *app = GTK_APPLICATION (application);
|
||||
11 gtk_window_present (gtk_application_get_active_window(app));
|
||||
12 }
|
||||
13
|
||||
14 static void
|
||||
15 app_startup (GApplication *application) {
|
||||
16 GtkApplication *app = GTK_APPLICATION (application);
|
||||
17 GtkWidget *win = gtk_application_window_new (app);
|
||||
18 gtk_window_set_default_size (GTK_WINDOW (win), 600, 400);
|
||||
19 GtkWidget *scr = gtk_scrolled_window_new ();
|
||||
20 gtk_window_set_child (GTK_WINDOW (win), scr);
|
||||
21
|
||||
22 GFile *file = g_file_new_for_path (".");
|
||||
23 GtkDirectoryList *dl = gtk_directory_list_new ("standard::name", file);
|
||||
24 g_object_unref (file);
|
||||
25 GtkNoSelection *ns = gtk_no_selection_new (G_LIST_MODEL (dl));
|
||||
26
|
||||
27 const char *ui_string =
|
||||
28 "<interface>"
|
||||
29 "<template class=\"GtkListItem\">"
|
||||
30 "<property name=\"child\">"
|
||||
31 "<object class=\"GtkLabel\">"
|
||||
32 "<binding name=\"label\">"
|
||||
33 "<closure type=\"gchararray\" function=\"get_file_name\">"
|
||||
34 "<lookup name=\"item\">GtkListItem</lookup>"
|
||||
35 "</closure>"
|
||||
36 "</binding>"
|
||||
37 "</object>"
|
||||
38 "</property>"
|
||||
39 "</template>"
|
||||
40 "</interface>"
|
||||
41 ;
|
||||
42 GBytes *gbytes = g_bytes_new_static (ui_string, strlen (ui_string));
|
||||
43 GtkListItemFactory *factory = gtk_builder_list_item_factory_new_from_bytes (NULL, gbytes);
|
||||
44
|
||||
45 GtkWidget *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ns), factory);
|
||||
46 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);
|
||||
47 }
|
||||
48
|
||||
49 /* ----- main ----- */
|
||||
50 #define APPLICATION_ID "com.github.ToshioCP.list3"
|
||||
51
|
||||
52 /* ----- main ----- */
|
||||
53 #define APPLICATION_ID "com.github.ToshioCP.list3"
|
||||
54
|
||||
55 int
|
||||
56 main (int argc, char **argv) {
|
||||
57 GtkApplication *app;
|
||||
58 int stat;
|
||||
59
|
||||
60 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_DEFAULT_FLAGS);
|
||||
52 int
|
||||
53 main (int argc, char **argv) {
|
||||
54 GtkApplication *app;
|
||||
55 int stat;
|
||||
56
|
||||
57 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_DEFAULT_FLAGS);
|
||||
58
|
||||
59 g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL);
|
||||
60 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||
61
|
||||
62 g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL);
|
||||
63 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||
64
|
||||
65 stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||
66 g_object_unref (app);
|
||||
67 return stat;
|
||||
68 }
|
||||
62 stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||
63 g_object_unref (app);
|
||||
64 return stat;
|
||||
65 }
|
||||
~~~
|
||||
|
||||
The ui data (xml data above) is used to build the GListItem template at runtime.
|
||||
|
|
28
gfm/sec27.md
28
gfm/sec27.md
|
@ -306,27 +306,19 @@ And a function `get_file_name` gets a filename from the GFileInfo object.
|
|||
2 get_icon (GtkListItem *item, GFileInfo *info) {
|
||||
3 GIcon *icon;
|
||||
4
|
||||
5 if (! G_IS_FILE_INFO (info))
|
||||
6 return NULL;
|
||||
7 else {
|
||||
8 icon = g_file_info_get_icon (info);
|
||||
9 g_object_ref (icon);
|
||||
10 return icon;
|
||||
11 }
|
||||
12 }
|
||||
13
|
||||
14 char *
|
||||
15 get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||
16 if (! G_IS_FILE_INFO (info))
|
||||
17 return NULL;
|
||||
18 else
|
||||
19 return g_strdup (g_file_info_get_name (info));
|
||||
20 }
|
||||
5 /* g_file_info_get_icon can return NULL */
|
||||
6 icon = G_IS_FILE_INFO (info) ? g_file_info_get_icon (info) : NULL;
|
||||
7 return icon ? g_object_ref (icon) : NULL;
|
||||
8 }
|
||||
9
|
||||
10 char *
|
||||
11 get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||
12 return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||
13 }
|
||||
~~~
|
||||
|
||||
One important thing is the ownership of the return values.
|
||||
When GtkExpression (closure tag creates a GtkCClosureExpression -- a child class of GtkExpression) is evaluated,
|
||||
the value is owned by the caller.
|
||||
The return value is owned by the caller.
|
||||
So, `g_obect_ref` or `g_strdup` is necessary.
|
||||
|
||||
## An activate signal handler of the button action
|
||||
|
|
|
@ -88,21 +88,14 @@ GIcon *
|
|||
get_icon (GtkListItem *item, GFileInfo *info) {
|
||||
GIcon *icon;
|
||||
|
||||
if (! G_IS_FILE_INFO (info))
|
||||
return NULL;
|
||||
else {
|
||||
icon = g_file_info_get_icon (info);
|
||||
g_object_ref (icon);
|
||||
return icon;
|
||||
}
|
||||
/* g_file_info_get_icon can return NULL */
|
||||
icon = G_IS_FILE_INFO (info) ? g_file_info_get_icon (info) : NULL;
|
||||
return icon ? g_object_ref (icon) : NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||
if (! G_IS_FILE_INFO (info))
|
||||
return NULL;
|
||||
else
|
||||
return g_strdup (g_file_info_get_name (info));
|
||||
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -88,21 +88,14 @@ GIcon *
|
|||
get_icon (GtkListItem *item, GFileInfo *info) {
|
||||
GIcon *icon;
|
||||
|
||||
if (! G_IS_FILE_INFO (info))
|
||||
return NULL;
|
||||
else {
|
||||
icon = g_file_info_get_icon (info);
|
||||
g_object_ref (icon);
|
||||
return icon;
|
||||
}
|
||||
/* g_file_info_get_icon can return NULL */
|
||||
icon = G_IS_FILE_INFO (info) ? g_file_info_get_icon (info) : NULL;
|
||||
return icon ? g_object_ref (icon) : NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||
if (! G_IS_FILE_INFO (info))
|
||||
return NULL;
|
||||
else
|
||||
return g_strdup (g_file_info_get_name (info));
|
||||
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -4,6 +4,7 @@ static void
|
|||
setup_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_data) {
|
||||
GtkWidget *lb = gtk_label_new (NULL);
|
||||
gtk_list_item_set_child (listitem, lb);
|
||||
/* Because gtk_list_item_set_child sunk the floating reference of lb, releasing (unref) isn't necessary for lb. */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -11,9 +12,8 @@ bind_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_da
|
|||
GtkWidget *lb = gtk_list_item_get_child (listitem);
|
||||
/* Strobj is owned by the instance. Caller mustn't change or destroy it. */
|
||||
GtkStringObject *strobj = gtk_list_item_get_item (listitem);
|
||||
const char *text = gtk_string_object_get_string (strobj);
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (lb), text);
|
||||
/* The string returned by gtk_string_object_get_string is owned by the instance. */
|
||||
gtk_label_set_text (GTK_LABEL (lb), gtk_string_object_get_string (strobj));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -23,8 +23,8 @@ unbind_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_
|
|||
|
||||
static void
|
||||
teardown_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_data) {
|
||||
gtk_list_item_set_child (listitem, NULL);
|
||||
/* The previous child is destroyed automatically. */
|
||||
/* There's nothing to do here. */
|
||||
/* GtkListItem instance will be destroyed soon. You don't need to set the child to NULL. */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -47,6 +47,7 @@ app_activate (GApplication *application) {
|
|||
GtkListItemFactory *factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_cb), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_cb), NULL);
|
||||
/* The following two lines can be left out. The handlers do nothing. */
|
||||
g_signal_connect (factory, "unbind", G_CALLBACK (unbind_cb), NULL);
|
||||
g_signal_connect (factory, "teardown", G_CALLBACK (teardown_cb), NULL);
|
||||
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
#include <gtk/gtk.h>
|
||||
|
||||
/* ----- activate, open, startup handlers ----- */
|
||||
static void
|
||||
app_activate (GApplication *application) {
|
||||
GtkApplication *app = GTK_APPLICATION (application);
|
||||
gtk_window_present (gtk_application_get_active_window(app));
|
||||
}
|
||||
|
||||
static void
|
||||
app_startup (GApplication *application) {
|
||||
GtkApplication *app = GTK_APPLICATION (application);
|
||||
GtkWidget *win = gtk_application_window_new (app);
|
||||
gtk_window_set_default_size (GTK_WINDOW (win), 600, 400);
|
||||
|
@ -35,7 +40,6 @@ app_activate (GApplication *application) {
|
|||
|
||||
GtkWidget *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ss), factory);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
|
||||
/* ----- main ----- */
|
||||
|
@ -48,6 +52,7 @@ main (int argc, char **argv) {
|
|||
|
||||
app = gtk_application_new (APPLICATION_ID, G_APPLICATION_DEFAULT_FLAGS);
|
||||
|
||||
g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL);
|
||||
g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||
|
||||
stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||
|
|
|
@ -2,15 +2,17 @@
|
|||
|
||||
char *
|
||||
get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||
if (! G_IS_FILE_INFO (info))
|
||||
return NULL;
|
||||
else
|
||||
return g_strdup (g_file_info_get_name (info));
|
||||
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||
}
|
||||
|
||||
/* ----- activate, open, startup handlers ----- */
|
||||
static void
|
||||
app_activate (GApplication *application) {
|
||||
GtkApplication *app = GTK_APPLICATION (application);
|
||||
gtk_window_present (gtk_application_get_active_window(app));
|
||||
}
|
||||
|
||||
static void
|
||||
app_startup (GApplication *application) {
|
||||
GtkApplication *app = GTK_APPLICATION (application);
|
||||
GtkWidget *win = gtk_application_window_new (app);
|
||||
gtk_window_set_default_size (GTK_WINDOW (win), 600, 400);
|
||||
|
@ -42,11 +44,6 @@ app_activate (GApplication *application) {
|
|||
|
||||
GtkWidget *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ns), factory);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
|
||||
static void
|
||||
app_startup (GApplication *application) {
|
||||
}
|
||||
|
||||
/* ----- main ----- */
|
||||
|
|
|
@ -22,12 +22,12 @@ There are two cases.
|
|||
One is the index starts from one (one-based) and the other is from zero (zero-based).
|
||||
|
||||
Gio provides GListModel interface.
|
||||
It is a zero-based list of the same type of GObject descendants, or objects that implement the same interface.
|
||||
It is a zero-based list and its items are the same type of GObject descendants, or objects that implement the same interface.
|
||||
An object implements GListModel is not a widget.
|
||||
So, the list is not displayed on the screen directly.
|
||||
There's another object GtkListView which is a widget to display the list.
|
||||
The items in the list need to be connected to the items in GtkListView.
|
||||
GtkListItemFactory object maps items in the list to GListView.
|
||||
GtkListItemFactory instance maps items in the list to GListView.
|
||||
|
||||
![List](../image/list.png){width=10cm height=7.5cm}
|
||||
|
||||
|
@ -79,8 +79,8 @@ GtkSelectionModel is an interface to support for selections.
|
|||
Thanks to this model, user can select items by clicking on them.
|
||||
It is implemented by GtkMultiSelection, GtkNoSelection and GtkSingleSelection objects.
|
||||
These three objects are usually enough to build an application.
|
||||
They are created with GListModel.
|
||||
You can also create them alone and add GListModel later.
|
||||
They are created with another GListModel.
|
||||
You can also create them alone and add a GListModel later.
|
||||
|
||||
- GtkMultiSelection supports multiple selection.
|
||||
- GtkNoSelection supports no selection. This is a wrapper to GListModel when GtkSelectionModel is needed.
|
||||
|
@ -102,7 +102,7 @@ This is very effective to restrain the growth of memory consumption so that GLis
|
|||
## GtkListItemFactory
|
||||
|
||||
GtkListItemFactory creates or recycles GtkListItem and connects it with an item of the list model.
|
||||
There are two child objects of this factory, GtkSignalListItemFactory and GtkBuilderListItemFactory.
|
||||
There are two child classes of this factory, GtkSignalListItemFactory and GtkBuilderListItemFactory.
|
||||
|
||||
### GtkSignalListItemFactory
|
||||
|
||||
|
@ -111,7 +111,7 @@ There are four signals.
|
|||
|
||||
1. "setup" is emitted to set up GtkListItem object.
|
||||
A user sets its child widget in the handler.
|
||||
For example, creates a GtkLabel widget and sets the child property of GtkListItem with it.
|
||||
For example, creates a GtkLabel widget and sets the child property of the GtkListItem to it.
|
||||
This setting is kept even the GtkListItem instance is recycled (to bind to another item of GListModel).
|
||||
2. "bind" is emitted to bind an item in the list model to the widget.
|
||||
For example, a user gets the item from "item" property of the GtkListItem instance.
|
||||
|
@ -193,18 +193,18 @@ And its child property is GtkLabel object.
|
|||
The factory sees this template and creates GtkLabel and sets the child property of GtkListItem.
|
||||
This is the same as what setup handler of GtkSignalListItemFactory did.
|
||||
|
||||
Then, bind the label property of GtkLabel to string property of GtkStringObject.
|
||||
The string object is referred to by item property of GtkListItem.
|
||||
Then, bind the label property of the GtkLabel to the string property of a GtkStringObject.
|
||||
The string object refers to the item property of the GtkListItem.
|
||||
So, the lookup tag is like this:
|
||||
|
||||
~~~
|
||||
string <- GtkStringObject <- item <- GtkListItem
|
||||
label <- string <- GtkStringObject <- item <- GtkListItem
|
||||
~~~
|
||||
|
||||
The last lookup tag has a content `GtkListItem`.
|
||||
Usually, C type like `GtkListItem` doesn't appear in the content of tags.
|
||||
This is a special case.
|
||||
There is an explanation about it in the [GTK Development Blog](https://blog.gtk.org/2020/09/05/a-primer-on-gtklistview/) by Matthias Clasen.
|
||||
There is an explanation in the [GTK Development Blog](https://blog.gtk.org/2020/09/05/a-primer-on-gtklistview/) by Matthias Clasen.
|
||||
|
||||
> Remember that the classname (GtkListItem) in a ui template is used as the “this” pointer referring to the object that is being instantiated.
|
||||
|
||||
|
@ -267,12 +267,8 @@ Closure tag specifies a function and the type of the return value of the functio
|
|||
~~~C
|
||||
const char *
|
||||
get_file_name (GtkListItem *item, GFileInfo *info) {
|
||||
if (! G_IS_FILE_INFO (info))
|
||||
return NULL;
|
||||
else
|
||||
return g_strdup (g_file_info_get_name (info));
|
||||
return G_IS_FILE_INFO (info) ? g_strdup (g_file_info_get_name (info)) : NULL;
|
||||
}
|
||||
|
||||
... ...
|
||||
... ...
|
||||
|
||||
|
@ -291,8 +287,8 @@ get_file_name (GtkListItem *item, GFileInfo *info) {
|
|||
"</interface>"
|
||||
~~~
|
||||
|
||||
- The string "gchararray" is the type name of strings.
|
||||
The type "gchar" is the same as "char".
|
||||
- The string "gchararray" is a type name.
|
||||
The type "gchar" is a type name and it is the same as C type "char".
|
||||
Therefore, "gchararray" is "an array of char type", which is the same as string type.
|
||||
It is used to get the type of GValue object.
|
||||
GValue is a generic value and it can contain various type of values.
|
||||
|
@ -304,13 +300,15 @@ Function attribute specifies the function name and type attribute specifies the
|
|||
The contents of closure tag (it is between \<closure...\> and\</closure\>) is parameters of the function.
|
||||
`<lookup name="item">GtkListItem</lookup>` gives the value of the item property of the GtkListItem.
|
||||
This will be the second argument of the function.
|
||||
The first parameter is always the GListItem instance.
|
||||
- `gtk_file_name` function first checks the `info` parameter.
|
||||
The first parameter is always the GListItem instance, which is a 'this' object.
|
||||
The 'this' object is explained in section 28.
|
||||
- `gtk_file_name` function is the callback function for the closure tag.
|
||||
It first checks the `info` parameter.
|
||||
Because it can be NULL when GListItem `item` is unbounded.
|
||||
If it's GFileInfo, it returns the filename.
|
||||
The filename is owned by GFileInfo object.
|
||||
So, the function `get_file_name` duplicates the string to own the newly created one.
|
||||
Closure tag binds the property of the outer tag (GtkLabel) to the filename.
|
||||
If it's GFileInfo, it returns the copied filename.
|
||||
Because the return value (filename) of `g_file_info_get_name` is owned by GFileInfo object.
|
||||
So, the the string needs to be duplicated to give the ownership to the caller.
|
||||
Binding tag binds the "label" property of the GtkLabel to the closure tag.
|
||||
|
||||
The whole program (`list3.c`) is as follows.
|
||||
The program is located in [src/misc](misc) directory.
|
||||
|
|
|
@ -159,8 +159,7 @@ list4/list4.c get_icon get_file_name
|
|||
@@@
|
||||
|
||||
One important thing is the ownership of the return values.
|
||||
When GtkExpression (closure tag creates a GtkCClosureExpression -- a child class of GtkExpression) is evaluated,
|
||||
the value is owned by the caller.
|
||||
The return value is owned by the caller.
|
||||
So, `g_obect_ref` or `g_strdup` is necessary.
|
||||
|
||||
## An activate signal handler of the button action
|
||||
|
|
Loading…
Reference in a new issue