mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2024-11-16 19:50:35 +01:00
7b14d03a24
Update the distribution package information.
533 lines
49 KiB
HTML
533 lines
49 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="generator" content="pandoc" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
|
||
<title>GTK 4 tutorial</title>
|
||
<style>
|
||
code{white-space: pre-wrap;}
|
||
span.smallcaps{font-variant: small-caps;}
|
||
span.underline{text-decoration: underline;}
|
||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||
ul.task-list{list-style: none;}
|
||
pre{overflow: visible;}
|
||
pre > code.sourceCode { white-space: pre; position: relative; }
|
||
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
||
pre > code.sourceCode > span:empty { height: 1.2em; }
|
||
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
||
div.sourceCode { margin: 1em 0; }
|
||
pre.sourceCode { margin: 0; }
|
||
@media screen {
|
||
div.sourceCode { overflow: auto; }
|
||
}
|
||
@media print {
|
||
pre > code.sourceCode { white-space: pre-wrap; }
|
||
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
||
}
|
||
pre.numberSource code
|
||
{ counter-reset: source-line 0; }
|
||
pre.numberSource code > span
|
||
{ position: relative; left: -4em; counter-increment: source-line; }
|
||
pre.numberSource code > span > a:first-child::after
|
||
{ content: counter(source-line);
|
||
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
||
border: none; display: inline-block;
|
||
-webkit-touch-callout: none; -webkit-user-select: none;
|
||
-khtml-user-select: none; -moz-user-select: none;
|
||
-ms-user-select: none; user-select: none;
|
||
padding: 0 4px; width: 4em;
|
||
color: #aaaaaa;
|
||
}
|
||
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
|
||
div.sourceCode
|
||
{ }
|
||
@media screen {
|
||
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
||
}
|
||
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
|
||
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
||
code span.at { color: #7d9029; } /* Attribute */
|
||
code span.bn { color: #40a070; } /* BaseN */
|
||
code span.bu { } /* BuiltIn */
|
||
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
|
||
code span.ch { color: #4070a0; } /* Char */
|
||
code span.cn { color: #880000; } /* Constant */
|
||
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
|
||
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
||
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
||
code span.dt { color: #902000; } /* DataType */
|
||
code span.dv { color: #40a070; } /* DecVal */
|
||
code span.er { color: #ff0000; font-weight: bold; } /* Error */
|
||
code span.ex { } /* Extension */
|
||
code span.fl { color: #40a070; } /* Float */
|
||
code span.fu { color: #06287e; } /* Function */
|
||
code span.im { } /* Import */
|
||
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
||
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
|
||
code span.op { color: #666666; } /* Operator */
|
||
code span.ot { color: #007020; } /* Other */
|
||
code span.pp { color: #bc7a00; } /* Preprocessor */
|
||
code span.sc { color: #4070a0; } /* SpecialChar */
|
||
code span.ss { color: #bb6688; } /* SpecialString */
|
||
code span.st { color: #4070a0; } /* String */
|
||
code span.va { color: #19177c; } /* Variable */
|
||
code span.vs { color: #4070a0; } /* VerbatimString */
|
||
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||
div.sourceCode { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
|
||
pre:not(.sourceCode) { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
|
||
table {margin-left: auto; margin-right: auto; border-collapse: collapse; border: 1px solid;}
|
||
th {padding: 2px 6px; border: 1px solid; background-color: ghostwhite;}
|
||
td {padding: 2px 6px; border: 1px solid;}
|
||
img {display: block; margin-left: auto; margin-right: auto;}
|
||
figcaption {text-align: center;}
|
||
</style>
|
||
</head>
|
||
<body style="padding-top: 70px;">
|
||
<div class="container">
|
||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
|
||
<div class="container-fluid">
|
||
<span class="navbar-brand">Gtk4 tutorial</span>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="index.html">Home</a>
|
||
</li>
|
||
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="sec17.html">Prev: section17</a>
|
||
</li>
|
||
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="sec19.html">Next: section19</a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
<div class="row justify-content-center">
|
||
<div class="col-xl-10 col-xxl-9">
|
||
<h1 id="stateful-action">Stateful action</h1>
|
||
<p>Some actions have states. The typical values of states are boolean or
|
||
string. However, other types of states are possible if you want.</p>
|
||
<p>Actions which have states are called stateful.</p>
|
||
<h2 id="stateful-action-without-a-parameter">Stateful action without a
|
||
parameter</h2>
|
||
<p>Some menus are called toggle menu. For example, fullscreen menu has a
|
||
state which has two values – fullscreen and non-fullscreen. The value of
|
||
the state is changed every time the menu is clicked. An action
|
||
corresponds to the fullscreen menu also have a state. Its value is TRUE
|
||
or FALSE and it is called boolean value. TRUE corresponds to fullscreen
|
||
and FALSE to non-fullscreen.</p>
|
||
<p>The following is an example code to implement a fullscreen menu
|
||
except the signal handler. The signal handler will be shown later.</p>
|
||
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>GSimpleAction <span class="op">*</span>act_fullscreen <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">"fullscreen"</span><span class="op">,</span></span>
|
||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> NULL<span class="op">,</span> g_variant_new_boolean <span class="op">(</span>FALSE<span class="op">));</span></span>
|
||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>g_signal_connect <span class="op">(</span>act_fullscreen<span class="op">,</span> <span class="st">"change-state"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>fullscreen_changed<span class="op">),</span> win<span class="op">);</span></span>
|
||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>win<span class="op">),</span> G_ACTION <span class="op">(</span>act_fullscreen<span class="op">));</span></span>
|
||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span>
|
||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>GMenuItem <span class="op">*</span>menu_item_fullscreen <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Full Screen"</span><span class="op">,</span> <span class="st">"win.fullscreen"</span><span class="op">);</span></span></code></pre></div>
|
||
<ul>
|
||
<li><code>act_fullscreen</code> is a GSimpleAction instance. It is
|
||
created with <code>g_simple_action_new_stateful</code>. The function has
|
||
three arguments. The first argument “fullscreen” is the name of the
|
||
action. The second argument is a parameter type. <code>NULL</code> means
|
||
the action doesn’t have a parameter. The third argument is the initial
|
||
state of the action. It is a GVariant value. GVariant will be explained
|
||
in the next subsection. The function
|
||
<code>g_variant_new_boolean (FALSE)</code> returns a boolean type
|
||
GVariant value which is <code>FALSE</code>. If there are two or more top
|
||
level windows, each window has its own <code>act_fullscreen</code>
|
||
action. So, the number of the actions is the same as the number of the
|
||
windows.</li>
|
||
<li>The action <code>act_fullscreen</code> has “change-state” signal.
|
||
The signal is connected to a handler <code>fullscreen_changed</code>. If
|
||
the fullscreen menu is clicked, then the corresponding action
|
||
<code>act_fullscreen</code> is activated. But no handler is connected to
|
||
the “activate” signal. Then, the default behavior for boolean-stated
|
||
actions with a NULL parameter type like <code>act_fullscreen</code> is
|
||
to toggle them via the “change-state” signal.</li>
|
||
<li>The action is added to the GtkWindow <code>win</code>. Therefore,
|
||
the scope of the action is “win”.</li>
|
||
<li><code>menu_item_fullscreen</code> is a GMenuItem instance. There are
|
||
two arguments. The first argument “Full Screen” is the label of
|
||
<code>menu_item_fullscreen</code>. The second argument is an action. The
|
||
action “win.fullscreen” has a prefix “win” and an action name
|
||
“fullscreen”. The prefix says that the action belongs to the
|
||
window.</li>
|
||
</ul>
|
||
<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>fullscreen_changed<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>value<span class="op">,</span> GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb2-3"><a href="#cb2-3"></a> <span class="cf">if</span> <span class="op">(</span>g_variant_get_boolean <span class="op">(</span>value<span class="op">))</span></span>
|
||
<span id="cb2-4"><a href="#cb2-4"></a> gtk_window_maximize <span class="op">(</span>win<span class="op">);</span></span>
|
||
<span id="cb2-5"><a href="#cb2-5"></a> <span class="cf">else</span></span>
|
||
<span id="cb2-6"><a href="#cb2-6"></a> gtk_window_unmaximize <span class="op">(</span>win<span class="op">);</span></span>
|
||
<span id="cb2-7"><a href="#cb2-7"></a> g_simple_action_set_state <span class="op">(</span>action<span class="op">,</span> value<span class="op">);</span></span>
|
||
<span id="cb2-8"><a href="#cb2-8"></a><span class="op">}</span></span></code></pre></div>
|
||
<ul>
|
||
<li>The handler <code>fullscreen_changed</code> has three parameters.
|
||
The first parameter is the action which emits the “change-state” signal.
|
||
The second parameter is the value of the new state of the action. The
|
||
third parameter is a user data which is set in
|
||
<code>g_signal_connect</code>.</li>
|
||
<li>If the value is boolean type and <code>TRUE</code>, then it
|
||
maximizes the window. Otherwise it un-maximizes.</li>
|
||
<li>Sets the state of the action with <code>value</code>. Note: At this
|
||
stage, that means the stage before
|
||
<code>g_simple_action_set_state</code> is called, the state of the
|
||
action still has the original value. So, you need to set the state with
|
||
the new value by <code>g_simple_action_set_state</code>.</li>
|
||
</ul>
|
||
<p>You can use “activate” signal instead of “change-state” signal, or
|
||
both signals. But the way above is the simplest and the best.</p>
|
||
<h3 id="gvariant">GVariant</h3>
|
||
<p>GVariant is a fundamental type. It isn’t a child of GObject. GVariant
|
||
can contain boolean, string or other type values. For example, the
|
||
following program assigns TRUE to <code>value</code> whose type is
|
||
GVariant.</p>
|
||
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>GVariant <span class="op">*</span>value <span class="op">=</span> g_variant_new_boolean <span class="op">(</span>TRUE<span class="op">);</span></span></code></pre></div>
|
||
<p>Another example is:</p>
|
||
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>GVariant <span class="op">*</span>value2 <span class="op">=</span> g_variant_new_string <span class="op">(</span><span class="st">"Hello"</span><span class="op">);</span></span></code></pre></div>
|
||
<p><code>value2</code> is a GVariant and it has a string type value
|
||
“Hello”. GVariant can contain other types like int16, int32, int64,
|
||
double and so on.</p>
|
||
<p>If you want to get the original value, use g_variant_get series
|
||
functions. For example, you can get the boolean value with
|
||
g_variant_get_boolean.</p>
|
||
<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>gboolean <span class="dt">bool</span> <span class="op">=</span> g_variant_get_boolean <span class="op">(</span>value<span class="op">);</span></span></code></pre></div>
|
||
<p>Since <code>value</code> has been created as a boolean type GVariant
|
||
with <code>TRUE</code> value, <code>bool</code> equals
|
||
<code>TRUE</code>. In the same way, you can get a string from
|
||
<code>value2</code></p>
|
||
<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>str <span class="op">=</span> g_variant_get_string <span class="op">(</span>value2<span class="op">,</span> NULL<span class="op">);</span></span></code></pre></div>
|
||
<p>The second parameter is a pointer to gsize type variable (gsize is
|
||
defined as unsigned long). If it isn’t NULL, then the pointed value is
|
||
used as the length by the function. If it is NULL, nothing happens. The
|
||
returned string <code>str</code> is owned by the instance and can’t be
|
||
changed or freed by the caller.</p>
|
||
<h2 id="stateful-action-with-a-parameter">Stateful action with a
|
||
parameter</h2>
|
||
<p>Another example of stateful actions is an action corresponds to color
|
||
select menus. For example, there are three menus and each menu has red,
|
||
green or blue color respectively. They determine the background color of
|
||
a GtkLabel widget. One action is connected to the three menus. The
|
||
action has a state whose value is “red”, “green” or “blue”. The values
|
||
are string. Those colors are given to the signal handler as a
|
||
parameter.</p>
|
||
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span>
|
||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>GVariantType <span class="op">*</span>vtype <span class="op">=</span> g_variant_type_new<span class="op">(</span><span class="st">"s"</span><span class="op">);</span></span>
|
||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>GSimpleAction <span class="op">*</span>act_color</span>
|
||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">"color"</span><span class="op">,</span> vtype<span class="op">,</span> g_variant_new_string <span class="op">(</span><span class="st">"red"</span><span class="op">));</span></span>
|
||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>g_variant_type_free <span class="op">(</span>vtype<span class="op">);</span></span>
|
||
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>GMenuItem <span class="op">*</span>menu_item_red <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Red"</span><span class="op">,</span> <span class="st">"app.color::red"</span><span class="op">);</span></span>
|
||
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>GMenuItem <span class="op">*</span>menu_item_green <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Green"</span><span class="op">,</span> <span class="st">"app.color::green"</span><span class="op">);</span></span>
|
||
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>GMenuItem <span class="op">*</span>menu_item_blue <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Blue"</span><span class="op">,</span> <span class="st">"app.color::blue"</span><span class="op">);</span></span>
|
||
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>g_signal_connect <span class="op">(</span>act_color<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>color_activated<span class="op">),</span> NULL<span class="op">);</span></span>
|
||
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span></code></pre></div>
|
||
<ul>
|
||
<li>GVariantType is a C structure and it keeps a type of GVariant. It is
|
||
created with the function <code>g_variant_type_new</code>. The argument
|
||
of the function is a GVariant type string. So,
|
||
<code>g_variant_type_new("s")</code> returns a GVariantType structure
|
||
contains a string type. The returned value, GVariantType structure, is
|
||
owned by the caller. So, you need to free it when it becomes
|
||
useless.</li>
|
||
<li>The variable <code>act_color</code> points a GSimpleAction instance.
|
||
It is created with <code>g_simple_action_new_stateful</code>. The
|
||
function has three arguments. The first argument “color” is the name of
|
||
the action. The second argument is a parameter type which is
|
||
GVariantType. <code>g_variant_type_new("s")</code> creates GVariantType
|
||
which is a string type (<code>G_VARIANT_TYPE_STRING</code>). The third
|
||
argument is the initial state of the action. It is a GVariant. The
|
||
function <code>g_variant_new_string ("red")</code> returns a GVariant
|
||
value which has the string value “red”. GVariant has a reference count
|
||
and <code>g_variant_new_...</code> series functions returns a GVariant
|
||
value with a floating reference. That means the caller doesn’t own the
|
||
value at this point. And <code>g_simple_action_new_stateful</code>
|
||
function consumes the floating reference so you don’t need to care about
|
||
releasing the GVariant instance.</li>
|
||
<li>The GVariantType structure <code>vtype</code> is useless after
|
||
<code>g_simple_action_new_stateful</code>. It is released with the
|
||
function <code>g_variant_type_free</code>.</li>
|
||
<li>The varable <code>menu_item_red</code> points a GMenuItem instance.
|
||
The function <code>g_menu_item_new</code> has two arguments. The first
|
||
argument “Red” is the label of <code>menu_item_red</code>. The second
|
||
argument is a detailed action. Its prefix is “app”, action name is
|
||
“color” and target is “red”. Target is sent to the action as a
|
||
parameter. The same goes for <code>menu_item_green</code> and
|
||
<code>menu_item_blue</code>.</li>
|
||
<li>The function <code>g_signal_connect</code> connects the activate
|
||
signal on the action <code>act_color</code> and the handler
|
||
<code>color_activated</code>. If one of the three menus is clicked, then
|
||
the action <code>act_color</code> is activated with the target
|
||
(parameter) which is given by the menu.</li>
|
||
</ul>
|
||
<p>The following is the “activate” signal handler.</p>
|
||
<div class="sourceCode" id="cb8"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>color_activated<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">char</span> <span class="op">*</span>color <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">"label.lb {background-color: %s;}"</span><span class="op">,</span></span>
|
||
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> g_variant_get_string <span class="op">(</span>parameter<span class="op">,</span> NULL<span class="op">));</span></span>
|
||
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> color<span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
||
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a> g_free <span class="op">(</span>color<span class="op">);</span></span>
|
||
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a> g_action_change_state <span class="op">(</span>G_ACTION <span class="op">(</span>action<span class="op">),</span> parameter<span class="op">);</span></span>
|
||
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||
<ul>
|
||
<li>The handler originally has three parameters. The third parameter is
|
||
a user data set in the <code>g_signal_connect</code> function. But it is
|
||
left out because the fourth argument of the
|
||
<code>g_signal_connect</code> has been NULL. The first parameter is the
|
||
action which emits the “activate” signal. The second parameter is the
|
||
parameter, or target, given to the action. It is a color specified by
|
||
the menu.</li>
|
||
<li>The variable <code>color</code> is a CSS string created by
|
||
<code>g_strdup_printf</code>. The arguments of
|
||
<code>g_strdup_printf</code> are the same as printf C standard function.
|
||
The function <code>g_variant_get_string</code> gets the string contained
|
||
in <code>parameter</code>. The string is owned by the instance and you
|
||
mustn’t change or free it. The string <code>label.lb</code> is a
|
||
selector. It consists of <code>label</code>, a node name of GtkLabel,
|
||
and <code>lb</code> which is a class name. It selects GtkLabel which has
|
||
<code>lb</code> class. For example, menus have GtkLabel to display their
|
||
labels, but they don’t have <code>lb</code> class. So, the CSS doesn’t
|
||
change their background color. The string
|
||
<code>{background-color %s}</code> makes the background color
|
||
<code>%s</code> to which the color from <code>parameter</code> is
|
||
assigned.</li>
|
||
<li>Frees the string <code>color</code>.</li>
|
||
<li>Changes the state with <code>g_action_change_state</code>.</li>
|
||
</ul>
|
||
<p>Note: If you haven’t set an “activate” signal handler, the signal is
|
||
forwarded to “change-state” signal. So, you can use “change-state”
|
||
signal instead of “activate” signal. See
|
||
<code>src/menu/menu2_change_state.c</code>.</p>
|
||
<h3 id="gvarianttype">GVariantType</h3>
|
||
<p>GVariantType gives a type of GVariant. GVariantType is created with a
|
||
type string.</p>
|
||
<ul>
|
||
<li>“b” means boolean type.</li>
|
||
<li>“s” means string type.</li>
|
||
</ul>
|
||
<p>The following program is a simple example. It finally outputs the
|
||
string “s”.</p>
|
||
<div class="sourceCode" id="cb9"><pre
|
||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1"></a><span class="pp">#include </span><span class="im"><glib.h></span></span>
|
||
<span id="cb9-2"><a href="#cb9-2"></a></span>
|
||
<span id="cb9-3"><a href="#cb9-3"></a><span class="dt">int</span></span>
|
||
<span id="cb9-4"><a href="#cb9-4"></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="cb9-5"><a href="#cb9-5"></a> GVariantType <span class="op">*</span>vtype <span class="op">=</span> g_variant_type_new <span class="op">(</span><span class="st">"s"</span><span class="op">);</span></span>
|
||
<span id="cb9-6"><a href="#cb9-6"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>type_string <span class="op">=</span> g_variant_type_peek_string <span class="op">(</span>vtype<span class="op">);</span></span>
|
||
<span id="cb9-7"><a href="#cb9-7"></a> g_print <span class="op">(</span><span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span>type_string<span class="op">);</span></span>
|
||
<span id="cb9-8"><a href="#cb9-8"></a> g_variant_type_free <span class="op">(</span>vtype<span class="op">);</span></span>
|
||
<span id="cb9-9"><a href="#cb9-9"></a><span class="op">}</span></span></code></pre></div>
|
||
<ul>
|
||
<li>The function <code>g_variant_type_new</code> creates a GVariantType
|
||
structure. The argument “s” is a type string. It means string. The
|
||
returned structure is owned by the caller. When it becomes useless, you
|
||
need to free it with the function <code>g_variant_type_free</code>.</li>
|
||
<li>The function <code>g_variant_type_peek_string</code> takes a peek at
|
||
<code>vtype</code>. It is the string “s” given to <code>vtype</code>
|
||
when it was created. The string is owned by the instance and the caller
|
||
can’t change or free it.</li>
|
||
<li>Prints the string to the terminal. You can’t free <code>vtype</code>
|
||
before <code>g_print</code> because the string <code>type_string</code>
|
||
is owned by <code>vtype</code>.</li>
|
||
<li>Frees <code>vtype</code>.</li>
|
||
</ul>
|
||
<h2 id="example">Example</h2>
|
||
<p>The following code includes stateful actions above. This program has
|
||
menus like this:</p>
|
||
<figure>
|
||
<img src="image/menu2.png" alt="menu2" />
|
||
<figcaption aria-hidden="true">menu2</figcaption>
|
||
</figure>
|
||
<ul>
|
||
<li>Fullscreen menu toggles the size of the window between maximum and
|
||
non-maximum. If the window is maximum size, which is called full screen,
|
||
then a check mark is put before “fullscreen” label.</li>
|
||
<li>Red, green and blue menu determines the back ground color of the
|
||
label in the window. The menus have radio buttons on the left of the
|
||
menus. And the radio button of the selected menu turns on.</li>
|
||
<li>Quit menu quits the application.</li>
|
||
</ul>
|
||
<p>The code is as follows.</p>
|
||
<div class="sourceCode" id="cb10"><pre
|
||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||
<span id="cb10-2"><a href="#cb10-2"></a></span>
|
||
<span id="cb10-3"><a href="#cb10-3"></a><span class="co">/* The provider below provides application wide CSS data. */</span></span>
|
||
<span id="cb10-4"><a href="#cb10-4"></a>GtkCssProvider <span class="op">*</span>provider<span class="op">;</span></span>
|
||
<span id="cb10-5"><a href="#cb10-5"></a></span>
|
||
<span id="cb10-6"><a href="#cb10-6"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb10-7"><a href="#cb10-7"></a>fullscreen_changed<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>value<span class="op">,</span> GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb10-8"><a href="#cb10-8"></a> <span class="cf">if</span> <span class="op">(</span>g_variant_get_boolean <span class="op">(</span>value<span class="op">))</span></span>
|
||
<span id="cb10-9"><a href="#cb10-9"></a> gtk_window_maximize <span class="op">(</span>win<span class="op">);</span></span>
|
||
<span id="cb10-10"><a href="#cb10-10"></a> <span class="cf">else</span></span>
|
||
<span id="cb10-11"><a href="#cb10-11"></a> gtk_window_unmaximize <span class="op">(</span>win<span class="op">);</span></span>
|
||
<span id="cb10-12"><a href="#cb10-12"></a> g_simple_action_set_state <span class="op">(</span>action<span class="op">,</span> value<span class="op">);</span></span>
|
||
<span id="cb10-13"><a href="#cb10-13"></a><span class="op">}</span></span>
|
||
<span id="cb10-14"><a href="#cb10-14"></a></span>
|
||
<span id="cb10-15"><a href="#cb10-15"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb10-16"><a href="#cb10-16"></a>color_activated<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb10-17"><a href="#cb10-17"></a> <span class="dt">char</span> <span class="op">*</span>color <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">"label.lb {background-color: %s;}"</span><span class="op">,</span> g_variant_get_string <span class="op">(</span>parameter<span class="op">,</span> NULL<span class="op">));</span></span>
|
||
<span id="cb10-18"><a href="#cb10-18"></a> <span class="co">/* Change the CSS data in the provider. */</span></span>
|
||
<span id="cb10-19"><a href="#cb10-19"></a> <span class="co">/* Previous data is thrown away. */</span></span>
|
||
<span id="cb10-20"><a href="#cb10-20"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> color<span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
||
<span id="cb10-21"><a href="#cb10-21"></a> g_free <span class="op">(</span>color<span class="op">);</span></span>
|
||
<span id="cb10-22"><a href="#cb10-22"></a> g_action_change_state <span class="op">(</span>G_ACTION <span class="op">(</span>action<span class="op">),</span> parameter<span class="op">);</span></span>
|
||
<span id="cb10-23"><a href="#cb10-23"></a><span class="op">}</span></span>
|
||
<span id="cb10-24"><a href="#cb10-24"></a></span>
|
||
<span id="cb10-25"><a href="#cb10-25"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb10-26"><a href="#cb10-26"></a>app_shutdown <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">,</span> GtkCssProvider <span class="op">*</span>provider<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb10-27"><a href="#cb10-27"></a> gtk_style_context_remove_provider_for_display <span class="op">(</span>gdk_display_get_default<span class="op">(),</span> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">));</span></span>
|
||
<span id="cb10-28"><a href="#cb10-28"></a><span class="op">}</span></span>
|
||
<span id="cb10-29"><a href="#cb10-29"></a></span>
|
||
<span id="cb10-30"><a href="#cb10-30"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb10-31"><a href="#cb10-31"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb10-32"><a href="#cb10-32"></a> GtkWindow <span class="op">*</span>win <span class="op">=</span> GTK_WINDOW <span class="op">(</span>gtk_application_window_new <span class="op">(</span>GTK_APPLICATION <span class="op">(</span>app<span class="op">)));</span></span>
|
||
<span id="cb10-33"><a href="#cb10-33"></a> gtk_window_set_title <span class="op">(</span>win<span class="op">,</span> <span class="st">"menu2"</span><span class="op">);</span></span>
|
||
<span id="cb10-34"><a href="#cb10-34"></a> gtk_window_set_default_size <span class="op">(</span>win<span class="op">,</span> <span class="dv">400</span><span class="op">,</span> <span class="dv">300</span><span class="op">);</span></span>
|
||
<span id="cb10-35"><a href="#cb10-35"></a></span>
|
||
<span id="cb10-36"><a href="#cb10-36"></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="cb10-37"><a href="#cb10-37"></a> gtk_widget_add_css_class <span class="op">(</span>lb<span class="op">,</span> <span class="st">"lb"</span><span class="op">);</span> <span class="co">/* the class is used by CSS Selector */</span></span>
|
||
<span id="cb10-38"><a href="#cb10-38"></a> gtk_window_set_child <span class="op">(</span>win<span class="op">,</span> lb<span class="op">);</span></span>
|
||
<span id="cb10-39"><a href="#cb10-39"></a></span>
|
||
<span id="cb10-40"><a href="#cb10-40"></a> GSimpleAction <span class="op">*</span>act_fullscreen</span>
|
||
<span id="cb10-41"><a href="#cb10-41"></a> <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">"fullscreen"</span><span class="op">,</span> NULL<span class="op">,</span> g_variant_new_boolean <span class="op">(</span>FALSE<span class="op">));</span></span>
|
||
<span id="cb10-42"><a href="#cb10-42"></a> g_signal_connect <span class="op">(</span>act_fullscreen<span class="op">,</span> <span class="st">"change-state"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>fullscreen_changed<span class="op">),</span> win<span class="op">);</span></span>
|
||
<span id="cb10-43"><a href="#cb10-43"></a> g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>win<span class="op">),</span> G_ACTION <span class="op">(</span>act_fullscreen<span class="op">));</span></span>
|
||
<span id="cb10-44"><a href="#cb10-44"></a></span>
|
||
<span id="cb10-45"><a href="#cb10-45"></a> gtk_application_window_set_show_menubar <span class="op">(</span>GTK_APPLICATION_WINDOW <span class="op">(</span>win<span class="op">),</span> TRUE<span class="op">);</span></span>
|
||
<span id="cb10-46"><a href="#cb10-46"></a></span>
|
||
<span id="cb10-47"><a href="#cb10-47"></a> gtk_window_present <span class="op">(</span>win<span class="op">);</span></span>
|
||
<span id="cb10-48"><a href="#cb10-48"></a><span class="op">}</span></span>
|
||
<span id="cb10-49"><a href="#cb10-49"></a></span>
|
||
<span id="cb10-50"><a href="#cb10-50"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb10-51"><a href="#cb10-51"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb10-52"><a href="#cb10-52"></a> GVariantType <span class="op">*</span>vtype <span class="op">=</span> g_variant_type_new<span class="op">(</span><span class="st">"s"</span><span class="op">);</span></span>
|
||
<span id="cb10-53"><a href="#cb10-53"></a> GSimpleAction <span class="op">*</span>act_color</span>
|
||
<span id="cb10-54"><a href="#cb10-54"></a> <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">"color"</span><span class="op">,</span> vtype<span class="op">,</span> g_variant_new_string <span class="op">(</span><span class="st">"red"</span><span class="op">));</span></span>
|
||
<span id="cb10-55"><a href="#cb10-55"></a> g_variant_type_free <span class="op">(</span>vtype<span class="op">);</span></span>
|
||
<span id="cb10-56"><a href="#cb10-56"></a> GSimpleAction <span class="op">*</span>act_quit</span>
|
||
<span id="cb10-57"><a href="#cb10-57"></a> <span class="op">=</span> g_simple_action_new <span class="op">(</span><span class="st">"quit"</span><span class="op">,</span> NULL<span class="op">);</span></span>
|
||
<span id="cb10-58"><a href="#cb10-58"></a> g_signal_connect <span class="op">(</span>act_color<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>color_activated<span class="op">),</span> NULL<span class="op">);</span></span>
|
||
<span id="cb10-59"><a href="#cb10-59"></a> g_signal_connect_swapped <span class="op">(</span>act_quit<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>g_application_quit<span class="op">),</span> app<span class="op">);</span></span>
|
||
<span id="cb10-60"><a href="#cb10-60"></a> g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>app<span class="op">),</span> G_ACTION <span class="op">(</span>act_color<span class="op">));</span></span>
|
||
<span id="cb10-61"><a href="#cb10-61"></a> g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>app<span class="op">),</span> G_ACTION <span class="op">(</span>act_quit<span class="op">));</span></span>
|
||
<span id="cb10-62"><a href="#cb10-62"></a></span>
|
||
<span id="cb10-63"><a href="#cb10-63"></a> GMenu <span class="op">*</span>menubar <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||
<span id="cb10-64"><a href="#cb10-64"></a> GMenu <span class="op">*</span>menu <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||
<span id="cb10-65"><a href="#cb10-65"></a> GMenu <span class="op">*</span>section1 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||
<span id="cb10-66"><a href="#cb10-66"></a> GMenu <span class="op">*</span>section2 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||
<span id="cb10-67"><a href="#cb10-67"></a> GMenu <span class="op">*</span>section3 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||
<span id="cb10-68"><a href="#cb10-68"></a> GMenuItem <span class="op">*</span>menu_item_fullscreen <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Full Screen"</span><span class="op">,</span> <span class="st">"win.fullscreen"</span><span class="op">);</span></span>
|
||
<span id="cb10-69"><a href="#cb10-69"></a> GMenuItem <span class="op">*</span>menu_item_red <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Red"</span><span class="op">,</span> <span class="st">"app.color::red"</span><span class="op">);</span></span>
|
||
<span id="cb10-70"><a href="#cb10-70"></a> GMenuItem <span class="op">*</span>menu_item_green <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Green"</span><span class="op">,</span> <span class="st">"app.color::green"</span><span class="op">);</span></span>
|
||
<span id="cb10-71"><a href="#cb10-71"></a> GMenuItem <span class="op">*</span>menu_item_blue <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Blue"</span><span class="op">,</span> <span class="st">"app.color::blue"</span><span class="op">);</span></span>
|
||
<span id="cb10-72"><a href="#cb10-72"></a> GMenuItem <span class="op">*</span>menu_item_quit <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">"Quit"</span><span class="op">,</span> <span class="st">"app.quit"</span><span class="op">);</span></span>
|
||
<span id="cb10-73"><a href="#cb10-73"></a></span>
|
||
<span id="cb10-74"><a href="#cb10-74"></a> g_menu_append_item <span class="op">(</span>section1<span class="op">,</span> menu_item_fullscreen<span class="op">);</span></span>
|
||
<span id="cb10-75"><a href="#cb10-75"></a> g_menu_append_item <span class="op">(</span>section2<span class="op">,</span> menu_item_red<span class="op">);</span></span>
|
||
<span id="cb10-76"><a href="#cb10-76"></a> g_menu_append_item <span class="op">(</span>section2<span class="op">,</span> menu_item_green<span class="op">);</span></span>
|
||
<span id="cb10-77"><a href="#cb10-77"></a> g_menu_append_item <span class="op">(</span>section2<span class="op">,</span> menu_item_blue<span class="op">);</span></span>
|
||
<span id="cb10-78"><a href="#cb10-78"></a> g_menu_append_item <span class="op">(</span>section3<span class="op">,</span> menu_item_quit<span class="op">);</span></span>
|
||
<span id="cb10-79"><a href="#cb10-79"></a> g_object_unref <span class="op">(</span>menu_item_red<span class="op">);</span></span>
|
||
<span id="cb10-80"><a href="#cb10-80"></a> g_object_unref <span class="op">(</span>menu_item_green<span class="op">);</span></span>
|
||
<span id="cb10-81"><a href="#cb10-81"></a> g_object_unref <span class="op">(</span>menu_item_blue<span class="op">);</span></span>
|
||
<span id="cb10-82"><a href="#cb10-82"></a> g_object_unref <span class="op">(</span>menu_item_fullscreen<span class="op">);</span></span>
|
||
<span id="cb10-83"><a href="#cb10-83"></a> g_object_unref <span class="op">(</span>menu_item_quit<span class="op">);</span></span>
|
||
<span id="cb10-84"><a href="#cb10-84"></a></span>
|
||
<span id="cb10-85"><a href="#cb10-85"></a> g_menu_append_section <span class="op">(</span>menu<span class="op">,</span> NULL<span class="op">,</span> G_MENU_MODEL <span class="op">(</span>section1<span class="op">));</span></span>
|
||
<span id="cb10-86"><a href="#cb10-86"></a> g_menu_append_section <span class="op">(</span>menu<span class="op">,</span> <span class="st">"Color"</span><span class="op">,</span> G_MENU_MODEL <span class="op">(</span>section2<span class="op">));</span></span>
|
||
<span id="cb10-87"><a href="#cb10-87"></a> g_menu_append_section <span class="op">(</span>menu<span class="op">,</span> NULL<span class="op">,</span> G_MENU_MODEL <span class="op">(</span>section3<span class="op">));</span></span>
|
||
<span id="cb10-88"><a href="#cb10-88"></a> g_menu_append_submenu <span class="op">(</span>menubar<span class="op">,</span> <span class="st">"Menu"</span><span class="op">,</span> G_MENU_MODEL <span class="op">(</span>menu<span class="op">));</span></span>
|
||
<span id="cb10-89"><a href="#cb10-89"></a> g_object_unref <span class="op">(</span>section1<span class="op">);</span></span>
|
||
<span id="cb10-90"><a href="#cb10-90"></a> g_object_unref <span class="op">(</span>section2<span class="op">);</span></span>
|
||
<span id="cb10-91"><a href="#cb10-91"></a> g_object_unref <span class="op">(</span>section3<span class="op">);</span></span>
|
||
<span id="cb10-92"><a href="#cb10-92"></a> g_object_unref <span class="op">(</span>menu<span class="op">);</span></span>
|
||
<span id="cb10-93"><a href="#cb10-93"></a></span>
|
||
<span id="cb10-94"><a href="#cb10-94"></a> gtk_application_set_menubar <span class="op">(</span>GTK_APPLICATION <span class="op">(</span>app<span class="op">),</span> G_MENU_MODEL <span class="op">(</span>menubar<span class="op">));</span></span>
|
||
<span id="cb10-95"><a href="#cb10-95"></a></span>
|
||
<span id="cb10-96"><a href="#cb10-96"></a> provider <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span>
|
||
<span id="cb10-97"><a href="#cb10-97"></a> <span class="co">/* Initialize the css data */</span></span>
|
||
<span id="cb10-98"><a href="#cb10-98"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> <span class="st">"label.lb {background-color: red;}"</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
||
<span id="cb10-99"><a href="#cb10-99"></a> <span class="co">/* Add CSS to the default GdkDisplay. */</span></span>
|
||
<span id="cb10-100"><a href="#cb10-100"></a> gtk_style_context_add_provider_for_display <span class="op">(</span>gdk_display_get_default <span class="op">(),</span></span>
|
||
<span id="cb10-101"><a href="#cb10-101"></a> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">),</span> GTK_STYLE_PROVIDER_PRIORITY_APPLICATION<span class="op">);</span></span>
|
||
<span id="cb10-102"><a href="#cb10-102"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"shutdown"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_shutdown<span class="op">),</span> provider<span class="op">);</span></span>
|
||
<span id="cb10-103"><a href="#cb10-103"></a> g_object_unref <span class="op">(</span>provider<span class="op">);</span> <span class="co">/* release provider, but it's still alive because the display owns it */</span></span>
|
||
<span id="cb10-104"><a href="#cb10-104"></a><span class="op">}</span></span>
|
||
<span id="cb10-105"><a href="#cb10-105"></a></span>
|
||
<span id="cb10-106"><a href="#cb10-106"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.menu2"</span></span>
|
||
<span id="cb10-107"><a href="#cb10-107"></a></span>
|
||
<span id="cb10-108"><a href="#cb10-108"></a><span class="dt">int</span></span>
|
||
<span id="cb10-109"><a href="#cb10-109"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb10-110"><a href="#cb10-110"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||
<span id="cb10-111"><a href="#cb10-111"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||
<span id="cb10-112"><a href="#cb10-112"></a></span>
|
||
<span id="cb10-113"><a href="#cb10-113"></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="cb10-114"><a href="#cb10-114"></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="cb10-115"><a href="#cb10-115"></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="cb10-116"><a href="#cb10-116"></a></span>
|
||
<span id="cb10-117"><a href="#cb10-117"></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="cb10-118"><a href="#cb10-118"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||
<span id="cb10-119"><a href="#cb10-119"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||
<span id="cb10-120"><a href="#cb10-120"></a><span class="op">}</span></span></code></pre></div>
|
||
<ul>
|
||
<li>6-23: Action signal handlers.</li>
|
||
<li>25-28: The handler <code>app_shutdown</code> is called when the
|
||
application quits. It removes the provider from the display.</li>
|
||
<li>30-48: An activate signal handler.</li>
|
||
<li>32-34: A new window is created and assigned to <code>win</code>. Its
|
||
title and default size are set to “menu2” and 400x300 respectively.</li>
|
||
<li>36-38: A new label is created and assigned to <code>lb</code> The
|
||
label is given a CSS class “lb”. It is added to <code>win</code> as a
|
||
child.</li>
|
||
<li>40-43: A toggle action is created and assigned to
|
||
<code>act_fullscreen</code>. It’s connected to the signal handler
|
||
<code>fullscreen_changed</code>. It’s added to the window, so the action
|
||
scope is “win”. So, if there are two or more windows, the actions are
|
||
created two or more.</li>
|
||
<li>45: The function
|
||
<code>gtk_application_window_set_show_menubar</code> adds a menubar to
|
||
the window.</li>
|
||
<li>47: Shows the window.</li>
|
||
<li>50-104: A startup signal handler.</li>
|
||
<li>52-61: Two actions <code>act_color</code> and <code>act_quit</code>
|
||
are created. These actions exists only one because the startup handler
|
||
is called once. They are connected to their handlers and added to the
|
||
application. Their scopes are “app”.</li>
|
||
<li>63-92: Menus are built.</li>
|
||
<li>94: The menubar is added to the application.</li>
|
||
<li>96-103: A CSS provider is created with the CSS data and added to the
|
||
default display. The “shutdown” signal on the application is connected
|
||
to a handler “app_shutdown”. So, the provider is removed from the
|
||
display and freed when the application quits.</li>
|
||
</ul>
|
||
<h2 id="compile">Compile</h2>
|
||
<p>Change your current directory to <code>src/menu</code>.</p>
|
||
<pre><code>$ comp menu2
|
||
$./a.out</code></pre>
|
||
<p>Then, you will see a window and the background color of the content
|
||
is red. You can change the size to maximum and change back to the
|
||
original size. You can change the background color to green or blue.</p>
|
||
<p>If you run the second application during the first application is
|
||
running, another window will appear in the same screen. Both of the
|
||
window have the same background color. Because the
|
||
<code>act_color</code> action has “app” scope and the CSS is applied to
|
||
the default display shared by the windows.</p>
|
||
<pre><code>$ ./a.out & # Run the first application
|
||
[1] 82113
|
||
$ ./a.out # Run the second application
|
||
$ </code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
||
</body>
|
||
</html>
|