mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2025-01-26 19:58:29 +01:00
Fix typo errors. For example, Gtk4 => GTK 4.
This commit is contained in:
parent
767aaad185
commit
85f4248515
46 changed files with 5079 additions and 3216 deletions
16
README.md
16
README.md
|
@ -13,16 +13,16 @@ The table of contents is at the end of this abstract.
|
|||
- Section 26 to 29 describes the list model and the list view (GtkListView, GtkGridView and GtkColumnView).
|
||||
It also describes GtkExpression.
|
||||
|
||||
The latest version of the tutorial is located at [Gtk4-tutorial github repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
||||
The latest version of the tutorial is located at [Gtk4-tutorial GitHub repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
||||
You can read it from there directly without having to download anything.
|
||||
|
||||
#### Gtk4 Documentation
|
||||
#### GTK 4 Documentation
|
||||
|
||||
Please refer to [GTK API Reference](https://docs.gtk.org/gtk4/index.html)
|
||||
and [GNOME Developer Documentation Website](https://developer.gnome.org/) for further information.
|
||||
|
||||
These websites are newly opened lately (Aug/2021).
|
||||
The old documentation is located at [Gtk Reference Manual](https://developer-old.gnome.org/gtk4/stable/) and [Gnome Developer Center](https://developer-old.gnome.org/).
|
||||
The old documentation is located at [GTK Reference Manual](https://developer-old.gnome.org/gtk4/stable/) and [GNOME Developer Center](https://developer-old.gnome.org/).
|
||||
The new website is in progress at present, so you might need to refer to the old version.
|
||||
|
||||
If you want to know about GObject and the type system, please refer to [GObject tutorial](https://github.com/ToshioCP/Gobject-tutorial).
|
||||
|
@ -31,9 +31,9 @@ The GObject details are easy to understand and also necessary to know when writi
|
|||
#### Contribution
|
||||
|
||||
This tutorial is under development and unstable.
|
||||
Even though the codes of the examples have been tested on GTK version 4.0, bugs may still exist.
|
||||
Even though the codes of the examples have been tested on GTK 4 (version 4.0), bugs may still exist.
|
||||
If you find any bugs, errors or mistakes in the tutorial and C examples, please let me know.
|
||||
You can post it to [github issues](https://github.com/ToshioCP/Gtk4-tutorial/issues).
|
||||
You can post it to [GitHub issues](https://github.com/ToshioCP/Gtk4-tutorial/issues).
|
||||
You can also post corrected files as a commit to [pull request](https://github.com/ToshioCP/Gtk4-tutorial/pulls).
|
||||
When you make corrections, correct the source files, which are under the 'src' directory,
|
||||
then run `rake` to create to create the output file. The GFM files under the 'gfm' directory are automatically updated.
|
||||
|
@ -46,18 +46,18 @@ All questions are helpful and will make this tutorial get better.
|
|||
If you want to get a HTML or PDF version, you can make them with `rake`, which is a ruby version of make.
|
||||
Type `rake html` for HTML.
|
||||
Type `rake pdf` for PDF.
|
||||
There is a documentation \("[How to build Gtk4 Tutorial](gfm/Readme_for_developers.md)"\) that describes how to make them.
|
||||
There is a documentation \("[How to build GTK 4 Tutorial](gfm/Readme_for_developers.md)"\) that describes how to make them.
|
||||
|
||||
## Table of contents
|
||||
|
||||
1. [Prerequisite and License](gfm/sec1.md)
|
||||
1. [Installing Gtk4 into Linux distributions](gfm/sec2.md)
|
||||
1. [Installing GTK 4 into Linux distributions](gfm/sec2.md)
|
||||
1. [GtkApplication and GtkApplicationWindow](gfm/sec3.md)
|
||||
1. [Widgets (1)](gfm/sec4.md)
|
||||
1. [Widgets (2)](gfm/sec5.md)
|
||||
1. [String and memory management](gfm/sec6.md)
|
||||
1. [Widgets (3)](gfm/sec7.md)
|
||||
1. [Defining a Child object](gfm/sec8.md)
|
||||
1. [Defining a child object](gfm/sec8.md)
|
||||
1. [The User Interface (UI) file and GtkBuilder](gfm/sec9.md)
|
||||
1. [Build system](gfm/sec10.md)
|
||||
1. [Initialization and destruction of instances](gfm/sec11.md)
|
||||
|
|
24
Rakefile
24
Rakefile
|
@ -59,7 +59,7 @@ imagefiles = srcfiles.map do |file|
|
|||
imagefiles = FileList[*imagefiles]
|
||||
|
||||
CLEAN.append(FileList["latex/*.tex", "latex/*.aux", "latex/*.log", "latex/*.toc"])
|
||||
CLOBBER.append("Readme.md").append(FileList["gfm/*.md"])
|
||||
CLOBBER.append("README.md").append(FileList["gfm/*.md"])
|
||||
CLOBBER.append(FileList["docs/*.html"])
|
||||
CLOBBER.append(FileList["docs/image/*"])
|
||||
CLOBBER.append(FileList["latex/*.pdf"])
|
||||
|
@ -70,12 +70,12 @@ task default: :md
|
|||
task all: [:md, :html, :pdf]
|
||||
|
||||
mdfiles = srcfiles.pathmap("%f").ext(".md").map{|f| "gfm/#{f}"}
|
||||
task md: %w[Readme.md] + mdfiles
|
||||
task md: %w[README.md] + mdfiles
|
||||
|
||||
file "Readme.md" => [abstract] + secfiles do |t|
|
||||
file "README.md" => [abstract] + secfiles do |t|
|
||||
abstract_md = "gfm/"+abstract.pathmap("%f").ext(".md")
|
||||
src2md(abstract, "gfm")
|
||||
buf = ["# Gtk4 Tutorial for beginners\n\nThe github page of this tutorial is also available. Click [here](https://toshiocp.github.io/Gtk4-tutorial/).\n\n"]\
|
||||
buf = ["# GTK 4 Tutorial for beginners\n\nThe GitHub page of this tutorial is also available. Click [here](https://toshiocp.github.io/Gtk4-tutorial/).\n\n"]\
|
||||
+ File.readlines(abstract_md)\
|
||||
+ ["\n## Table of contents\n\n"]
|
||||
File.delete(abstract_md)
|
||||
|
@ -96,13 +96,13 @@ srcfiles.each do |src|
|
|||
if secfiles.include?(t.source)
|
||||
i = get_sec_num(src)
|
||||
if secfiles.size == 1
|
||||
nav = "Up: [Readme.md](../Readme.md)\n"
|
||||
nav = "Up: [README.md](../README.md)\n"
|
||||
elsif i == 1
|
||||
nav = "Up: [Readme.md](../Readme.md), Next: [Section 2](sec2.md)\n"
|
||||
nav = "Up: [README.md](../README.md), Next: [Section 2](sec2.md)\n"
|
||||
elsif i == secfiles.size
|
||||
nav = "Up: [Readme.md](../Readme.md), Prev: [Section #{i-1}](sec#{i-1}.md)\n"
|
||||
nav = "Up: [README.md](../README.md), Prev: [Section #{i-1}](sec#{i-1}.md)\n"
|
||||
else
|
||||
nav = "Up: [Readme.md](../Readme.md), Prev: [Section #{i-1}](sec#{i-1}.md), Next: [Section #{i+1}](sec#{i+1}.md)\n"
|
||||
nav = "Up: [README.md](../README.md), Prev: [Section #{i-1}](sec#{i-1}.md), Next: [Section #{i+1}](sec#{i+1}.md)\n"
|
||||
end
|
||||
File.write(t.name, nav + "\n" + File.read(t.name) + "\n" + nav)
|
||||
end
|
||||
|
@ -117,7 +117,7 @@ task html: %W[docs/index.html docs/.nojekyll] + htmlfiles + htmlimagefiles
|
|||
file "docs/index.html" => [abstract, "docs"] + secfiles do
|
||||
abstract_md = "docs/"+abstract.pathmap("%f").ext(".md")
|
||||
src2md(abstract, "html")
|
||||
buf = [ "# Gtk4 Tutorial for beginners\n\n" ]\
|
||||
buf = [ "# GTK 4 Tutorial for beginners\n\n" ]\
|
||||
+ File.readlines(abstract_md)\
|
||||
+ ["\n## Table of contents\n\n"]
|
||||
File.delete(abstract_md)
|
||||
|
@ -128,7 +128,7 @@ file "docs/index.html" => [abstract, "docs"] + secfiles do
|
|||
buf << "\nThis website uses [Bootstrap](https://getbootstrap.jp/)."
|
||||
File.write("docs/index.md", buf.join)
|
||||
mk_html_template(nil, nil, nil)
|
||||
sh "pandoc -s --template=docs/template.html --metadata=title:\"Gtk4 tutorial\" -o docs/index.html docs/index.md"
|
||||
sh "pandoc -s --template=docs/template.html --metadata=title:\"GTK 4 tutorial\" -o docs/index.html docs/index.md"
|
||||
File.delete "docs/index.md"
|
||||
File.delete "docs/template.html"
|
||||
end
|
||||
|
@ -156,7 +156,7 @@ srcfiles.each do |src|
|
|||
else
|
||||
mk_html_template("index.html", nil, nil)
|
||||
end
|
||||
sh "pandoc -s --template=docs/template.html --metadata=title:\"Gtk4 tutorial\" -o #{t.name} #{html_md}"
|
||||
sh "pandoc -s --template=docs/template.html --metadata=title:\"GTK 4 tutorial\" -o #{t.name} #{html_md}"
|
||||
File.delete(html_md)
|
||||
File.delete "docs/template.html"
|
||||
end
|
||||
|
@ -212,7 +212,7 @@ end
|
|||
task :clean
|
||||
task :clobber
|
||||
task :cleangfm do
|
||||
rm 'Readme.md'
|
||||
rm 'README.md'
|
||||
remove_entry_secure("gfm")
|
||||
end
|
||||
task :cleanhtml do
|
||||
|
|
|
@ -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;}
|
||||
|
@ -105,55 +105,95 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 id="how-to-build-gtk4-tutorial">How to build Gtk4 Tutorial</h1>
|
||||
<h1 id="how-to-build-gtk4-tutorial">How to build Gtk4-Tutorial</h1>
|
||||
<h2 id="quick-start-guide">Quick start guide</h2>
|
||||
<ol type="1">
|
||||
<li>You need linux operationg system, ruby, rake, pandoc and latex system.</li>
|
||||
<li>You need linux operationg system, ruby, rake, pandoc and latex
|
||||
system.</li>
|
||||
<li>download this repository and uncompress the file.</li>
|
||||
<li>change your current directory to the top directory of the source files.</li>
|
||||
<li>type <code>rake html</code> to create html files. The files are created under the <code>docs</code> directory.</li>
|
||||
<li>type <code>rake pdf</code> to create pdf a file. The file is created under the <code>latex</code> directory.</li>
|
||||
<li>change your current directory to the top directory of the source
|
||||
files.</li>
|
||||
<li>type <code>rake html</code> to create html files. The files are
|
||||
created under the <code>docs</code> directory.</li>
|
||||
<li>type <code>rake pdf</code> to create pdf a file. The file is created
|
||||
under the <code>latex</code> directory.</li>
|
||||
</ol>
|
||||
<h2 id="prerequisites">Prerequisites</h2>
|
||||
<ul>
|
||||
<li>Linux operationg system. The programs in this repository has been tested on Ubuntu 21.04.</li>
|
||||
<li>Download the files in the repository. There are two ways to download.
|
||||
<li>Linux operationg system. The programs in this repository has been
|
||||
tested on Ubuntu 21.04.</li>
|
||||
<li>Download the files in the repository. There are two ways to
|
||||
download.
|
||||
<ol type="1">
|
||||
<li>Use git. Type <code>git clone https://github.com/ToshioCP/Gtk4-tutorial.git</code> on the command-line.</li>
|
||||
<li>Download a zip file. Click on the <code>Code</code> button (green button) on the top page of the repository. Then, click “Download ZIP”.</li>
|
||||
<li>Use git. Type
|
||||
<code>git clone https://github.com/ToshioCP/Gtk4-tutorial.git</code> on
|
||||
the command-line.</li>
|
||||
<li>Download a zip file. Click on the <code>Code</code> button (green
|
||||
button) on the top page of the repository. Then, click “Download
|
||||
ZIP”.</li>
|
||||
</ol></li>
|
||||
<li>Ruby and rake.</li>
|
||||
<li>Pandoc. It is used to convert markdown to html and/or latex.</li>
|
||||
<li>Latex system. Texlive2020 or later version is recommended. It is used to generate the pdf file.</li>
|
||||
<li>Latex system. Texlive2020 or later version is recommended. It is
|
||||
used to generate the pdf file.</li>
|
||||
</ul>
|
||||
<h2 id="github-flavored-markdown">Github flavored markdown</h2>
|
||||
<p>When you see <a href="https://github.com/ToshioCP/Gtk4-tutorial">gtk4_tutorial github repository</a>, you’ll find the contents of the <code>Readme.md</code> file. This file is written in markdown language. Markdown files have <code>.md</code> suffix.</p>
|
||||
<p>There are several kinds of markdown language. <code>Readme.md</code> uses ‘github flavored markdown’, which is often shortened as GFM. Markdown files in the <code>gfm</code> directory are written in GFM. If you are not familiar with it, refer to the page <a href="https://github.github.com/gfm/">github flavor markdown spec</a>.</p>
|
||||
<h2 id="github-flavored-markdown">GitHub Flavored Markdown</h2>
|
||||
<p>When you see <a
|
||||
href="https://github.com/ToshioCP/Gtk4-tutorial">gtk4_tutorial GitHub
|
||||
repository</a>, you’ll find the contents of the <code>Readme.md</code>
|
||||
file. This file is written in markdown language. Markdown files have
|
||||
<code>.md</code> suffix.</p>
|
||||
<p>There are several kinds of markdown language. <code>Readme.md</code>
|
||||
uses ‘GitHub Flavored Markdown’, which is often shortened as GFM.
|
||||
Markdown files in the <code>gfm</code> directory are written in GFM. If
|
||||
you are not familiar with it, refer to the page <a
|
||||
href="https://github.github.com/gfm/">GitHub Flavor Markdown
|
||||
spec</a>.</p>
|
||||
<h2 id="pandocs-markdown">Pandoc’s markdown</h2>
|
||||
<p>This tutorial also uses another markdown – ‘pandoc’s markdown’. Pandoc is a converter between markdown, html, latex, word docx and so on. This type of markdown is used to convert markdown to html and/or latex.</p>
|
||||
<p>This tutorial also uses another markdown – ‘pandoc’s markdown’.
|
||||
Pandoc is a converter between markdown, html, latex, word docx and so
|
||||
on. This type of markdown is used to convert markdown to html and/or
|
||||
latex.</p>
|
||||
<h2 id="src.md-file">.Src.md file</h2>
|
||||
<p>.Src.md file has “.src.md” suffix. The syntax of .src.md file is similar to markdown but it has a special command which isn’t included in markdown syntax. It is @@@ command. The command starts with a line begins with “@@@” and ends with a line “@@@”. For example,</p>
|
||||
<p>.Src.md file has “.src.md” suffix. The syntax of .src.md file is
|
||||
similar to markdown but it has a special command which isn’t included in
|
||||
markdown syntax. It is @@@ command. The command starts with a line
|
||||
begins with “@@@” and ends with a line “@@@”. For example,</p>
|
||||
<pre><code>@@@include
|
||||
tfeapplication.c
|
||||
@@@</code></pre>
|
||||
<p>There are four types of @@@ command.</p>
|
||||
<h3 id="include">@@<span class="citation" data-cites="include">@include</span></h3>
|
||||
<p>This type of @@@ command starts with a line “@@<span class="citation" data-cites="include">@include</span>”.</p>
|
||||
<h3 id="include">@@<span class="citation"
|
||||
data-cites="include">@include</span></h3>
|
||||
<p>This type of @@@ command starts with a line “@@<span class="citation"
|
||||
data-cites="include">@include</span>”.</p>
|
||||
<pre><code>@@@include
|
||||
tfeapplication.c
|
||||
@@@</code></pre>
|
||||
<p>This command replaces itself with the texts read from the C source files surrounded by <code>@@@include</code> and <code>@@@</code>. If a function list follows the filename, only the functions are read.</p>
|
||||
<p>This command replaces itself with the texts read from the C source
|
||||
files surrounded by <code>@@@include</code> and <code>@@@</code>. If a
|
||||
function list follows the filename, only the functions are read.</p>
|
||||
<pre><code>@@@include
|
||||
tfeapplication.c main startup
|
||||
@@@</code></pre>
|
||||
<p>The command above is replaced by the contents of <code>main</code> and <code>startup</code> functions in the file <code>tfeapplication.c</code>.</p>
|
||||
<p>Other language’s source files are also possible. The following example shows that the ruby file ‘lib_src2md.rb’ is inserted by the command.</p>
|
||||
<p>The command above is replaced by the contents of <code>main</code>
|
||||
and <code>startup</code> functions in the file
|
||||
<code>tfeapplication.c</code>.</p>
|
||||
<p>Other language’s source files are also possible. The following
|
||||
example shows that the ruby file ‘lib_src2md.rb’ is inserted by the
|
||||
command.</p>
|
||||
<pre><code>@@@include
|
||||
lib_src2md.rb
|
||||
@@@</code></pre>
|
||||
<p>You can’t specify functions or methods unless the file is C source.</p>
|
||||
<p>The inserted text is converted to fence code block. Fence code block begins with <code>~~~</code> and ends with <code>~~~</code>. The contents are displayed verbatim. <code>~~~</code> is look like a fence so the block is called “fence code block”.</p>
|
||||
<p>If the target markdown is GFM, then an info string can follow the beginning fence. The following example shows that the @@@ command includes a C source file <code>sample.c</code>.</p>
|
||||
<p>You can’t specify functions or methods unless the file is C
|
||||
source.</p>
|
||||
<p>The inserted text is converted to fence code block. Fence code block
|
||||
begins with <code>~~~</code> and ends with <code>~~~</code>. The
|
||||
contents are displayed verbatim. <code>~~~</code> is look like a fence
|
||||
so the block is called “fence code block”.</p>
|
||||
<p>If the target markdown is GFM, then an info string can follow the
|
||||
beginning fence. The following example shows that the @@@ command
|
||||
includes a C source file <code>sample.c</code>.</p>
|
||||
<pre><code>$ cat src/sample.c
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
|
@ -175,20 +215,26 @@ main (int argc, char **argv) {
|
|||
}
|
||||
~~~
|
||||
... ...</code></pre>
|
||||
<p>Info strings are usually languages like C, ruby, xml and so on. This string is decided with the filename extension.</p>
|
||||
<p>Info strings are usually languages like C, ruby, xml and so on. This
|
||||
string is decided with the filename extension.</p>
|
||||
<ul>
|
||||
<li><code>.c</code> => C</li>
|
||||
<li><code>.rb</code> => ruby</li>
|
||||
<li><code>.xml</code> => xml</li>
|
||||
</ul>
|
||||
<p>The supported languages are written in the <code>lang</code> method in <code>lib/lib_src2md.rb</code>.</p>
|
||||
<p>A line number will be inserted at the top of each line in the code block. If you don’t want to insert it, give “-N” option to @@<span class="citation" data-cites="include">@include</span> command.</p>
|
||||
<p>The supported languages are written in the <code>lang</code> method
|
||||
in <code>lib/lib_src2md.rb</code>.</p>
|
||||
<p>A line number will be inserted at the top of each line in the code
|
||||
block. If you don’t want to insert it, give “-N” option to @@<span
|
||||
class="citation" data-cites="include">@include</span> command.</p>
|
||||
<p>Options:</p>
|
||||
<ul>
|
||||
<li><code>-n</code>: Inserts a line number at the top of each line (default).</li>
|
||||
<li><code>-n</code>: Inserts a line number at the top of each line
|
||||
(default).</li>
|
||||
<li><code>-N</code>: No line number is inserted.</li>
|
||||
</ul>
|
||||
<p>The following shows that the line numbers are inserted at the beginning of each line.</p>
|
||||
<p>The following shows that the line numbers are inserted at the
|
||||
beginning of each line.</p>
|
||||
<pre><code>$cat src/sample.src.md
|
||||
... ...
|
||||
@@@include
|
||||
|
@ -205,36 +251,55 @@ $ cat gfm/sample.md
|
|||
14 }
|
||||
~~~
|
||||
... ...</code></pre>
|
||||
<p>If a markdown is an intermediate file to html, another type of info string follows the fence. If @@<span class="citation" data-cites="include">@include</span> command doesn’t have -N option, then the generated markdown is:</p>
|
||||
<p>If a markdown is an intermediate file to html, another type of info
|
||||
string follows the fence. If @@<span class="citation"
|
||||
data-cites="include">@include</span> command doesn’t have -N option,
|
||||
then the generated markdown is:</p>
|
||||
<pre><code>~~~{.C .numberLines}
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
... ...
|
||||
}
|
||||
~~~</code></pre>
|
||||
<p>The info string <code>.C</code> specifies C language. The info string <code>.numberLines</code> is a class of the pandoc markdown. If the class is given, pandoc generates CSS to insert line numbers to the source code in the html file. That’s why the fence code block in the markdown doesn’t have line numbers, which is different from gfm markdown. If <code>-N</code> option is given, then the info string is <code>{.C}</code> only.</p>
|
||||
<p>If a markdown is an intermediate file to latex, the same info string follows the beginning fence.</p>
|
||||
<p>The info string <code>.C</code> specifies C language. The info string
|
||||
<code>.numberLines</code> is a class of the pandoc markdown. If the
|
||||
class is given, pandoc generates CSS to insert line numbers to the
|
||||
source code in the html file. That’s why the fence code block in the
|
||||
markdown doesn’t have line numbers, which is different from gfm
|
||||
markdown. If <code>-N</code> option is given, then the info string is
|
||||
<code>{.C}</code> only.</p>
|
||||
<p>If a markdown is an intermediate file to latex, the same info string
|
||||
follows the beginning fence.</p>
|
||||
<pre><code>~~~{.C .numberLines}
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
... ...
|
||||
}
|
||||
~~~</code></pre>
|
||||
<p>Rake uses pandoc with –listings option to convert the markdown to a latex file. The generated latex file uses ‘listings package’ to list source files instead of verbatim environment. The markdown above is converted to the following latex source file.</p>
|
||||
<p>Rake uses pandoc with –listings option to convert the markdown to a
|
||||
latex file. The generated latex file uses ‘listings package’ to list
|
||||
source files instead of verbatim environment. The markdown above is
|
||||
converted to the following latex source file.</p>
|
||||
<pre><code>\begin{lstlisting}[language=C, numbers=left]
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
... ...
|
||||
}
|
||||
\end{lstlisting}</code></pre>
|
||||
<p>Listing package can color or emphasize keywords, strings, comments and directives. But it doesn’t really analyze the syntax of the language, so the emphasis tokens are limited.</p>
|
||||
<p>@@<span class="citation" data-cites="include">@include</span> command has two advantages.</p>
|
||||
<p>Listing package can color or emphasize keywords, strings, comments
|
||||
and directives. But it doesn’t really analyze the syntax of the
|
||||
language, so the emphasis tokens are limited.</p>
|
||||
<p>@@<span class="citation" data-cites="include">@include</span> command
|
||||
has two advantages.</p>
|
||||
<ol type="1">
|
||||
<li>Less typing.</li>
|
||||
<li>You don’t need to modify your .src.md file, even if the C source file is modified.</li>
|
||||
<li>You don’t need to modify your .src.md file, even if the C source
|
||||
file is modified.</li>
|
||||
</ol>
|
||||
<h3 id="shell">@@<span class="citation" data-cites="shell">@shell</span></h3>
|
||||
<p>This type of @@@ command starts with a line begins with “@@<span class="citation" data-cites="shell">@shell</span>”.</p>
|
||||
<h3 id="shell">@@<span class="citation"
|
||||
data-cites="shell">@shell</span></h3>
|
||||
<p>This type of @@@ command starts with a line begins with “@@<span
|
||||
class="citation" data-cites="shell">@shell</span>”.</p>
|
||||
<pre><code>@@@shell
|
||||
shell command
|
||||
... ...
|
||||
|
@ -253,8 +318,15 @@ wc Rakefile
|
|||
$ wc Rakefile
|
||||
164 475 4971 Rakefile
|
||||
~~~</code></pre>
|
||||
<h3 id="if-series">@@<span class="citation" data-cites="if">@if</span> series</h3>
|
||||
<p>This type of @@@ command starts with a line begins with “@@<span class="citation" data-cites="if">@if</span>”, and followed by “@@<span class="citation" data-cites="elif">@elif</span>”, “@@<span class="citation" data-cites="else">@else</span>” or “@@<span class="citation" data-cites="end">@end</span>”. This command is similar to “#if”, “#elif”, #else" and “#endif” directives in the C preprocessor. For example,</p>
|
||||
<h3 id="if-series">@@<span class="citation" data-cites="if">@if</span>
|
||||
series</h3>
|
||||
<p>This type of @@@ command starts with a line begins with “@@<span
|
||||
class="citation" data-cites="if">@if</span>”, and followed by “@@<span
|
||||
class="citation" data-cites="elif">@elif</span>”, “@@<span
|
||||
class="citation" data-cites="else">@else</span>” or “@@<span
|
||||
class="citation" data-cites="end">@end</span>”. This command is similar
|
||||
to “#if”, “#elif”, #else” and “#endif” directives in the C preprocessor.
|
||||
For example,</p>
|
||||
<pre><code>@@@if gfm
|
||||
Refer to [tfetextview API reference](tfetextview_doc.md)
|
||||
@@@elif html
|
||||
|
@ -262,19 +334,28 @@ Refer to [tfetextview API reference](tfetextview_doc.html)
|
|||
@@@elif latex
|
||||
Refer to tfetextview API reference in appendix.
|
||||
@@@end</code></pre>
|
||||
<p><code>@@@if</code> and <code>@@@elif</code> have conditions. They are <code>gfm</code>, <code>html</code> or <code>latex</code> so far.</p>
|
||||
<p><code>@@@if</code> and <code>@@@elif</code> have conditions. They are
|
||||
<code>gfm</code>, <code>html</code> or <code>latex</code> so far.</p>
|
||||
<ul>
|
||||
<li>gfm: if the target is GFM</li>
|
||||
<li>html: if the target is html</li>
|
||||
<li>latex: if the target is pdf.</li>
|
||||
</ul>
|
||||
<p>Other type of conditions may be available in the future version.</p>
|
||||
<p>The code analyzing @@<span class="citation" data-cites="if">@if</span> series command is rather complicated. It is based on the state diagram below.</p>
|
||||
<p>The code analyzing @@<span class="citation"
|
||||
data-cites="if">@if</span> series command is rather complicated. It is
|
||||
based on the state diagram below.</p>
|
||||
<figure>
|
||||
<img src="image/state_diagram.png" alt="" /><figcaption>state diagram</figcaption>
|
||||
<img src="image/state_diagram.png" alt="state diagram" />
|
||||
<figcaption aria-hidden="true">state diagram</figcaption>
|
||||
</figure>
|
||||
<h3 id="table">@@<span class="citation" data-cites="table">@table</span></h3>
|
||||
<p>This type of @@@ command starts with a line begins with “@@<span class="citation" data-cites="table">@table</span>”. The contents of this command is a table of the GFM or pandoc’s markdown. The command makes a table easy to read. For example, a text file <code>sample.md</code> has a table like this:</p>
|
||||
<h3 id="table">@@<span class="citation"
|
||||
data-cites="table">@table</span></h3>
|
||||
<p>This type of @@@ command starts with a line begins with “@@<span
|
||||
class="citation" data-cites="table">@table</span>”. The contents of this
|
||||
command is a table of the GFM or pandoc’s markdown. The command makes a
|
||||
table easy to read. For example, a text file <code>sample.md</code> has
|
||||
a table like this:</p>
|
||||
<pre><code>Price list
|
||||
|
||||
@@@table
|
||||
|
@ -290,18 +371,40 @@ Refer to tfetextview API reference in appendix.
|
|||
|:---:|:---:|
|
||||
|mouse| $10 |
|
||||
| PC |$500 |</code></pre>
|
||||
<p>This command just changes the appearance of the table. There’s no influence on html/latex files that is converted from the markdown. Notice that the command supports only the above type of markdown table format.</p>
|
||||
<p>A script <code>mktbl.rb</code> supports this command. If you run the script like this:</p>
|
||||
<p>This command just changes the appearance of the table. There’s no
|
||||
influence on html/latex files that is converted from the markdown.
|
||||
Notice that the command supports only the above type of markdown table
|
||||
format.</p>
|
||||
<p>A script <code>mktbl.rb</code> supports this command. If you run the
|
||||
script like this:</p>
|
||||
<pre><code>$ ruby mktbl.rb sample.md</code></pre>
|
||||
<p>Then, the tables in ‘sample.md’ will be arranged. The script also makes a backup file <code>sample.md.bak</code>.</p>
|
||||
<p>The task of the script seems easy, but the program is not so simple. The script <code>mktbl.rb</code> uses a library <code>lib/lib_src2md.rb</code></p>
|
||||
<p>@@<span class="citation" data-cites="commands">@commands</span> are effective in the whole text. This means you can’t stop the @@<span class="citation" data-cites="commands">@commands</span>. But sometimes you want to show the commands literally like this document. One solution is to add four blanks at the top of the line. Then @@<span class="citation" data-cites="commands">@commands</span> are not effective because @@<span class="citation" data-cites="commands">@commands</span> must be at the top of the line.</p>
|
||||
<p>Then, the tables in ‘sample.md’ will be arranged. The script also
|
||||
makes a backup file <code>sample.md.bak</code>.</p>
|
||||
<p>The task of the script seems easy, but the program is not so simple.
|
||||
The script <code>mktbl.rb</code> uses a library
|
||||
<code>lib/lib_src2md.rb</code></p>
|
||||
<p>@@<span class="citation" data-cites="commands">@commands</span> are
|
||||
effective in the whole text. This means you can’t stop the @@<span
|
||||
class="citation" data-cites="commands">@commands</span>. But sometimes
|
||||
you want to show the commands literally like this document. One solution
|
||||
is to add four blanks at the top of the line. Then @@<span
|
||||
class="citation" data-cites="commands">@commands</span> are not
|
||||
effective because @@<span class="citation"
|
||||
data-cites="commands">@commands</span> must be at the top of the
|
||||
line.</p>
|
||||
<h2 id="conversion">Conversion</h2>
|
||||
<p>The @@@ commands are carried out by a method <code>src2md</code>, which is in the file <code>lib/lib_src2md.rb</code>. This method converts <code>.src.md</code> file into <code>.md</code> file. In addition, some other conversions are made by <code>src2md</code> method.</p>
|
||||
<p>The @@@ commands are carried out by a method <code>src2md</code>,
|
||||
which is in the file <code>lib/lib_src2md.rb</code>. This method
|
||||
converts <code>.src.md</code> file into <code>.md</code> file. In
|
||||
addition, some other conversions are made by <code>src2md</code>
|
||||
method.</p>
|
||||
<ul>
|
||||
<li>Relative links are changed according to the change of the base directory.</li>
|
||||
<li>Size option in an image link is removed when the destination is GFM or html.</li>
|
||||
<li>Relative link is removed except .src.md files when the destination is html.</li>
|
||||
<li>Relative links are changed according to the change of the base
|
||||
directory.</li>
|
||||
<li>Size option in an image link is removed when the destination is GFM
|
||||
or html.</li>
|
||||
<li>Relative link is removed except .src.md files when the destination
|
||||
is html.</li>
|
||||
<li>Relative link is removed when the destination is latex.</li>
|
||||
</ul>
|
||||
<p>The order of the conversions are:</p>
|
||||
|
@ -312,40 +415,88 @@ Refer to tfetextview API reference in appendix.
|
|||
<li>@@<span class="citation" data-cites="shell">@shell</span></li>
|
||||
<li>others</li>
|
||||
</ol>
|
||||
<p>There is the <code>src2md.rb</code> file in the top directory of this repository. It just invokes the method <code>src2md</code>. In the same way, the method is called in the action in the <code>Rakefile</code>.</p>
|
||||
<p>There is the <code>src2md.rb</code> file in the top directory of this
|
||||
repository. It just invokes the method <code>src2md</code>. In the same
|
||||
way, the method is called in the action in the
|
||||
<code>Rakefile</code>.</p>
|
||||
<h2 id="directory-structure">Directory structure</h2>
|
||||
<p>There are seven directories under <code>gtk4_tutorial</code> directory. They are <code>gfm</code>, <code>docs</code>, <code>latex</code>, <code>src</code>, <code>image</code>, <code>test</code> and <code>lib</code>. Three directories <code>gfm</code>, <code>docs</code> and <code>latex</code> are the destination directories for GFM, html and latex files respectively. It is possible that these three directories don’t exist before the conversion.</p>
|
||||
<p>There are seven directories under <code>gtk4_tutorial</code>
|
||||
directory. They are <code>gfm</code>, <code>docs</code>,
|
||||
<code>latex</code>, <code>src</code>, <code>image</code>,
|
||||
<code>test</code> and <code>lib</code>. Three directories
|
||||
<code>gfm</code>, <code>docs</code> and <code>latex</code> are the
|
||||
destination directories for GFM, html and latex files respectively. It
|
||||
is possible that these three directories don’t exist before the
|
||||
conversion.</p>
|
||||
<ul>
|
||||
<li>src: This directory contains .src.md files and C-related source files.</li>
|
||||
<li>src: This directory contains .src.md files and C-related source
|
||||
files.</li>
|
||||
<li>image: This directory contains image files like png or jpg.</li>
|
||||
<li>gfm: <code>rake</code> converts .src.md files to GFM files and store them in this directory.</li>
|
||||
<li>docs: <code>rake html</code> will convert .src.md files to html files and store them in this directory.</li>
|
||||
<li>latex: <code>rake pdf</code> will convert .src.md files to latex files and store them in this directory. Finally it creates a pdf file in <code>latex</code> directory.</li>
|
||||
<li>gfm: <code>rake</code> converts .src.md files to GFM files and store
|
||||
them in this directory.</li>
|
||||
<li>docs: <code>rake html</code> will convert .src.md files to html
|
||||
files and store them in this directory.</li>
|
||||
<li>latex: <code>rake pdf</code> will convert .src.md files to latex
|
||||
files and store them in this directory. Finally it creates a pdf file in
|
||||
<code>latex</code> directory.</li>
|
||||
<li>lib: This directory includes ruby library files.</li>
|
||||
<li>test: This directory contains test files. The tests are carried out by typing <code>rake test</code> on the terminal.</li>
|
||||
<li>test: This directory contains test files. The tests are carried out
|
||||
by typing <code>rake test</code> on the terminal.</li>
|
||||
</ul>
|
||||
<h2 id="src-directory-and-the-top-directory">Src directory and the top directory</h2>
|
||||
<p>Src directory contains .src.md files and C-related source files. The top directory, which is gtk_tutorial directory, contains <code>Rakefile</code>, <code>src2md.rb</code> and some other files. When <code>Readme.md</code> is generated, it will be located at the top directory. <code>Readme.md</code> has title, abstract, table of contents with links to GFM files.</p>
|
||||
<p>Rakefile describes how to convert .src.md files into GFM, html and/or pdf files. Rake carries out the conversion according to the <code>Rakefile</code>.</p>
|
||||
<h2 id="the-name-of-files-in-src-directory">The name of files in src directory</h2>
|
||||
<p>Files in <code>src</code> directory are an abstract, sections of the document and other .src.md files. An <code>abstract.src.md</code> contains the abstract of this tutorial. Each section filename is “sec”, number of the section and “.src.md” suffix. For example, “sec1.src.md”, “sec5.src.md” or “sec12.src.md”. They are the files correspond to the section 1, section 5 and section 12 respectively.</p>
|
||||
<h2 id="src-directory-and-the-top-directory">Src directory and the top
|
||||
directory</h2>
|
||||
<p>Src directory contains .src.md files and C-related source files. The
|
||||
top directory, which is gtk_tutorial directory, contains
|
||||
<code>Rakefile</code>, <code>src2md.rb</code> and some other files. When
|
||||
<code>Readme.md</code> is generated, it will be located at the top
|
||||
directory. <code>Readme.md</code> has title, abstract, table of contents
|
||||
with links to GFM files.</p>
|
||||
<p>Rakefile describes how to convert .src.md files into GFM, html and/or
|
||||
pdf files. Rake carries out the conversion according to the
|
||||
<code>Rakefile</code>.</p>
|
||||
<h2 id="the-name-of-files-in-src-directory">The name of files in src
|
||||
directory</h2>
|
||||
<p>Files in <code>src</code> directory are an abstract, sections of the
|
||||
document and other .src.md files. An <code>abstract.src.md</code>
|
||||
contains the abstract of this tutorial. Each section filename is “sec”,
|
||||
number of the section and “.src.md” suffix. For example, “sec1.src.md”,
|
||||
“sec5.src.md” or “sec12.src.md”. They are the files correspond to the
|
||||
section 1, section 5 and section 12 respectively.</p>
|
||||
<h2 id="c-source-file-directory">C source file directory</h2>
|
||||
<p>Most of .src.md files have <code>@@@include</code> commands and they include C source files. Such C source files are located in the subdirectories of <code>src</code> directory.</p>
|
||||
<p>Those C files have been compiled and tested. When you compile source files, some auxiliary files and a target file like <code>a.out</code> are created. Or <code>_build</code> directory is made when <code>meson</code> and <code>ninja</code> is used when compiling. Those files are not tracked by <code>git</code> because they are specified in <code>.gitignore</code>.</p>
|
||||
<p>The name of the subdirectories should be independent of section names. It is because of renumbering, which will be explained in the next subsection.</p>
|
||||
<p>Most of .src.md files have <code>@@@include</code> commands and they
|
||||
include C source files. Such C source files are located in the
|
||||
subdirectories of <code>src</code> directory.</p>
|
||||
<p>Those C files have been compiled and tested. When you compile source
|
||||
files, some auxiliary files and a target file like <code>a.out</code>
|
||||
are created. Or <code>_build</code> directory is made when
|
||||
<code>meson</code> and <code>ninja</code> is used when compiling. Those
|
||||
files are not tracked by <code>git</code> because they are specified in
|
||||
<code>.gitignore</code>.</p>
|
||||
<p>The name of the subdirectories should be independent of section
|
||||
names. It is because of renumbering, which will be explained in the next
|
||||
subsection.</p>
|
||||
<h2 id="renumbering">Renumbering</h2>
|
||||
<p>Sometimes you might want to insert a new section. For example, you want to insert it between section 4 and section 5. You can make a temporary section 4.5, that is a rational number between 4 and 5. However, section numbers are usually integer so section 4.5 must be changed to section 5. And the numbers of the following sections must be increased by one.</p>
|
||||
<p>This renumbering is done by the <code>renumber</code> method in the <code>lib/lib_renumber.rb</code> file.</p>
|
||||
<p>Sometimes you might want to insert a new section. For example, you
|
||||
want to insert it between section 4 and section 5. You can make a
|
||||
temporary section 4.5, that is a rational number between 4 and 5.
|
||||
However, section numbers are usually integer so section 4.5 must be
|
||||
changed to section 5. And the numbers of the following sections must be
|
||||
increased by one.</p>
|
||||
<p>This renumbering is done by the <code>renumber</code> method in the
|
||||
<code>lib/lib_renumber.rb</code> file.</p>
|
||||
<ul>
|
||||
<li>It changes file names.</li>
|
||||
<li>If there are references (links) to sections in .src.md files, the section numbers will be automatically renumbered.</li>
|
||||
<li>If there are references (links) to sections in .src.md files, the
|
||||
section numbers will be automatically renumbered.</li>
|
||||
</ul>
|
||||
<h2 id="rakefile">Rakefile</h2>
|
||||
<p>Rakefile is similar to Makefile but controlled by rake, which is a ruby script. Rakefile in this tutorial has the following tasks.</p>
|
||||
<p>Rakefile is similar to Makefile but controlled by rake, which is a
|
||||
ruby script. Rakefile in this tutorial has the following tasks.</p>
|
||||
<ul>
|
||||
<li>md: generate GFM markdown files. This is the default.</li>
|
||||
<li>html: generate html files.</li>
|
||||
<li>pdf: generate latex files and a pdf file, which is compiled by lualatex.</li>
|
||||
<li>pdf: generate latex files and a pdf file, which is compiled by
|
||||
lualatex.</li>
|
||||
<li>all: generate md, html and pdf files.</li>
|
||||
<li>clean: delete latex intermediate files.</li>
|
||||
<li>clobber: delete all the generated files.</li>
|
||||
|
@ -354,43 +505,106 @@ Refer to tfetextview API reference in appendix.
|
|||
<h2 id="generate-gfm-markdown-files">Generate GFM markdown files</h2>
|
||||
<p>Markdown files (GFM) are generated by rake.</p>
|
||||
<pre><code>$ rake</code></pre>
|
||||
<p>This command generates <code>Readme.md</code> with <code>src/abstract.src.md</code> and titles of each <code>.src.md</code> file. At the same time, it converts each .src.md file into a GFM file under the <code>gfm</code> directory. Navigation lines are added at the top and bottom of each markdown section file.</p>
|
||||
<p>You can describe width and height of images in .src.md files. For example,</p>
|
||||
<p>This command generates <code>Readme.md</code> with
|
||||
<code>src/abstract.src.md</code> and titles of each <code>.src.md</code>
|
||||
file. At the same time, it converts each .src.md file into a GFM file
|
||||
under the <code>gfm</code> directory. Navigation lines are added at the
|
||||
top and bottom of each markdown section file.</p>
|
||||
<p>You can describe width and height of images in .src.md files. For
|
||||
example,</p>
|
||||
<pre><code>![sample image](../image/sample_image.png){width=10cm height=6cm}</code></pre>
|
||||
<p>The size between left brace and right brace is used in latex file and it is not fit to GFM syntax. So the size will be removed in the conversion.</p>
|
||||
<p>If a .src.md file has relative URL links, they will be changed by conversion. Because .src.md files are located under the <code>src</code> directory and GFM files are located under the <code>gfm</code> directory. That means the base directory of the relative link are different. For example, <code>[src/sample.c](sample.c)</code> is translated to <code>[src/sample.c](../src/sample.c)</code>.</p>
|
||||
<p>If a link points another .src.md file, then the target filename will be changed to .md file. For example, <code>[Section 5](sec5.src.md)</code> is translated to <code>[Section 5](sec5.md)</code>.</p>
|
||||
<p>If you want to clean the directory, that means remove all the generated markdown files, type <code>rake clobber</code>.</p>
|
||||
<p>The size between left brace and right brace is used in latex file and
|
||||
it is not fit to GFM syntax. So the size will be removed in the
|
||||
conversion.</p>
|
||||
<p>If a .src.md file has relative URL links, they will be changed by
|
||||
conversion. Because .src.md files are located under the <code>src</code>
|
||||
directory and GFM files are located under the <code>gfm</code>
|
||||
directory. That means the base directory of the relative link are
|
||||
different. For example, <code>[src/sample.c](sample.c)</code> is
|
||||
translated to <code>[src/sample.c](../src/sample.c)</code>.</p>
|
||||
<p>If a link points another .src.md file, then the target filename will
|
||||
be changed to .md file. For example,
|
||||
<code>[Section 5](sec5.src.md)</code> is translated to
|
||||
<code>[Section 5](sec5.md)</code>.</p>
|
||||
<p>If you want to clean the directory, that means remove all the
|
||||
generated markdown files, type <code>rake clobber</code>.</p>
|
||||
<pre><code>$ rake clobber</code></pre>
|
||||
<p>Sometimes this is necessary before generating GFM files.</p>
|
||||
<pre><code>$ rake clobber
|
||||
$ rake</code></pre>
|
||||
<p>For example, if you append a new section and other files are still the same as before, <code>rake clobber</code> is necessary. Because the navigation of the previous section of the newly added section needs to be updated. If you don’t do <code>rake clobber</code>, then it won’t be updated because the the timestamp of .md file in gfm is newer than the one of .src.md file. In this case, using <code>touch</code> to the previous section .src.md also works to update the file.</p>
|
||||
<p>If you see the github repository (ToshioCP/Gtk4-tutorial), <code>Readme.md</code> is shown below the code. And <code>Readme.md</code> includes links to each markdown files. The repository not only stores source files but also shows the whole tutorial.</p>
|
||||
<p>For example, if you append a new section and other files are still
|
||||
the same as before, <code>rake clobber</code> is necessary. Because the
|
||||
navigation of the previous section of the newly added section needs to
|
||||
be updated. If you don’t do <code>rake clobber</code>, then it won’t be
|
||||
updated because the the timestamp of .md file in gfm is newer than the
|
||||
one of .src.md file. In this case, using <code>touch</code> to the
|
||||
previous section .src.md also works to update the file.</p>
|
||||
<p>If you see the GitHub repository (ToshioCP/Gtk4-tutorial),
|
||||
<code>Readme.md</code> is shown below the code. And
|
||||
<code>Readme.md</code> includes links to each markdown files. The
|
||||
repository not only stores source files but also shows the whole
|
||||
tutorial.</p>
|
||||
<h2 id="generate-html-files">Generate html files</h2>
|
||||
<p>Src.md files can be translated to html files. You need pandoc to do this. Most linux distribution has pandoc package. Refer to your distribution document to install it.</p>
|
||||
<p>Src.md files can be translated to html files. You need pandoc to do
|
||||
this. Most linux distribution has pandoc package. Refer to your
|
||||
distribution document to install it.</p>
|
||||
<p>Type <code>rake html</code> to generate html files.</p>
|
||||
<pre><code>$ rake html</code></pre>
|
||||
<p>First, it generates pandoc’s markdown files under <code>docs</code> directory. Then, pandoc converts them to html files. The width and height of image files are removed. Links to .src.md files will be converted like this.</p>
|
||||
<p>First, it generates pandoc’s markdown files under <code>docs</code>
|
||||
directory. Then, pandoc converts them to html files. The width and
|
||||
height of image files are removed. Links to .src.md files will be
|
||||
converted like this.</p>
|
||||
<pre><code>[Section 5](sec5.src.md) => [Section 5](sec5.html)</code></pre>
|
||||
<p>Image files are copied to <code>docs/image</code> direcotiry and links to them will be converted like this:</p>
|
||||
<p>Image files are copied to <code>docs/image</code> direcotiry and
|
||||
links to them will be converted like this:</p>
|
||||
<pre><code>[sample.png](../image/sample.png) => [sample.png](image/sample.png)</code></pre>
|
||||
<p>Other relative links will be removed.</p>
|
||||
<p><code>index.html</code> is the top html file. If you want to clean html files, type <code>rake clobber</code> or <code>cleanhtml</code>.</p>
|
||||
<p><code>index.html</code> is the top html file. If you want to clean
|
||||
html files, type <code>rake clobber</code> or
|
||||
<code>cleanhtml</code>.</p>
|
||||
<pre><code>$ rake clobber</code></pre>
|
||||
<p>Every html file has a header (<code><head> -- </head></code>). It is created by pandoc with ‘-s’ option. You can customize the output with your own template file for pandoc. Rake uses <code>lib/lib_mk_html_template.rb</code> to create its own template. The template inserts bootstrap CSS and Javascript through <code>jsDelivr</code>.</p>
|
||||
<p>The <code>docs</code> directory contains all the necessary html files. They are used in the <a href="https://ToshioCP.github.io/Gtk4-tutorial">github pages</a> of this repository.</p>
|
||||
<p>So if you want to publish this tutorial on your own web site, just upload the files in the <code>docs</code> directory to your site.</p>
|
||||
<p>Every html file has a header
|
||||
(<code><head> -- </head></code>). It is created by pandoc
|
||||
with ‘-s’ option. You can customize the output with your own template
|
||||
file for pandoc. Rake uses <code>lib/lib_mk_html_template.rb</code> to
|
||||
create its own template. The template inserts bootstrap CSS and
|
||||
Javascript through <code>jsDelivr</code>.</p>
|
||||
<p>The <code>docs</code> directory contains all the necessary html
|
||||
files. They are used in the <a
|
||||
href="https://ToshioCP.github.io/Gtk4-tutorial">GitHub pages</a> of this
|
||||
repository.</p>
|
||||
<p>So if you want to publish this tutorial on your own web site, just
|
||||
upload the files in the <code>docs</code> directory to your site.</p>
|
||||
<h2 id="generate-a-pdf-file">Generate a pdf file</h2>
|
||||
<p>You need pandoc to convert markdown files into latex source files.</p>
|
||||
<p>Type <code>rake pdf</code> to generate latex files and finally make a pdf file.</p>
|
||||
<p>You need pandoc to convert markdown files into latex source
|
||||
files.</p>
|
||||
<p>Type <code>rake pdf</code> to generate latex files and finally make a
|
||||
pdf file.</p>
|
||||
<pre><code>$ rake pdf</code></pre>
|
||||
<p>First, it generates pandoc’s markdown files under <code>latex</code> directory. Then, pandoc converts them into latex files. Links to files or directories are removed because latex doesn’t support them. However, links to full URL and image files are kept. Image size is set with the size between the left brace and right brace.</p>
|
||||
<p>First, it generates pandoc’s markdown files under <code>latex</code>
|
||||
directory. Then, pandoc converts them into latex files. Links to files
|
||||
or directories are removed because latex doesn’t support them. However,
|
||||
links to full URL and image files are kept. Image size is set with the
|
||||
size between the left brace and right brace.</p>
|
||||
<pre><code>![sample image](../image/sample_image.png){width=10cm height=6cm}</code></pre>
|
||||
<p>You need to specify appropriate width and height. It is almost <code>0.015 x pixels</code> cm. For example, if the width of an image is 400 pixels, the width in a latex file will be almost 6cm.</p>
|
||||
<p>A file <code>main.tex</code> is the root file of all the generated latex files. It has <code>\input</code> commands, which inserts each section file, between <code>\begin{document}</code> and <code>\end{document}</code>. It also has <code>\input</code>, which inserts <code>helper.tex</code>, in the preamble. Two files <code>main.tex</code> and <code>helper.tex</code> are created by <code>lib/lib_gen_main_tex.rb</code>. It has a sample markdown code and converts it witn <code>pandoc -s</code>. Then, it extracts the preamble in the generated file and puts it into <code>helper.tex</code>. You can customize <code>helper.tex</code> by modifying <code>lib/lib_gen_main_tex.rb</code>.</p>
|
||||
<p>Finally, lualatex compiles the <code>main.tex</code> into a pdf file.</p>
|
||||
<p>If you want to clean <code>latex</code> directory, type <code>rake clobber</code> or <code>rake cleanlatex</code></p>
|
||||
<p>You need to specify appropriate width and height. It is almost
|
||||
<code>0.015 x pixels</code> cm. For example, if the width of an image is
|
||||
400 pixels, the width in a latex file will be almost 6cm.</p>
|
||||
<p>A file <code>main.tex</code> is the root file of all the generated
|
||||
latex files. It has <code>\input</code> commands, which inserts each
|
||||
section file, between <code>\begin{document}</code> and
|
||||
<code>\end{document}</code>. It also has <code>\input</code>, which
|
||||
inserts <code>helper.tex</code>, in the preamble. Two files
|
||||
<code>main.tex</code> and <code>helper.tex</code> are created by
|
||||
<code>lib/lib_gen_main_tex.rb</code>. It has a sample markdown code and
|
||||
converts it witn <code>pandoc -s</code>. Then, it extracts the preamble
|
||||
in the generated file and puts it into <code>helper.tex</code>. You can
|
||||
customize <code>helper.tex</code> by modifying
|
||||
<code>lib/lib_gen_main_tex.rb</code>.</p>
|
||||
<p>Finally, lualatex compiles the <code>main.tex</code> into a pdf
|
||||
file.</p>
|
||||
<p>If you want to clean <code>latex</code> directory, type
|
||||
<code>rake clobber</code> or <code>rake cleanlatex</code></p>
|
||||
<pre><code>$ rake clobber</code></pre>
|
||||
<p>This removes all the latex source files and a pdf file.</p>
|
||||
</div>
|
||||
|
|
|
@ -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;}
|
||||
|
@ -102,37 +102,74 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 id="gtk4-tutorial-for-beginners">Gtk4 Tutorial for beginners</h1>
|
||||
<h1 id="gtk-4-tutorial-for-beginners">GTK 4 Tutorial for beginners</h1>
|
||||
<h4 id="contents-of-this-repository">Contents of this Repository</h4>
|
||||
<p>This tutorial illustrates how to write C programs with the Gtk4 library. It focuses on beginners so the contents are limited to the basics. The table of contents is at the end of this abstract.</p>
|
||||
<p>This tutorial illustrates how to write C programs with the GTK 4
|
||||
library. It focuses on beginners so the contents are limited to the
|
||||
basics. The table of contents is at the end of this abstract.</p>
|
||||
<ul>
|
||||
<li>Section 3 to 21 describes the basics, with the example of a simple editor <code>tfe</code> (Text File Editor).</li>
|
||||
<li>Section 3 to 21 describes the basics, with the example of a simple
|
||||
editor <code>tfe</code> (Text File Editor).</li>
|
||||
<li>Section 22 to 25 describes GtkDrawingArea.</li>
|
||||
<li>Section 26 to 29 describes the list model and the list view (GtkListView, GtkGridView and GtkColumnView). It also describes GtkExpression.</li>
|
||||
<li>Section 26 to 29 describes the list model and the list view
|
||||
(GtkListView, GtkGridView and GtkColumnView). It also describes
|
||||
GtkExpression.</li>
|
||||
</ul>
|
||||
<p>The latest version of the tutorial is located at <a href="https://github.com/ToshioCP/Gtk4-tutorial">Gtk4-tutorial github repository</a>. You can read it from there directly without having to download anything.</p>
|
||||
<h4 id="gtk4-documentation">Gtk4 Documentation</h4>
|
||||
<p>Please refer to <a href="https://docs.gtk.org/gtk4/index.html">Gtk API Reference</a> and <a href="https://developer.gnome.org/">Gnome Developer Documentation Website</a> for further information.</p>
|
||||
<p>These websites are newly opened lately (Aug/2021). The old documentation is located at <a href="https://developer-old.gnome.org/gtk4/stable/">Gtk Reference Manual</a> and <a href="https://developer-old.gnome.org/">Gnome Developer Center</a>. The new website is in progress at present, so you might need to refer to the old version.</p>
|
||||
<p>If you want to know about GObject and the type system, please refer to <a href="https://github.com/ToshioCP/Gobject-tutorial">GObject tutorial</a>. The GObject details are easy to understand and also necessary to know when writing Gtk4 programs.</p>
|
||||
<p>The latest version of the tutorial is located at <a
|
||||
href="https://github.com/ToshioCP/Gtk4-tutorial">Gtk4-tutorial GitHub
|
||||
repository</a>. You can read it from there directly without having to
|
||||
download anything.</p>
|
||||
<h4 id="gtk-4-documentation">GTK 4 Documentation</h4>
|
||||
<p>Please refer to <a href="https://docs.gtk.org/gtk4/index.html">GTK
|
||||
API Reference</a> and <a href="https://developer.gnome.org/">GNOME
|
||||
Developer Documentation Website</a> for further information.</p>
|
||||
<p>These websites are newly opened lately (Aug/2021). The old
|
||||
documentation is located at <a
|
||||
href="https://developer-old.gnome.org/gtk4/stable/">GTK Reference
|
||||
Manual</a> and <a href="https://developer-old.gnome.org/">GNOME
|
||||
Developer Center</a>. The new website is in progress at present, so you
|
||||
might need to refer to the old version.</p>
|
||||
<p>If you want to know about GObject and the type system, please refer
|
||||
to <a href="https://github.com/ToshioCP/Gobject-tutorial">GObject
|
||||
tutorial</a>. The GObject details are easy to understand and also
|
||||
necessary to know when writing GTK 4 programs.</p>
|
||||
<h4 id="contribution">Contribution</h4>
|
||||
<p>This tutorial is under development and unstable. Even though the codes of the examples have been tested on Gtk4 version 4.0, bugs may still exist. If you find any bugs, errors or mistakes in the tutorial and C examples, please let me know. You can post it to <a href="https://github.com/ToshioCP/Gtk4-tutorial/issues">github issues</a>. You can also post corrected files as a commit to <a href="https://github.com/ToshioCP/Gtk4-tutorial/pulls">pull request</a>. When you make corrections, correct the source files, which are under the ‘src’ directory, then run <code>rake</code> to create to create the output file. The GFM files under the ‘gfm’ directory are automatically updated.</p>
|
||||
<p>If you have a question, feel free to post it as an issue. All questions are helpful and will make this tutorial get better.</p>
|
||||
<h4 id="how-to-get-a-html-or-pdf-version">How to get a HTML or PDF version</h4>
|
||||
<p>If you want to get a HTML or PDF version, you can make them with <code>rake</code>, which is a ruby version of make. Type <code>rake html</code> for HTML. Type <code>rake pdf</code> for PDF. There is a documentation (“<a href="Readme_for_developers.html">How to build Gtk4 Tutorial</a>”) that describes how to make them.</p>
|
||||
<p>This tutorial is under development and unstable. Even though the
|
||||
codes of the examples have been tested on GTK 4 (version 4.0), bugs may
|
||||
still exist. If you find any bugs, errors or mistakes in the tutorial
|
||||
and C examples, please let me know. You can post it to <a
|
||||
href="https://github.com/ToshioCP/Gtk4-tutorial/issues">GitHub
|
||||
issues</a>. You can also post corrected files as a commit to <a
|
||||
href="https://github.com/ToshioCP/Gtk4-tutorial/pulls">pull request</a>.
|
||||
When you make corrections, correct the source files, which are under the
|
||||
‘src’ directory, then run <code>rake</code> to create to create the
|
||||
output file. The GFM files under the ‘gfm’ directory are automatically
|
||||
updated.</p>
|
||||
<p>If you have a question, feel free to post it as an issue. All
|
||||
questions are helpful and will make this tutorial get better.</p>
|
||||
<h4 id="how-to-get-a-html-or-pdf-version">How to get a HTML or PDF
|
||||
version</h4>
|
||||
<p>If you want to get a HTML or PDF version, you can make them with
|
||||
<code>rake</code>, which is a ruby version of make. Type
|
||||
<code>rake html</code> for HTML. Type <code>rake pdf</code> for PDF.
|
||||
There is a documentation (“<a href="Readme_for_developers.html">How to
|
||||
build GTK 4 Tutorial</a>”) that describes how to make them.</p>
|
||||
<h2 id="table-of-contents">Table of contents</h2>
|
||||
<ol type="1">
|
||||
<li><a href="sec1.html">Prerequisite and License</a></li>
|
||||
<li><a href="sec2.html">Installing Gtk4 into Linux distributions</a></li>
|
||||
<li><a href="sec2.html">Installing GTK 4 into Linux
|
||||
distributions</a></li>
|
||||
<li><a href="sec3.html">GtkApplication and GtkApplicationWindow</a></li>
|
||||
<li><a href="sec4.html">Widgets (1)</a></li>
|
||||
<li><a href="sec5.html">Widgets (2)</a></li>
|
||||
<li><a href="sec6.html">String and memory management</a></li>
|
||||
<li><a href="sec7.html">Widgets (3)</a></li>
|
||||
<li><a href="sec8.html">Defining a Child object</a></li>
|
||||
<li><a href="sec9.html">The User Interface (UI) file and GtkBuilder</a></li>
|
||||
<li><a href="sec8.html">Defining a child object</a></li>
|
||||
<li><a href="sec9.html">The User Interface (UI) file and
|
||||
GtkBuilder</a></li>
|
||||
<li><a href="sec10.html">Build system</a></li>
|
||||
<li><a href="sec11.html">Initialization and destruction of instances</a></li>
|
||||
<li><a href="sec11.html">Initialization and destruction of
|
||||
instances</a></li>
|
||||
<li><a href="sec12.html">Signals</a></li>
|
||||
<li><a href="sec13.html">Functions in TfeTextView</a></li>
|
||||
<li><a href="sec14.html">Functions in GtkNotebook</a></li>
|
||||
|
@ -141,7 +178,8 @@
|
|||
<li><a href="sec17.html">Menu and action</a></li>
|
||||
<li><a href="sec18.html">Stateful action</a></li>
|
||||
<li><a href="sec19.html">Ui file for menu and action entries</a></li>
|
||||
<li><a href="sec20.html">GtkMenuButton, accelerators, font, pango and gsettings</a></li>
|
||||
<li><a href="sec20.html">GtkMenuButton, accelerators, font, pango and
|
||||
gsettings</a></li>
|
||||
<li><a href="sec21.html">Template XML and composite widget</a></li>
|
||||
<li><a href="sec22.html">GtkDrawingArea and Cairo</a></li>
|
||||
<li><a href="sec23.html">Periodic Events</a></li>
|
||||
|
@ -152,7 +190,8 @@
|
|||
<li><a href="sec28.html">GtkExpression</a></li>
|
||||
<li><a href="sec29.html">GtkColumnView</a></li>
|
||||
</ol>
|
||||
<p>This website uses <a href="https://getbootstrap.jp/">Bootstrap</a>.</p>
|
||||
<p>This website uses <a
|
||||
href="https://getbootstrap.jp/">Bootstrap</a>.</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>
|
||||
|
|
|
@ -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;}
|
||||
|
@ -110,26 +110,47 @@
|
|||
</nav>
|
||||
<h1 id="prerequisite-and-license">Prerequisite and License</h1>
|
||||
<h2 id="prerequisite">Prerequisite</h2>
|
||||
<h3 id="gtk4-on-a-linux-os">Gtk4 on a Linux OS</h3>
|
||||
<p>This tutorial is about Gtk4 libraries. It is originally used on Linux with C compiler, but now it is used more widely, on Windows and MacOS, with Vala, Python and so on. However, this tutorial describes only <em>C programs on Linux</em>.</p>
|
||||
<h3 id="gtk-4-on-a-linux-os">GTK 4 on a Linux OS</h3>
|
||||
<p>This tutorial is about GTK 4 libraries. It is originally used on
|
||||
Linux with C compiler, but now it is used more widely, on Windows and
|
||||
MacOS, with Vala, Python and so on. However, this tutorial describes
|
||||
only <em>C programs on Linux</em>.</p>
|
||||
<p>If you want to try the examples in the tutorial, you need:</p>
|
||||
<ul>
|
||||
<li>PC with Linux distribution like Ubuntu, Debian and so on.</li>
|
||||
<li>Gcc.</li>
|
||||
<li>Gtk4. The stable version of Gtk on Linux distributions is version three at present. You need to install Gtk4 to your computer. See <a href="sec3.html">Section 3</a> for the installation of Gtk4.</li>
|
||||
<li>GTK 4. The stable version of Gtk on Linux distributions is version
|
||||
three at present. You need to install GTK 4 to your computer. See <a
|
||||
href="sec3.html">Section 3</a> for the installation of GTK 4.</li>
|
||||
</ul>
|
||||
<h3 id="ruby-and-rake-for-making-the-document">Ruby and rake for making the document</h3>
|
||||
<p>This repository includes Ruby programs. They are used to make Markdown files, HTML files, Latex files and a PDF file.</p>
|
||||
<h3 id="ruby-and-rake-for-making-the-document">Ruby and rake for making
|
||||
the document</h3>
|
||||
<p>This repository includes Ruby programs. They are used to make
|
||||
Markdown files, HTML files, Latex files and a PDF file.</p>
|
||||
<p>You need:</p>
|
||||
<ul>
|
||||
<li>Linux distribution like Ubuntu.</li>
|
||||
<li>Ruby programming language. There are two ways to install it. One is installing the distribution’s package. The other is using rbenv and ruby-build. If you want to use the latest version of ruby, use rbenv.</li>
|
||||
<li>Rake. It is a gem, which is a library written in Ruby. You can install it as a package of your distribution or use gem command.</li>
|
||||
<li>Ruby programming language. There are two ways to install it. One is
|
||||
installing the distribution’s package. The other is using rbenv and
|
||||
ruby-build. If you want to use the latest version of ruby, use
|
||||
rbenv.</li>
|
||||
<li>Rake. It is a gem, which is a library written in Ruby. You can
|
||||
install it as a package of your distribution or use gem command.</li>
|
||||
</ul>
|
||||
<h2 id="license">License</h2>
|
||||
<p>Copyright (C) 2020 ToshioCP (Toshio Sekiya)</p>
|
||||
<p>Gtk4 tutorial repository contains the tutorial document and software such as converters, generators and controllers. All of them make up the ‘Gtk4 tutorial’ package. This package is simply called ‘Gtk4 tutorial’ in the following description. ‘Gtk4 tutorial’ is free; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License or, at your option, any later version.</p>
|
||||
<p>‘Gtk4 tutorial’ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the <a href="https://www.gnu.org/licenses/gpl-3.0.html">GNU General Public License</a> for more details.</p>
|
||||
<p>Gtk4-tutorial repository contains the tutorial document and software
|
||||
such as converters, generators and controllers. All of them make up the
|
||||
‘Gtk4-tutorial’ package. This package is simply called ‘Gtk4-tutorial’
|
||||
in the following description. ‘Gtk4-tutorial’ is free; you can
|
||||
redistribute it and/or modify it under the terms of the GNU General
|
||||
Public License as published by the Free Software Foundation; either
|
||||
version 3 of the License or, at your option, any later version.</p>
|
||||
<p>‘Gtk4-tutorial’ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the <a
|
||||
href="https://www.gnu.org/licenses/gpl-3.0.html">GNU General Public
|
||||
License</a> for more details.</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>
|
||||
|
|
619
docs/sec13.html
619
docs/sec13.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;}
|
||||
|
@ -114,313 +114,480 @@
|
|||
<h1 id="functions-in-tfetextview">Functions in TfeTextView</h1>
|
||||
<p>In this section I will explain functions in TfeTextView object.</p>
|
||||
<h2 id="tfe.h-and-tfetextview.h">tfe.h and tfetextview.h</h2>
|
||||
<p><code>tfe.h</code> is a top header file and it includes <code>gtk.h</code> and all the header files. C source files <code>tfeapplication.c</code> and <code>tfenotebook.c</code> include <code>tfe.h</code> at the beginning.</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<p><code>tfe.h</code> is a top header file and it includes
|
||||
<code>gtk.h</code> and all the header files. C source files
|
||||
<code>tfeapplication.c</code> and <code>tfenotebook.c</code> include
|
||||
<code>tfe.h</code> at the beginning.</p>
|
||||
<div class="sourceCode" id="cb1"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2"></a></span>
|
||||
<span id="cb1-3"><a href="#cb1-3"></a><span class="pp">#include </span><span class="im">"../tfetextview/tfetextview.h"</span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4"></a><span class="pp">#include </span><span class="im">"tfenotebook.h"</span></span></code></pre></div>
|
||||
<p><code>../tfetextview/tfetextview.h</code> is a header file which describes the public functions in <code>tfetextview.c</code>.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="pp">#ifndef __TFE_TEXT_VIEW_H__</span></span>
|
||||
<p><code>../tfetextview/tfetextview.h</code> is a header file which
|
||||
describes the public functions in <code>tfetextview.c</code>.</p>
|
||||
<div class="sourceCode" id="cb2"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="pp">#ifndef __TFE_TEXT_VIEW_H__</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2"></a><span class="pp">#define __TFE_TEXT_VIEW_H__</span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3"></a></span>
|
||||
<span id="cb2-4"><a href="#cb2-4"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a></span>
|
||||
<span id="cb2-6"><a href="#cb2-6"></a><span class="pp">#define TFE_TYPE_TEXT_VIEW tfe_text_view_get_type ()</span></span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a>G_DECLARE_FINAL_TYPE (TfeTextView, tfe_text_view, TFE, TEXT_VIEW, GtkTextView)</span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfeTextView<span class="op">,</span> tfe_text_view<span class="op">,</span> TFE<span class="op">,</span> TEXT_VIEW<span class="op">,</span> GtkTextView<span class="op">)</span></span>
|
||||
<span id="cb2-8"><a href="#cb2-8"></a></span>
|
||||
<span id="cb2-9"><a href="#cb2-9"></a><span class="co">/* "open-response" signal response */</span></span>
|
||||
<span id="cb2-10"><a href="#cb2-10"></a><span class="kw">enum</span> TfeTextViewOpenResponseType</span>
|
||||
<span id="cb2-11"><a href="#cb2-11"></a>{</span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> TFE_OPEN_RESPONSE_SUCCESS,</span>
|
||||
<span id="cb2-13"><a href="#cb2-13"></a> TFE_OPEN_RESPONSE_CANCEL,</span>
|
||||
<span id="cb2-11"><a href="#cb2-11"></a><span class="op">{</span></span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> TFE_OPEN_RESPONSE_SUCCESS<span class="op">,</span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13"></a> TFE_OPEN_RESPONSE_CANCEL<span class="op">,</span></span>
|
||||
<span id="cb2-14"><a href="#cb2-14"></a> TFE_OPEN_RESPONSE_ERROR</span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a>};</span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a><span class="op">};</span></span>
|
||||
<span id="cb2-16"><a href="#cb2-16"></a></span>
|
||||
<span id="cb2-17"><a href="#cb2-17"></a>GFile *</span>
|
||||
<span id="cb2-18"><a href="#cb2-18"></a>tfe_text_view_get_file (TfeTextView *tv);</span>
|
||||
<span id="cb2-17"><a href="#cb2-17"></a>GFile <span class="op">*</span></span>
|
||||
<span id="cb2-18"><a href="#cb2-18"></a>tfe_text_view_get_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">);</span></span>
|
||||
<span id="cb2-19"><a href="#cb2-19"></a></span>
|
||||
<span id="cb2-20"><a href="#cb2-20"></a><span class="dt">void</span></span>
|
||||
<span id="cb2-21"><a href="#cb2-21"></a>tfe_text_view_open (TfeTextView *tv, GtkWindow *win);</span>
|
||||
<span id="cb2-21"><a href="#cb2-21"></a>tfe_text_view_open <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">,</span> GtkWindow <span class="op">*</span>win<span class="op">);</span></span>
|
||||
<span id="cb2-22"><a href="#cb2-22"></a></span>
|
||||
<span id="cb2-23"><a href="#cb2-23"></a><span class="dt">void</span></span>
|
||||
<span id="cb2-24"><a href="#cb2-24"></a>tfe_text_view_save (TfeTextView *tv);</span>
|
||||
<span id="cb2-24"><a href="#cb2-24"></a>tfe_text_view_save <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">);</span></span>
|
||||
<span id="cb2-25"><a href="#cb2-25"></a></span>
|
||||
<span id="cb2-26"><a href="#cb2-26"></a><span class="dt">void</span></span>
|
||||
<span id="cb2-27"><a href="#cb2-27"></a>tfe_text_view_saveas (TfeTextView *tv);</span>
|
||||
<span id="cb2-27"><a href="#cb2-27"></a>tfe_text_view_saveas <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">);</span></span>
|
||||
<span id="cb2-28"><a href="#cb2-28"></a></span>
|
||||
<span id="cb2-29"><a href="#cb2-29"></a>GtkWidget *</span>
|
||||
<span id="cb2-30"><a href="#cb2-30"></a>tfe_text_view_new_with_file (GFile *file);</span>
|
||||
<span id="cb2-29"><a href="#cb2-29"></a>GtkWidget <span class="op">*</span></span>
|
||||
<span id="cb2-30"><a href="#cb2-30"></a>tfe_text_view_new_with_file <span class="op">(</span>GFile <span class="op">*</span>file<span class="op">);</span></span>
|
||||
<span id="cb2-31"><a href="#cb2-31"></a></span>
|
||||
<span id="cb2-32"><a href="#cb2-32"></a>GtkWidget *</span>
|
||||
<span id="cb2-33"><a href="#cb2-33"></a>tfe_text_view_new (<span class="dt">void</span>);</span>
|
||||
<span id="cb2-32"><a href="#cb2-32"></a>GtkWidget <span class="op">*</span></span>
|
||||
<span id="cb2-33"><a href="#cb2-33"></a>tfe_text_view_new <span class="op">(</span><span class="dt">void</span><span class="op">);</span></span>
|
||||
<span id="cb2-34"><a href="#cb2-34"></a></span>
|
||||
<span id="cb2-35"><a href="#cb2-35"></a><span class="pp">#endif </span><span class="co">/* __TFE_TEXT_VIEW_H__ */</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>1,2,35: Thanks to these three lines, the following lines are included only once.</li>
|
||||
<li>4: Includes gtk4 header files. The header file <code>gtk4</code> also has the same mechanism to avoid including it multiple times.</li>
|
||||
<li>6-7: These two lines define TfeTextView type, its class structure and some useful macros.</li>
|
||||
<li>9-15: A definition of the value of the parameter of “open-response” signal.</li>
|
||||
<li>1,2,35: Thanks to these three lines, the following lines are
|
||||
included only once.</li>
|
||||
<li>4: Includes gtk4 header files. The header file <code>gtk4</code>
|
||||
also has the same mechanism to avoid including it multiple times.</li>
|
||||
<li>6-7: These two lines define TfeTextView type, its class structure
|
||||
and some useful macros.</li>
|
||||
<li>9-15: A definition of the value of the parameter of “open-response”
|
||||
signal.</li>
|
||||
<li>17-33: Declarations of public functions on TfeTextView.</li>
|
||||
</ul>
|
||||
<h2 id="functions-to-create-tfetextview-instances">Functions to create TfeTextView instances</h2>
|
||||
<p>A TfeTextView instance is created with <code>tfe_text_view_new</code> or <code>tfe_text_view_new_with_file</code>.</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"></a>GtkWidget *tfe_text_view_new (<span class="dt">void</span>);</span></code></pre></div>
|
||||
<p><code>tfe_text_view_new</code> just creates a new TfeTextView instance and returns the pointer to the new instance.</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"></a>GtkWidget *tfe_text_view_new_with_file (GFile *file);</span></code></pre></div>
|
||||
<p><code>tfe_text_view_new_with_file</code> is given a Gfile object as an argument and it loads the file into the GtkTextBuffer instance, then returns the pointer to the new instance. If an error occurs during the creation process, NULL is returned.</p>
|
||||
<h2 id="functions-to-create-tfetextview-instances">Functions to create
|
||||
TfeTextView instances</h2>
|
||||
<p>A TfeTextView instance is created with <code>tfe_text_view_new</code>
|
||||
or <code>tfe_text_view_new_with_file</code>.</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>GtkWidget <span class="op">*</span>tfe_text_view_new <span class="op">(</span><span class="dt">void</span><span class="op">);</span></span></code></pre></div>
|
||||
<p><code>tfe_text_view_new</code> just creates a new TfeTextView
|
||||
instance and returns the pointer to the new instance.</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>GtkWidget <span class="op">*</span>tfe_text_view_new_with_file <span class="op">(</span>GFile <span class="op">*</span>file<span class="op">);</span></span></code></pre></div>
|
||||
<p><code>tfe_text_view_new_with_file</code> is given a Gfile object as
|
||||
an argument and it loads the file into the GtkTextBuffer instance, then
|
||||
returns the pointer to the new instance. If an error occurs during the
|
||||
creation process, NULL is returned.</p>
|
||||
<p>Each function is defined as follows.</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a>GtkWidget *</span>
|
||||
<span id="cb5-2"><a href="#cb5-2"></a>tfe_text_view_new_with_file (GFile *file) {</span>
|
||||
<span id="cb5-3"><a href="#cb5-3"></a> g_return_val_if_fail (G_IS_FILE (file), NULL);</span>
|
||||
<div class="sourceCode" id="cb5"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a>GtkWidget <span class="op">*</span></span>
|
||||
<span id="cb5-2"><a href="#cb5-2"></a>tfe_text_view_new_with_file <span class="op">(</span>GFile <span class="op">*</span>file<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-3"><a href="#cb5-3"></a> g_return_val_if_fail <span class="op">(</span>G_IS_FILE <span class="op">(</span>file<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb5-4"><a href="#cb5-4"></a></span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a> GtkWidget *tv;</span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a> GtkTextBuffer *tb;</span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a> <span class="dt">char</span> *contents;</span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a> gsize length;</span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a> GtkWidget <span class="op">*</span>tv<span class="op">;</span></span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a> GtkTextBuffer <span class="op">*</span>tb<span class="op">;</span></span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a> gsize length<span class="op">;</span></span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></a></span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a> <span class="cf">if</span> (! g_file_load_contents (file, NULL, &contents, &length, NULL, NULL)) <span class="co">/* read error */</span></span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> <span class="cf">return</span> NULL;</span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a> <span class="cf">if</span> <span class="op">(!</span> g_file_load_contents <span class="op">(</span>file<span class="op">,</span> NULL<span class="op">,</span> <span class="op">&</span>contents<span class="op">,</span> <span class="op">&</span>length<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">))</span> <span class="co">/* read error */</span></span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> <span class="cf">return</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb5-12"><a href="#cb5-12"></a></span>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a> <span class="cf">if</span> ((tv = tfe_text_view_new()) != NULL) {</span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a> tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
|
||||
<span id="cb5-15"><a href="#cb5-15"></a> gtk_text_buffer_set_text (tb, contents, length);</span>
|
||||
<span id="cb5-16"><a href="#cb5-16"></a> TFE_TEXT_VIEW (tv)->file = g_file_dup (file);</span>
|
||||
<span id="cb5-17"><a href="#cb5-17"></a> gtk_text_buffer_set_modified (tb, FALSE);</span>
|
||||
<span id="cb5-18"><a href="#cb5-18"></a> }</span>
|
||||
<span id="cb5-19"><a href="#cb5-19"></a> g_free (contents);</span>
|
||||
<span id="cb5-20"><a href="#cb5-20"></a> <span class="cf">return</span> tv;</span>
|
||||
<span id="cb5-21"><a href="#cb5-21"></a>}</span>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a> <span class="cf">if</span> <span class="op">((</span>tv <span class="op">=</span> tfe_text_view_new<span class="op">())</span> <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a> tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb5-15"><a href="#cb5-15"></a> gtk_text_buffer_set_text <span class="op">(</span>tb<span class="op">,</span> contents<span class="op">,</span> length<span class="op">);</span></span>
|
||||
<span id="cb5-16"><a href="#cb5-16"></a> TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">)-></span>file <span class="op">=</span> g_file_dup <span class="op">(</span>file<span class="op">);</span></span>
|
||||
<span id="cb5-17"><a href="#cb5-17"></a> gtk_text_buffer_set_modified <span class="op">(</span>tb<span class="op">,</span> FALSE<span class="op">);</span></span>
|
||||
<span id="cb5-18"><a href="#cb5-18"></a> <span class="op">}</span></span>
|
||||
<span id="cb5-19"><a href="#cb5-19"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span>
|
||||
<span id="cb5-20"><a href="#cb5-20"></a> <span class="cf">return</span> tv<span class="op">;</span></span>
|
||||
<span id="cb5-21"><a href="#cb5-21"></a><span class="op">}</span></span>
|
||||
<span id="cb5-22"><a href="#cb5-22"></a></span>
|
||||
<span id="cb5-23"><a href="#cb5-23"></a>GtkWidget *</span>
|
||||
<span id="cb5-24"><a href="#cb5-24"></a>tfe_text_view_new (<span class="dt">void</span>) {</span>
|
||||
<span id="cb5-25"><a href="#cb5-25"></a> <span class="cf">return</span> GTK_WIDGET (g_object_new (TFE_TYPE_TEXT_VIEW, NULL));</span>
|
||||
<span id="cb5-26"><a href="#cb5-26"></a>}</span></code></pre></div>
|
||||
<span id="cb5-23"><a href="#cb5-23"></a>GtkWidget <span class="op">*</span></span>
|
||||
<span id="cb5-24"><a href="#cb5-24"></a>tfe_text_view_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-25"><a href="#cb5-25"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_TEXT_VIEW<span class="op">,</span> NULL<span class="op">));</span></span>
|
||||
<span id="cb5-26"><a href="#cb5-26"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>23-25: <code>tfe_text_view_new</code> function. Just returns the value from the function <code>g_object_new</code> but casts it to the pointer to GtkWidget. Initialization is done in <code>tfe_text_view_init</code> which is called in the process of <code>g_object_new</code> function.</li>
|
||||
<li>23-25: <code>tfe_text_view_new</code> function. Just returns the
|
||||
value from the function <code>g_object_new</code> but casts it to the
|
||||
pointer to GtkWidget. Initialization is done in
|
||||
<code>tfe_text_view_init</code> which is called in the process of
|
||||
<code>g_object_new</code> function.</li>
|
||||
<li>1-21: <code>tfe_text_view_new_with_file</code> function.</li>
|
||||
<li>3: <code>g_return_val_if_fail</code> is described in <a href="https://docs.gtk.org/glib/func.return_val_if_fail.html">GLib API Reference, g_return_val_if_fail</a>. And also <a href="https://docs.gtk.org/glib/logging.html">GLib API Reference, Message Logging</a>. It tests whether the argument <code>file</code> is a pointer to GFile. If it’s true, then the program goes on to the next line. If it’s false, then it returns NULL (the second argument) immediately. And at the same time it logs out the error message (usually the log is outputted to stderr or stdout). This function is used to check the programmer’s error. If an error occurs, the solution is usually to change the (caller) program and fix the bug. You need to distinguish programmer’s errors and runtime errors. You shouldn’t use this function to find runtime errors.</li>
|
||||
<li>10-11: If an error occurs when reading the file, then the function returns NULL.</li>
|
||||
<li>13: Calls the function <code>tfe_text_view_new</code>. The function creates TfeTextView instance and returns the pointer to the instance. If an error happens in <code>tfe_text_view_new</code>, it returns NULL.</li>
|
||||
<li>14: Gets the pointer to GtkTextBuffer corresponds to <code>tv</code>. The pointer is assigned to <code>tb</code></li>
|
||||
<li>15: Assigns the contents read from the file to GtkTextBuffer pointed by <code>tb</code>.</li>
|
||||
<li>16: Duplicates <code>file</code> and sets <code>tv->file</code> to point it.</li>
|
||||
<li>17: The function <code>gtk_text_buffer_set_modified (tb, FALSE)</code> sets the modification flag of <code>tb</code> to FALSE. The modification flag indicates that the contents of the buffer has been modified. It is used when the contents are saved. If the modification flag is FALSE, it doesn’t need to save the contents.</li>
|
||||
<li>3: <code>g_return_val_if_fail</code> is described in <a
|
||||
href="https://docs.gtk.org/glib/func.return_val_if_fail.html">GLib API
|
||||
Reference, g_return_val_if_fail</a>. And also <a
|
||||
href="https://docs.gtk.org/glib/logging.html">GLib API Reference,
|
||||
Message Logging</a>. It tests whether the argument <code>file</code> is
|
||||
a pointer to GFile. If it’s true, then the program goes on to the next
|
||||
line. If it’s false, then it returns NULL (the second argument)
|
||||
immediately. And at the same time it logs out the error message (usually
|
||||
the log is outputted to stderr or stdout). This function is used to
|
||||
check the programmer’s error. If an error occurs, the solution is
|
||||
usually to change the (caller) program and fix the bug. You need to
|
||||
distinguish programmer’s errors and runtime errors. You shouldn’t use
|
||||
this function to find runtime errors.</li>
|
||||
<li>10-11: If an error occurs when reading the file, then the function
|
||||
returns NULL.</li>
|
||||
<li>13: Calls the function <code>tfe_text_view_new</code>. The function
|
||||
creates TfeTextView instance and returns the pointer to the instance. If
|
||||
an error happens in <code>tfe_text_view_new</code>, it returns
|
||||
NULL.</li>
|
||||
<li>14: Gets the pointer to GtkTextBuffer corresponds to
|
||||
<code>tv</code>. The pointer is assigned to <code>tb</code></li>
|
||||
<li>15: Assigns the contents read from the file to GtkTextBuffer pointed
|
||||
by <code>tb</code>.</li>
|
||||
<li>16: Duplicates <code>file</code> and sets <code>tv->file</code>
|
||||
to point it.</li>
|
||||
<li>17: The function
|
||||
<code>gtk_text_buffer_set_modified (tb, FALSE)</code> sets the
|
||||
modification flag of <code>tb</code> to FALSE. The modification flag
|
||||
indicates that the contents of the buffer has been modified. It is used
|
||||
when the contents are saved. If the modification flag is FALSE, it
|
||||
doesn’t need to save the contents.</li>
|
||||
<li>19: Frees the memories pointed by <code>contents</code>.</li>
|
||||
<li>20: Returns <code>tv</code>, which is a pointer to the newly created TfeTextView instance. If an error happens, NULL is returned.</li>
|
||||
<li>20: Returns <code>tv</code>, which is a pointer to the newly created
|
||||
TfeTextView instance. If an error happens, NULL is returned.</li>
|
||||
</ul>
|
||||
<h2 id="save-and-saveas-functions">Save and saveas functions</h2>
|
||||
<p>Save and saveas functions write the contents in the GtkTextBuffer to a file.</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"></a><span class="dt">void</span> tfe_text_view_save (TfeTextView *tv)</span></code></pre></div>
|
||||
<p>The function <code>tfe_text_view_save</code> writes the contents in the GtkTextBuffer to a file specified by <code>tv->file</code>. If <code>tv->file</code> is NULL, then it shows GtkFileChooserDialog and prompts the user to choose a file to save. Then it saves the contents to the file and sets <code>tv->file</code> to point the GFile instance for the file.</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"></a><span class="dt">void</span> tfe_text_view_saveas (TfeTextView *tv)</span></code></pre></div>
|
||||
<p>The function <code>saveas</code> uses GtkFileChooserDialog and prompts the user to select a existed file or specify a new file to save. Then, the function changes <code>tv->file</code> and save the contents to the specified file. If an error occurs, it is shown to the user through the message dialog. The error is managed only in the TfeTextView and no information is notified to the caller.</p>
|
||||
<div class="sourceCode" id="cb8"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a><span class="dt">static</span> gboolean</span>
|
||||
<span id="cb8-2"><a href="#cb8-2"></a>save_file (GFile *file, GtkTextBuffer *tb, GtkWindow *win) {</span>
|
||||
<span id="cb8-3"><a href="#cb8-3"></a> GtkTextIter start_iter;</span>
|
||||
<span id="cb8-4"><a href="#cb8-4"></a> GtkTextIter end_iter;</span>
|
||||
<span id="cb8-5"><a href="#cb8-5"></a> gchar *contents;</span>
|
||||
<span id="cb8-6"><a href="#cb8-6"></a> gboolean stat;</span>
|
||||
<span id="cb8-7"><a href="#cb8-7"></a> GtkWidget *message_dialog;</span>
|
||||
<span id="cb8-8"><a href="#cb8-8"></a> GError *err = NULL;</span>
|
||||
<p>Save and saveas functions write the contents in the GtkTextBuffer to
|
||||
a file.</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">void</span> tfe_text_view_save <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span></span></code></pre></div>
|
||||
<p>The function <code>tfe_text_view_save</code> writes the contents in
|
||||
the GtkTextBuffer to a file specified by <code>tv->file</code>. If
|
||||
<code>tv->file</code> is NULL, then it shows GtkFileChooserDialog and
|
||||
prompts the user to choose a file to save. Then it saves the contents to
|
||||
the file and sets <code>tv->file</code> to point the GFile instance
|
||||
for the file.</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="dt">void</span> tfe_text_view_saveas <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span></span></code></pre></div>
|
||||
<p>The function <code>saveas</code> uses GtkFileChooserDialog and
|
||||
prompts the user to select a existed file or specify a new file to save.
|
||||
Then, the function changes <code>tv->file</code> and save the
|
||||
contents to the specified file. If an error occurs, it is shown to the
|
||||
user through the message dialog. The error is managed only in the
|
||||
TfeTextView and no information is notified to the caller.</p>
|
||||
<div class="sourceCode" id="cb8"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a><span class="dt">static</span> gboolean</span>
|
||||
<span id="cb8-2"><a href="#cb8-2"></a>save_file <span class="op">(</span>GFile <span class="op">*</span>file<span class="op">,</span> GtkTextBuffer <span class="op">*</span>tb<span class="op">,</span> GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb8-3"><a href="#cb8-3"></a> GtkTextIter start_iter<span class="op">;</span></span>
|
||||
<span id="cb8-4"><a href="#cb8-4"></a> GtkTextIter end_iter<span class="op">;</span></span>
|
||||
<span id="cb8-5"><a href="#cb8-5"></a> gchar <span class="op">*</span>contents<span class="op">;</span></span>
|
||||
<span id="cb8-6"><a href="#cb8-6"></a> gboolean stat<span class="op">;</span></span>
|
||||
<span id="cb8-7"><a href="#cb8-7"></a> GtkWidget <span class="op">*</span>message_dialog<span class="op">;</span></span>
|
||||
<span id="cb8-8"><a href="#cb8-8"></a> GError <span class="op">*</span>err <span class="op">=</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb8-9"><a href="#cb8-9"></a></span>
|
||||
<span id="cb8-10"><a href="#cb8-10"></a> gtk_text_buffer_get_bounds (tb, &start_iter, &end_iter);</span>
|
||||
<span id="cb8-11"><a href="#cb8-11"></a> contents = gtk_text_buffer_get_text (tb, &start_iter, &end_iter, FALSE);</span>
|
||||
<span id="cb8-12"><a href="#cb8-12"></a> <span class="cf">if</span> (g_file_replace_contents (file, contents, strlen (contents), NULL, TRUE, G_FILE_CREATE_NONE, NULL, NULL, &err)) {</span>
|
||||
<span id="cb8-13"><a href="#cb8-13"></a> gtk_text_buffer_set_modified (tb, FALSE);</span>
|
||||
<span id="cb8-14"><a href="#cb8-14"></a> stat = TRUE;</span>
|
||||
<span id="cb8-15"><a href="#cb8-15"></a> } <span class="cf">else</span> {</span>
|
||||
<span id="cb8-16"><a href="#cb8-16"></a> message_dialog = gtk_message_dialog_new (win, GTK_DIALOG_MODAL,</span>
|
||||
<span id="cb8-17"><a href="#cb8-17"></a> GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,</span>
|
||||
<span id="cb8-18"><a href="#cb8-18"></a> <span class="st">"%s.</span><span class="sc">\n</span><span class="st">"</span>, err->message);</span>
|
||||
<span id="cb8-19"><a href="#cb8-19"></a> g_signal_connect (message_dialog, <span class="st">"response"</span>, G_CALLBACK (gtk_window_destroy), NULL);</span>
|
||||
<span id="cb8-20"><a href="#cb8-20"></a> gtk_widget_show (message_dialog);</span>
|
||||
<span id="cb8-21"><a href="#cb8-21"></a> g_error_free (err);</span>
|
||||
<span id="cb8-22"><a href="#cb8-22"></a> stat = FALSE;</span>
|
||||
<span id="cb8-23"><a href="#cb8-23"></a> }</span>
|
||||
<span id="cb8-24"><a href="#cb8-24"></a> g_free (contents);</span>
|
||||
<span id="cb8-25"><a href="#cb8-25"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb8-26"><a href="#cb8-26"></a>}</span>
|
||||
<span id="cb8-10"><a href="#cb8-10"></a> gtk_text_buffer_get_bounds <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">);</span></span>
|
||||
<span id="cb8-11"><a href="#cb8-11"></a> contents <span class="op">=</span> gtk_text_buffer_get_text <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">,</span> FALSE<span class="op">);</span></span>
|
||||
<span id="cb8-12"><a href="#cb8-12"></a> <span class="cf">if</span> <span class="op">(</span>g_file_replace_contents <span class="op">(</span>file<span class="op">,</span> contents<span class="op">,</span> strlen <span class="op">(</span>contents<span class="op">),</span> NULL<span class="op">,</span> TRUE<span class="op">,</span> G_FILE_CREATE_NONE<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> <span class="op">&</span>err<span class="op">))</span> <span class="op">{</span></span>
|
||||
<span id="cb8-13"><a href="#cb8-13"></a> gtk_text_buffer_set_modified <span class="op">(</span>tb<span class="op">,</span> FALSE<span class="op">);</span></span>
|
||||
<span id="cb8-14"><a href="#cb8-14"></a> stat <span class="op">=</span> TRUE<span class="op">;</span></span>
|
||||
<span id="cb8-15"><a href="#cb8-15"></a> <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
|
||||
<span id="cb8-16"><a href="#cb8-16"></a> message_dialog <span class="op">=</span> gtk_message_dialog_new <span class="op">(</span>win<span class="op">,</span> GTK_DIALOG_MODAL<span class="op">,</span></span>
|
||||
<span id="cb8-17"><a href="#cb8-17"></a> GTK_MESSAGE_ERROR<span class="op">,</span> GTK_BUTTONS_CLOSE<span class="op">,</span></span>
|
||||
<span id="cb8-18"><a href="#cb8-18"></a> <span class="st">"%s.</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> err<span class="op">-></span>message<span class="op">);</span></span>
|
||||
<span id="cb8-19"><a href="#cb8-19"></a> g_signal_connect <span class="op">(</span>message_dialog<span class="op">,</span> <span class="st">"response"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>gtk_window_destroy<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb8-20"><a href="#cb8-20"></a> gtk_widget_show <span class="op">(</span>message_dialog<span class="op">);</span></span>
|
||||
<span id="cb8-21"><a href="#cb8-21"></a> g_error_free <span class="op">(</span>err<span class="op">);</span></span>
|
||||
<span id="cb8-22"><a href="#cb8-22"></a> stat <span class="op">=</span> FALSE<span class="op">;</span></span>
|
||||
<span id="cb8-23"><a href="#cb8-23"></a> <span class="op">}</span></span>
|
||||
<span id="cb8-24"><a href="#cb8-24"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span>
|
||||
<span id="cb8-25"><a href="#cb8-25"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb8-26"><a href="#cb8-26"></a><span class="op">}</span></span>
|
||||
<span id="cb8-27"><a href="#cb8-27"></a></span>
|
||||
<span id="cb8-28"><a href="#cb8-28"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb8-29"><a href="#cb8-29"></a>saveas_dialog_response (GtkWidget *dialog, gint response, TfeTextView *tv) {</span>
|
||||
<span id="cb8-30"><a href="#cb8-30"></a> GtkTextBuffer *tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
|
||||
<span id="cb8-31"><a href="#cb8-31"></a> GFile *file;</span>
|
||||
<span id="cb8-32"><a href="#cb8-32"></a> GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (tv), GTK_TYPE_WINDOW);</span>
|
||||
<span id="cb8-29"><a href="#cb8-29"></a>saveas_dialog_response <span class="op">(</span>GtkWidget <span class="op">*</span>dialog<span class="op">,</span> gint response<span class="op">,</span> TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb8-30"><a href="#cb8-30"></a> GtkTextBuffer <span class="op">*</span>tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb8-31"><a href="#cb8-31"></a> GFile <span class="op">*</span>file<span class="op">;</span></span>
|
||||
<span id="cb8-32"><a href="#cb8-32"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> gtk_widget_get_ancestor <span class="op">(</span>GTK_WIDGET <span class="op">(</span>tv<span class="op">),</span> GTK_TYPE_WINDOW<span class="op">);</span></span>
|
||||
<span id="cb8-33"><a href="#cb8-33"></a></span>
|
||||
<span id="cb8-34"><a href="#cb8-34"></a> <span class="cf">if</span> (response == GTK_RESPONSE_ACCEPT) {</span>
|
||||
<span id="cb8-35"><a href="#cb8-35"></a> file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));</span>
|
||||
<span id="cb8-36"><a href="#cb8-36"></a> <span class="cf">if</span> (! G_IS_FILE (file))</span>
|
||||
<span id="cb8-37"><a href="#cb8-37"></a> g_warning (<span class="st">"TfeTextView: gtk_file_chooser_get_file returns non GFile.</span><span class="sc">\n</span><span class="st">"</span>);</span>
|
||||
<span id="cb8-38"><a href="#cb8-38"></a> <span class="cf">else</span> <span class="cf">if</span> (save_file(file, tb, GTK_WINDOW (win))) {</span>
|
||||
<span id="cb8-39"><a href="#cb8-39"></a> <span class="cf">if</span> (G_IS_FILE (tv->file))</span>
|
||||
<span id="cb8-40"><a href="#cb8-40"></a> g_object_unref (tv->file);</span>
|
||||
<span id="cb8-41"><a href="#cb8-41"></a> tv->file = file;</span>
|
||||
<span id="cb8-42"><a href="#cb8-42"></a> g_signal_emit (tv, tfe_text_view_signals[CHANGE_FILE], <span class="dv">0</span>);</span>
|
||||
<span id="cb8-43"><a href="#cb8-43"></a> } <span class="cf">else</span></span>
|
||||
<span id="cb8-44"><a href="#cb8-44"></a> g_object_unref (file);</span>
|
||||
<span id="cb8-45"><a href="#cb8-45"></a> }</span>
|
||||
<span id="cb8-46"><a href="#cb8-46"></a> gtk_window_destroy (GTK_WINDOW (dialog));</span>
|
||||
<span id="cb8-47"><a href="#cb8-47"></a>}</span>
|
||||
<span id="cb8-34"><a href="#cb8-34"></a> <span class="cf">if</span> <span class="op">(</span>response <span class="op">==</span> GTK_RESPONSE_ACCEPT<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb8-35"><a href="#cb8-35"></a> file <span class="op">=</span> gtk_file_chooser_get_file <span class="op">(</span>GTK_FILE_CHOOSER <span class="op">(</span>dialog<span class="op">));</span></span>
|
||||
<span id="cb8-36"><a href="#cb8-36"></a> <span class="cf">if</span> <span class="op">(!</span> G_IS_FILE <span class="op">(</span>file<span class="op">))</span></span>
|
||||
<span id="cb8-37"><a href="#cb8-37"></a> g_warning <span class="op">(</span><span class="st">"TfeTextView: gtk_file_chooser_get_file returns non GFile.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||
<span id="cb8-38"><a href="#cb8-38"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>save_file<span class="op">(</span>file<span class="op">,</span> tb<span class="op">,</span> GTK_WINDOW <span class="op">(</span>win<span class="op">)))</span> <span class="op">{</span></span>
|
||||
<span id="cb8-39"><a href="#cb8-39"></a> <span class="cf">if</span> <span class="op">(</span>G_IS_FILE <span class="op">(</span>tv<span class="op">-></span>file<span class="op">))</span></span>
|
||||
<span id="cb8-40"><a href="#cb8-40"></a> g_object_unref <span class="op">(</span>tv<span class="op">-></span>file<span class="op">);</span></span>
|
||||
<span id="cb8-41"><a href="#cb8-41"></a> tv<span class="op">-></span>file <span class="op">=</span> file<span class="op">;</span></span>
|
||||
<span id="cb8-42"><a href="#cb8-42"></a> g_signal_emit <span class="op">(</span>tv<span class="op">,</span> tfe_text_view_signals<span class="op">[</span>CHANGE_FILE<span class="op">],</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||
<span id="cb8-43"><a href="#cb8-43"></a> <span class="op">}</span> <span class="cf">else</span></span>
|
||||
<span id="cb8-44"><a href="#cb8-44"></a> g_object_unref <span class="op">(</span>file<span class="op">);</span></span>
|
||||
<span id="cb8-45"><a href="#cb8-45"></a> <span class="op">}</span></span>
|
||||
<span id="cb8-46"><a href="#cb8-46"></a> gtk_window_destroy <span class="op">(</span>GTK_WINDOW <span class="op">(</span>dialog<span class="op">));</span></span>
|
||||
<span id="cb8-47"><a href="#cb8-47"></a><span class="op">}</span></span>
|
||||
<span id="cb8-48"><a href="#cb8-48"></a></span>
|
||||
<span id="cb8-49"><a href="#cb8-49"></a><span class="dt">void</span></span>
|
||||
<span id="cb8-50"><a href="#cb8-50"></a>tfe_text_view_save (TfeTextView *tv) {</span>
|
||||
<span id="cb8-51"><a href="#cb8-51"></a> g_return_if_fail (TFE_IS_TEXT_VIEW (tv));</span>
|
||||
<span id="cb8-50"><a href="#cb8-50"></a>tfe_text_view_save <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb8-51"><a href="#cb8-51"></a> g_return_if_fail <span class="op">(</span>TFE_IS_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb8-52"><a href="#cb8-52"></a></span>
|
||||
<span id="cb8-53"><a href="#cb8-53"></a> GtkTextBuffer *tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
|
||||
<span id="cb8-54"><a href="#cb8-54"></a> GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (tv), GTK_TYPE_WINDOW);</span>
|
||||
<span id="cb8-53"><a href="#cb8-53"></a> GtkTextBuffer <span class="op">*</span>tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb8-54"><a href="#cb8-54"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> gtk_widget_get_ancestor <span class="op">(</span>GTK_WIDGET <span class="op">(</span>tv<span class="op">),</span> GTK_TYPE_WINDOW<span class="op">);</span></span>
|
||||
<span id="cb8-55"><a href="#cb8-55"></a></span>
|
||||
<span id="cb8-56"><a href="#cb8-56"></a> <span class="cf">if</span> (! gtk_text_buffer_get_modified (tb))</span>
|
||||
<span id="cb8-57"><a href="#cb8-57"></a> <span class="cf">return</span>; <span class="co">/* no need to save it */</span></span>
|
||||
<span id="cb8-58"><a href="#cb8-58"></a> <span class="cf">else</span> <span class="cf">if</span> (tv->file == NULL)</span>
|
||||
<span id="cb8-59"><a href="#cb8-59"></a> tfe_text_view_saveas (tv);</span>
|
||||
<span id="cb8-60"><a href="#cb8-60"></a> <span class="cf">else</span> <span class="cf">if</span> (! G_IS_FILE (tv->file))</span>
|
||||
<span id="cb8-61"><a href="#cb8-61"></a> g_error (<span class="st">"TfeTextView: The pointer tv->file isn't NULL nor GFile.</span><span class="sc">\n</span><span class="st">"</span>);</span>
|
||||
<span id="cb8-56"><a href="#cb8-56"></a> <span class="cf">if</span> <span class="op">(!</span> gtk_text_buffer_get_modified <span class="op">(</span>tb<span class="op">))</span></span>
|
||||
<span id="cb8-57"><a href="#cb8-57"></a> <span class="cf">return</span><span class="op">;</span> <span class="co">/* no need to save it */</span></span>
|
||||
<span id="cb8-58"><a href="#cb8-58"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>tv<span class="op">-></span>file <span class="op">==</span> NULL<span class="op">)</span></span>
|
||||
<span id="cb8-59"><a href="#cb8-59"></a> tfe_text_view_saveas <span class="op">(</span>tv<span class="op">);</span></span>
|
||||
<span id="cb8-60"><a href="#cb8-60"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span> G_IS_FILE <span class="op">(</span>tv<span class="op">-></span>file<span class="op">))</span></span>
|
||||
<span id="cb8-61"><a href="#cb8-61"></a> g_error <span class="op">(</span><span class="st">"TfeTextView: The pointer tv->file isn't NULL nor GFile.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||
<span id="cb8-62"><a href="#cb8-62"></a> <span class="cf">else</span></span>
|
||||
<span id="cb8-63"><a href="#cb8-63"></a> save_file (tv->file, tb, GTK_WINDOW (win));</span>
|
||||
<span id="cb8-64"><a href="#cb8-64"></a>}</span>
|
||||
<span id="cb8-63"><a href="#cb8-63"></a> save_file <span class="op">(</span>tv<span class="op">-></span>file<span class="op">,</span> tb<span class="op">,</span> GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb8-64"><a href="#cb8-64"></a><span class="op">}</span></span>
|
||||
<span id="cb8-65"><a href="#cb8-65"></a></span>
|
||||
<span id="cb8-66"><a href="#cb8-66"></a><span class="dt">void</span></span>
|
||||
<span id="cb8-67"><a href="#cb8-67"></a>tfe_text_view_saveas (TfeTextView *tv) {</span>
|
||||
<span id="cb8-68"><a href="#cb8-68"></a> g_return_if_fail (TFE_IS_TEXT_VIEW (tv));</span>
|
||||
<span id="cb8-67"><a href="#cb8-67"></a>tfe_text_view_saveas <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb8-68"><a href="#cb8-68"></a> g_return_if_fail <span class="op">(</span>TFE_IS_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb8-69"><a href="#cb8-69"></a></span>
|
||||
<span id="cb8-70"><a href="#cb8-70"></a> GtkWidget *dialog;</span>
|
||||
<span id="cb8-71"><a href="#cb8-71"></a> GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (tv), GTK_TYPE_WINDOW);</span>
|
||||
<span id="cb8-70"><a href="#cb8-70"></a> GtkWidget <span class="op">*</span>dialog<span class="op">;</span></span>
|
||||
<span id="cb8-71"><a href="#cb8-71"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> gtk_widget_get_ancestor <span class="op">(</span>GTK_WIDGET <span class="op">(</span>tv<span class="op">),</span> GTK_TYPE_WINDOW<span class="op">);</span></span>
|
||||
<span id="cb8-72"><a href="#cb8-72"></a></span>
|
||||
<span id="cb8-73"><a href="#cb8-73"></a> dialog = gtk_file_chooser_dialog_new (<span class="st">"Save file"</span>, GTK_WINDOW (win), GTK_FILE_CHOOSER_ACTION_SAVE,</span>
|
||||
<span id="cb8-74"><a href="#cb8-74"></a> <span class="st">"Cancel"</span>, GTK_RESPONSE_CANCEL,</span>
|
||||
<span id="cb8-75"><a href="#cb8-75"></a> <span class="st">"Save"</span>, GTK_RESPONSE_ACCEPT,</span>
|
||||
<span id="cb8-76"><a href="#cb8-76"></a> NULL);</span>
|
||||
<span id="cb8-77"><a href="#cb8-77"></a> g_signal_connect (dialog, <span class="st">"response"</span>, G_CALLBACK (saveas_dialog_response), tv);</span>
|
||||
<span id="cb8-78"><a href="#cb8-78"></a> gtk_widget_show (dialog);</span>
|
||||
<span id="cb8-79"><a href="#cb8-79"></a>}</span></code></pre></div>
|
||||
<span id="cb8-73"><a href="#cb8-73"></a> dialog <span class="op">=</span> gtk_file_chooser_dialog_new <span class="op">(</span><span class="st">"Save file"</span><span class="op">,</span> GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> GTK_FILE_CHOOSER_ACTION_SAVE<span class="op">,</span></span>
|
||||
<span id="cb8-74"><a href="#cb8-74"></a> <span class="st">"Cancel"</span><span class="op">,</span> GTK_RESPONSE_CANCEL<span class="op">,</span></span>
|
||||
<span id="cb8-75"><a href="#cb8-75"></a> <span class="st">"Save"</span><span class="op">,</span> GTK_RESPONSE_ACCEPT<span class="op">,</span></span>
|
||||
<span id="cb8-76"><a href="#cb8-76"></a> NULL<span class="op">);</span></span>
|
||||
<span id="cb8-77"><a href="#cb8-77"></a> g_signal_connect <span class="op">(</span>dialog<span class="op">,</span> <span class="st">"response"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>saveas_dialog_response<span class="op">),</span> tv<span class="op">);</span></span>
|
||||
<span id="cb8-78"><a href="#cb8-78"></a> gtk_widget_show <span class="op">(</span>dialog<span class="op">);</span></span>
|
||||
<span id="cb8-79"><a href="#cb8-79"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>1-26: <code>save_file</code> function. This function is called from <code>saveas_dialog_response</code> and <code>tfe_text_view_save</code>. This function saves the contents of the buffer to the file given as an argument. If error happens, it displays an error message. The class of this function is <code>static</code>. Therefore, only functions in this file (<code>tfeTetview.c</code>) call this function. Such static functions usally don’t have <code>g_return_val_if_fail</code> function.</li>
|
||||
<li>1-26: <code>save_file</code> function. This function is called from
|
||||
<code>saveas_dialog_response</code> and <code>tfe_text_view_save</code>.
|
||||
This function saves the contents of the buffer to the file given as an
|
||||
argument. If error happens, it displays an error message. The class of
|
||||
this function is <code>static</code>. Therefore, only functions in this
|
||||
file (<code>tfeTetview.c</code>) call this function. Such static
|
||||
functions usally don’t have <code>g_return_val_if_fail</code>
|
||||
function.</li>
|
||||
<li>10-11: Gets the text contents from the buffer.</li>
|
||||
<li>12-14: Saves the contents to the file. If no error happens, set the modified flag to be FALSE. This means that the buffer is not modified since it has been saved. And set the return status <code>stat</code> to be TRUE.</li>
|
||||
<li>15-23: If it fails to save the contents, displays an error message.</li>
|
||||
<li>12-14: Saves the contents to the file. If no error happens, set the
|
||||
modified flag to be FALSE. This means that the buffer is not modified
|
||||
since it has been saved. And set the return status <code>stat</code> to
|
||||
be TRUE.</li>
|
||||
<li>15-23: If it fails to save the contents, displays an error
|
||||
message.</li>
|
||||
<li>16-18: Creates a message dialog with the error message.</li>
|
||||
<li>19: Connects the “response” signal to <code>gtk_window_destroy</code>, so that the dialog disappears when a user clicked on the button.</li>
|
||||
<li>20-21: Shows the window, frees <code>err</code> and set <code>stat</code> to be FLASE.</li>
|
||||
<li>19: Connects the “response” signal to
|
||||
<code>gtk_window_destroy</code>, so that the dialog disappears when a
|
||||
user clicked on the button.</li>
|
||||
<li>20-21: Shows the window, frees <code>err</code> and set
|
||||
<code>stat</code> to be FLASE.</li>
|
||||
<li>24: Frees <code>contents</code>.</li>
|
||||
<li>25: Returns to the caller.</li>
|
||||
<li>28-47: <code>saveas_dialog_response</code> function. This is a signal handler for the “response” signal on GtkFileChooserDialog instance created by <code>tfe_text_view_saveas</code> function. This handler analyzes the response and determines whether to save the contents.</li>
|
||||
<li>34-45: If the response is <code>GTK_RESPONSE_ACCEPT</code>, the user has clicked on the <code>Save</code> button. So, it tries to save.</li>
|
||||
<li>28-47: <code>saveas_dialog_response</code> function. This is a
|
||||
signal handler for the “response” signal on GtkFileChooserDialog
|
||||
instance created by <code>tfe_text_view_saveas</code> function. This
|
||||
handler analyzes the response and determines whether to save the
|
||||
contents.</li>
|
||||
<li>34-45: If the response is <code>GTK_RESPONSE_ACCEPT</code>, the user
|
||||
has clicked on the <code>Save</code> button. So, it tries to save.</li>
|
||||
<li>35: Gets the GFile <code>file</code> from GtkFileChooserDialog.</li>
|
||||
<li>36-37: If it doesn’t point GFile, it outputs an error message to the log.</li>
|
||||
<li>38: Otherwise, it calls <code>save_file</code> to save the contents to the file.</li>
|
||||
<li>39-42: If <code>save_file</code> has successfully saved the contents, <code>tv->file</code> is updated. If the old GFile pointed by <code>tv->file</code> exists, it is freed in advance. Emits “change-file” signal.</li>
|
||||
<li>36-37: If it doesn’t point GFile, it outputs an error message to the
|
||||
log.</li>
|
||||
<li>38: Otherwise, it calls <code>save_file</code> to save the contents
|
||||
to the file.</li>
|
||||
<li>39-42: If <code>save_file</code> has successfully saved the
|
||||
contents, <code>tv->file</code> is updated. If the old GFile pointed
|
||||
by <code>tv->file</code> exists, it is freed in advance. Emits
|
||||
“change-file” signal.</li>
|
||||
<li>44: Unrefs <code>file</code>.</li>
|
||||
<li>46: destroys the file chooser dialog.</li>
|
||||
<li>49-64: <code>tfe_text_view_save</code> function.</li>
|
||||
<li>51: <code>tfe_text_view_save</code> is public, i.e. it is open to the other files. So, it doesn’t have <code>static</code> class. Public functions should check the parameter type with <code>g_return_if_fail</code> function. If <code>tv</code> is not a pointer to a TfeTextView instance, then it logs an error message and immediately returns. This function is similar to <code>g_return_val_if_fail</code>, but no value is returned because <code>tfe_text_view_save</code> doesn’t return a value.</li>
|
||||
<li>53-54: Gets GtkTextBuffer instance and GtkWidget instance and assignes them to <code>tb</code> and<code>win</code> respectively.</li>
|
||||
<li>56-57: If the buffer hasn’t modified, then it doesn’t need to save it. So the function returns.</li>
|
||||
<li>58-59: If <code>tv->file</code> is NULL, no file has given yet. It calls <code>tfe_text_view_saveas</code> which prompts a user to select a file or specify a new file to save.</li>
|
||||
<li>60-61: If <code>tv->file</code> doesn’t point GFile, somethig bad has happened. Logs an error message.</li>
|
||||
<li>62-63: Calls <code>save_file</code> to save the contents to the file.</li>
|
||||
<li>66-79: <code>tfe_text_view_saveas</code> function. It shows GtkFileChooserDialog and prompts the user to choose a file.</li>
|
||||
<li>73-76: Creates GtkFileChooserDialog. The title is “Save file”. Transient parent of the dialog is <code>win</code>, which is the top-level window. The action is save mode. The buttons are Cancel and Save.</li>
|
||||
<li>77: connects the “response” signal of the dialog and <code>saveas_dialog_response</code> handler.</li>
|
||||
<li>51: <code>tfe_text_view_save</code> is public, i.e. it is open to
|
||||
the other files. So, it doesn’t have <code>static</code> class. Public
|
||||
functions should check the parameter type with
|
||||
<code>g_return_if_fail</code> function. If <code>tv</code> is not a
|
||||
pointer to a TfeTextView instance, then it logs an error message and
|
||||
immediately returns. This function is similar to
|
||||
<code>g_return_val_if_fail</code>, but no value is returned because
|
||||
<code>tfe_text_view_save</code> doesn’t return a value.</li>
|
||||
<li>53-54: Gets GtkTextBuffer instance and GtkWidget instance and
|
||||
assignes them to <code>tb</code> and<code>win</code> respectively.</li>
|
||||
<li>56-57: If the buffer hasn’t modified, then it doesn’t need to save
|
||||
it. So the function returns.</li>
|
||||
<li>58-59: If <code>tv->file</code> is NULL, no file has given yet.
|
||||
It calls <code>tfe_text_view_saveas</code> which prompts a user to
|
||||
select a file or specify a new file to save.</li>
|
||||
<li>60-61: If <code>tv->file</code> doesn’t point GFile, somethig bad
|
||||
has happened. Logs an error message.</li>
|
||||
<li>62-63: Calls <code>save_file</code> to save the contents to the
|
||||
file.</li>
|
||||
<li>66-79: <code>tfe_text_view_saveas</code> function. It shows
|
||||
GtkFileChooserDialog and prompts the user to choose a file.</li>
|
||||
<li>73-76: Creates GtkFileChooserDialog. The title is “Save file”.
|
||||
Transient parent of the dialog is <code>win</code>, which is the
|
||||
top-level window. The action is save mode. The buttons are Cancel and
|
||||
Save.</li>
|
||||
<li>77: connects the “response” signal of the dialog and
|
||||
<code>saveas_dialog_response</code> handler.</li>
|
||||
<li>78: Shows the dialog.</li>
|
||||
</ul>
|
||||
<figure>
|
||||
<img src="image/saveas.png" alt="" /><figcaption>Saveas process</figcaption>
|
||||
<img src="image/saveas.png" alt="Saveas process" />
|
||||
<figcaption aria-hidden="true">Saveas process</figcaption>
|
||||
</figure>
|
||||
<p>When you use GtkFileChooserDialog, you need to divide the program into two parts. One is a function which creates GtkFileChooserDialog and the other is a signal handler. The function just creates and shows GtkFileChooserDialog. The rest is done by the handler. It gets Gfile from GtkFileChooserDialog and saves the buffer to the file by calling <code>save_file</code>.</p>
|
||||
<p>When you use GtkFileChooserDialog, you need to divide the program
|
||||
into two parts. One is a function which creates GtkFileChooserDialog and
|
||||
the other is a signal handler. The function just creates and shows
|
||||
GtkFileChooserDialog. The rest is done by the handler. It gets Gfile
|
||||
from GtkFileChooserDialog and saves the buffer to the file by calling
|
||||
<code>save_file</code>.</p>
|
||||
<h2 id="open-function">Open function</h2>
|
||||
<p>Open function shows GtkFileChooserDialog to users and prompts them to choose a file. Then it reads the file and puts the text into GtkTextBuffer.</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="dt">void</span> tfe_text_view_open (TfeTextView *tv, GtkWindow *win);</span></code></pre></div>
|
||||
<p>The parameter <code>win</code> is the top-level window. It will be a transient parent window of GtkFileChooserDialog when the dialog is created. This allows window managers to keep the dialog on top of the parent window, or center the dialog over the parent window. It is possible to give no parent window to the dialog. However, it is encouraged to give a parent window to dialog. This function might be called just after <code>tv</code> has been created. In that case, <code>tv</code> has not been incorporated into the widget hierarchy. Therefore it is impossible to get the top-level window from <code>tv</code>. That’s why the function needs <code>win</code> parameter.</p>
|
||||
<p>This function is usually called when the buffer of <code>tv</code> is empty. However, even if the buffer is not empty, <code>tfe_text_view_open</code> doesn’t treat it as an error. If you want to revert the buffer, calling this function is appropriate. Otherwise probably bad things will happen.</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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-2"><a href="#cb10-2"></a>open_dialog_response(GtkWidget *dialog, gint response, TfeTextView *tv) {</span>
|
||||
<span id="cb10-3"><a href="#cb10-3"></a> GtkTextBuffer *tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
|
||||
<span id="cb10-4"><a href="#cb10-4"></a> GFile *file;</span>
|
||||
<span id="cb10-5"><a href="#cb10-5"></a> <span class="dt">char</span> *contents;</span>
|
||||
<span id="cb10-6"><a href="#cb10-6"></a> gsize length;</span>
|
||||
<span id="cb10-7"><a href="#cb10-7"></a> GtkWidget *message_dialog;</span>
|
||||
<span id="cb10-8"><a href="#cb10-8"></a> GError *err = NULL;</span>
|
||||
<p>Open function shows GtkFileChooserDialog to users and prompts them to
|
||||
choose a file. Then it reads the file and puts the text into
|
||||
GtkTextBuffer.</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> tfe_text_view_open <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">,</span> GtkWindow <span class="op">*</span>win<span class="op">);</span></span></code></pre></div>
|
||||
<p>The parameter <code>win</code> is the top-level window. It will be a
|
||||
transient parent window of GtkFileChooserDialog when the dialog is
|
||||
created. This allows window managers to keep the dialog on top of the
|
||||
parent window, or center the dialog over the parent window. It is
|
||||
possible to give no parent window to the dialog. However, it is
|
||||
encouraged to give a parent window to dialog. This function might be
|
||||
called just after <code>tv</code> has been created. In that case,
|
||||
<code>tv</code> has not been incorporated into the widget hierarchy.
|
||||
Therefore it is impossible to get the top-level window from
|
||||
<code>tv</code>. That’s why the function needs <code>win</code>
|
||||
parameter.</p>
|
||||
<p>This function is usually called when the buffer of <code>tv</code> is
|
||||
empty. However, even if the buffer is not empty,
|
||||
<code>tfe_text_view_open</code> doesn’t treat it as an error. If you
|
||||
want to revert the buffer, calling this function is appropriate.
|
||||
Otherwise probably bad things will happen.</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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-2"><a href="#cb10-2"></a>open_dialog_response<span class="op">(</span>GtkWidget <span class="op">*</span>dialog<span class="op">,</span> gint response<span class="op">,</span> TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb10-3"><a href="#cb10-3"></a> GtkTextBuffer <span class="op">*</span>tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4"></a> GFile <span class="op">*</span>file<span class="op">;</span></span>
|
||||
<span id="cb10-5"><a href="#cb10-5"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span>
|
||||
<span id="cb10-6"><a href="#cb10-6"></a> gsize length<span class="op">;</span></span>
|
||||
<span id="cb10-7"><a href="#cb10-7"></a> GtkWidget <span class="op">*</span>message_dialog<span class="op">;</span></span>
|
||||
<span id="cb10-8"><a href="#cb10-8"></a> GError <span class="op">*</span>err <span class="op">=</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb10-9"><a href="#cb10-9"></a></span>
|
||||
<span id="cb10-10"><a href="#cb10-10"></a> <span class="cf">if</span> (response != GTK_RESPONSE_ACCEPT)</span>
|
||||
<span id="cb10-11"><a href="#cb10-11"></a> g_signal_emit (tv, tfe_text_view_signals[OPEN_RESPONSE], <span class="dv">0</span>, TFE_OPEN_RESPONSE_CANCEL);</span>
|
||||
<span id="cb10-12"><a href="#cb10-12"></a> <span class="cf">else</span> <span class="cf">if</span> (! G_IS_FILE (file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)))) {</span>
|
||||
<span id="cb10-13"><a href="#cb10-13"></a> g_warning (<span class="st">"TfeTextView: gtk_file_chooser_get_file returns non GFile.</span><span class="sc">\n</span><span class="st">"</span>);</span>
|
||||
<span id="cb10-14"><a href="#cb10-14"></a> g_signal_emit (tv, tfe_text_view_signals[OPEN_RESPONSE], <span class="dv">0</span>, TFE_OPEN_RESPONSE_ERROR);</span>
|
||||
<span id="cb10-15"><a href="#cb10-15"></a> } <span class="cf">else</span> <span class="cf">if</span> (! g_file_load_contents (file, NULL, &contents, &length, NULL, &err)) { <span class="co">/* read error */</span></span>
|
||||
<span id="cb10-16"><a href="#cb10-16"></a> g_object_unref (file);</span>
|
||||
<span id="cb10-17"><a href="#cb10-17"></a> message_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog), GTK_DIALOG_MODAL,</span>
|
||||
<span id="cb10-18"><a href="#cb10-18"></a> GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,</span>
|
||||
<span id="cb10-19"><a href="#cb10-19"></a> <span class="st">"%s.</span><span class="sc">\n</span><span class="st">"</span>, err->message);</span>
|
||||
<span id="cb10-20"><a href="#cb10-20"></a> g_signal_connect (message_dialog, <span class="st">"response"</span>, G_CALLBACK (gtk_window_destroy), NULL);</span>
|
||||
<span id="cb10-21"><a href="#cb10-21"></a> gtk_widget_show (message_dialog);</span>
|
||||
<span id="cb10-22"><a href="#cb10-22"></a> g_error_free (err);</span>
|
||||
<span id="cb10-23"><a href="#cb10-23"></a> g_signal_emit (tv, tfe_text_view_signals[OPEN_RESPONSE], <span class="dv">0</span>, TFE_OPEN_RESPONSE_ERROR);</span>
|
||||
<span id="cb10-24"><a href="#cb10-24"></a> } <span class="cf">else</span> {</span>
|
||||
<span id="cb10-25"><a href="#cb10-25"></a> gtk_text_buffer_set_text (tb, contents, length);</span>
|
||||
<span id="cb10-26"><a href="#cb10-26"></a> g_free (contents);</span>
|
||||
<span id="cb10-27"><a href="#cb10-27"></a> <span class="cf">if</span> (G_IS_FILE (tv->file))</span>
|
||||
<span id="cb10-28"><a href="#cb10-28"></a> g_object_unref (tv->file);</span>
|
||||
<span id="cb10-29"><a href="#cb10-29"></a> tv->file = file;</span>
|
||||
<span id="cb10-30"><a href="#cb10-30"></a> gtk_text_buffer_set_modified (tb, FALSE);</span>
|
||||
<span id="cb10-31"><a href="#cb10-31"></a> g_signal_emit (tv, tfe_text_view_signals[OPEN_RESPONSE], <span class="dv">0</span>, TFE_OPEN_RESPONSE_SUCCESS);</span>
|
||||
<span id="cb10-32"><a href="#cb10-32"></a> g_signal_emit (tv, tfe_text_view_signals[CHANGE_FILE], <span class="dv">0</span>);</span>
|
||||
<span id="cb10-33"><a href="#cb10-33"></a> }</span>
|
||||
<span id="cb10-34"><a href="#cb10-34"></a> gtk_window_destroy (GTK_WINDOW (dialog));</span>
|
||||
<span id="cb10-35"><a href="#cb10-35"></a>}</span>
|
||||
<span id="cb10-10"><a href="#cb10-10"></a> <span class="cf">if</span> <span class="op">(</span>response <span class="op">!=</span> GTK_RESPONSE_ACCEPT<span class="op">)</span></span>
|
||||
<span id="cb10-11"><a href="#cb10-11"></a> g_signal_emit <span class="op">(</span>tv<span class="op">,</span> tfe_text_view_signals<span class="op">[</span>OPEN_RESPONSE<span class="op">],</span> <span class="dv">0</span><span class="op">,</span> TFE_OPEN_RESPONSE_CANCEL<span class="op">);</span></span>
|
||||
<span id="cb10-12"><a href="#cb10-12"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span> G_IS_FILE <span class="op">(</span>file <span class="op">=</span> gtk_file_chooser_get_file <span class="op">(</span>GTK_FILE_CHOOSER <span class="op">(</span>dialog<span class="op">))))</span> <span class="op">{</span></span>
|
||||
<span id="cb10-13"><a href="#cb10-13"></a> g_warning <span class="op">(</span><span class="st">"TfeTextView: gtk_file_chooser_get_file returns non GFile.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||
<span id="cb10-14"><a href="#cb10-14"></a> g_signal_emit <span class="op">(</span>tv<span class="op">,</span> tfe_text_view_signals<span class="op">[</span>OPEN_RESPONSE<span class="op">],</span> <span class="dv">0</span><span class="op">,</span> TFE_OPEN_RESPONSE_ERROR<span class="op">);</span></span>
|
||||
<span id="cb10-15"><a href="#cb10-15"></a> <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span> g_file_load_contents <span class="op">(</span>file<span class="op">,</span> NULL<span class="op">,</span> <span class="op">&</span>contents<span class="op">,</span> <span class="op">&</span>length<span class="op">,</span> NULL<span class="op">,</span> <span class="op">&</span>err<span class="op">))</span> <span class="op">{</span> <span class="co">/* read error */</span></span>
|
||||
<span id="cb10-16"><a href="#cb10-16"></a> g_object_unref <span class="op">(</span>file<span class="op">);</span></span>
|
||||
<span id="cb10-17"><a href="#cb10-17"></a> message_dialog <span class="op">=</span> gtk_message_dialog_new <span class="op">(</span>GTK_WINDOW <span class="op">(</span>dialog<span class="op">),</span> GTK_DIALOG_MODAL<span class="op">,</span></span>
|
||||
<span id="cb10-18"><a href="#cb10-18"></a> GTK_MESSAGE_ERROR<span class="op">,</span> GTK_BUTTONS_CLOSE<span class="op">,</span></span>
|
||||
<span id="cb10-19"><a href="#cb10-19"></a> <span class="st">"%s.</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> err<span class="op">-></span>message<span class="op">);</span></span>
|
||||
<span id="cb10-20"><a href="#cb10-20"></a> g_signal_connect <span class="op">(</span>message_dialog<span class="op">,</span> <span class="st">"response"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>gtk_window_destroy<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb10-21"><a href="#cb10-21"></a> gtk_widget_show <span class="op">(</span>message_dialog<span class="op">);</span></span>
|
||||
<span id="cb10-22"><a href="#cb10-22"></a> g_error_free <span class="op">(</span>err<span class="op">);</span></span>
|
||||
<span id="cb10-23"><a href="#cb10-23"></a> g_signal_emit <span class="op">(</span>tv<span class="op">,</span> tfe_text_view_signals<span class="op">[</span>OPEN_RESPONSE<span class="op">],</span> <span class="dv">0</span><span class="op">,</span> TFE_OPEN_RESPONSE_ERROR<span class="op">);</span></span>
|
||||
<span id="cb10-24"><a href="#cb10-24"></a> <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
|
||||
<span id="cb10-25"><a href="#cb10-25"></a> gtk_text_buffer_set_text <span class="op">(</span>tb<span class="op">,</span> contents<span class="op">,</span> length<span class="op">);</span></span>
|
||||
<span id="cb10-26"><a href="#cb10-26"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span>
|
||||
<span id="cb10-27"><a href="#cb10-27"></a> <span class="cf">if</span> <span class="op">(</span>G_IS_FILE <span class="op">(</span>tv<span class="op">-></span>file<span class="op">))</span></span>
|
||||
<span id="cb10-28"><a href="#cb10-28"></a> g_object_unref <span class="op">(</span>tv<span class="op">-></span>file<span class="op">);</span></span>
|
||||
<span id="cb10-29"><a href="#cb10-29"></a> tv<span class="op">-></span>file <span class="op">=</span> file<span class="op">;</span></span>
|
||||
<span id="cb10-30"><a href="#cb10-30"></a> gtk_text_buffer_set_modified <span class="op">(</span>tb<span class="op">,</span> FALSE<span class="op">);</span></span>
|
||||
<span id="cb10-31"><a href="#cb10-31"></a> g_signal_emit <span class="op">(</span>tv<span class="op">,</span> tfe_text_view_signals<span class="op">[</span>OPEN_RESPONSE<span class="op">],</span> <span class="dv">0</span><span class="op">,</span> TFE_OPEN_RESPONSE_SUCCESS<span class="op">);</span></span>
|
||||
<span id="cb10-32"><a href="#cb10-32"></a> g_signal_emit <span class="op">(</span>tv<span class="op">,</span> tfe_text_view_signals<span class="op">[</span>CHANGE_FILE<span class="op">],</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||
<span id="cb10-33"><a href="#cb10-33"></a> <span class="op">}</span></span>
|
||||
<span id="cb10-34"><a href="#cb10-34"></a> gtk_window_destroy <span class="op">(</span>GTK_WINDOW <span class="op">(</span>dialog<span class="op">));</span></span>
|
||||
<span id="cb10-35"><a href="#cb10-35"></a><span class="op">}</span></span>
|
||||
<span id="cb10-36"><a href="#cb10-36"></a></span>
|
||||
<span id="cb10-37"><a href="#cb10-37"></a><span class="dt">void</span></span>
|
||||
<span id="cb10-38"><a href="#cb10-38"></a>tfe_text_view_open (TfeTextView *tv, GtkWindow *win) {</span>
|
||||
<span id="cb10-39"><a href="#cb10-39"></a> g_return_if_fail (TFE_IS_TEXT_VIEW (tv));</span>
|
||||
<span id="cb10-40"><a href="#cb10-40"></a> g_return_if_fail (GTK_IS_WINDOW (win));</span>
|
||||
<span id="cb10-38"><a href="#cb10-38"></a>tfe_text_view_open <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">,</span> GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb10-39"><a href="#cb10-39"></a> g_return_if_fail <span class="op">(</span>TFE_IS_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb10-40"><a href="#cb10-40"></a> g_return_if_fail <span class="op">(</span>GTK_IS_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb10-41"><a href="#cb10-41"></a></span>
|
||||
<span id="cb10-42"><a href="#cb10-42"></a> GtkWidget *dialog;</span>
|
||||
<span id="cb10-42"><a href="#cb10-42"></a> GtkWidget <span class="op">*</span>dialog<span class="op">;</span></span>
|
||||
<span id="cb10-43"><a href="#cb10-43"></a></span>
|
||||
<span id="cb10-44"><a href="#cb10-44"></a> dialog = gtk_file_chooser_dialog_new (<span class="st">"Open file"</span>, win, GTK_FILE_CHOOSER_ACTION_OPEN,</span>
|
||||
<span id="cb10-45"><a href="#cb10-45"></a> <span class="st">"Cancel"</span>, GTK_RESPONSE_CANCEL,</span>
|
||||
<span id="cb10-46"><a href="#cb10-46"></a> <span class="st">"Open"</span>, GTK_RESPONSE_ACCEPT,</span>
|
||||
<span id="cb10-47"><a href="#cb10-47"></a> NULL);</span>
|
||||
<span id="cb10-48"><a href="#cb10-48"></a> g_signal_connect (dialog, <span class="st">"response"</span>, G_CALLBACK (open_dialog_response), tv);</span>
|
||||
<span id="cb10-49"><a href="#cb10-49"></a> gtk_widget_show (dialog);</span>
|
||||
<span id="cb10-50"><a href="#cb10-50"></a>}</span></code></pre></div>
|
||||
<span id="cb10-44"><a href="#cb10-44"></a> dialog <span class="op">=</span> gtk_file_chooser_dialog_new <span class="op">(</span><span class="st">"Open file"</span><span class="op">,</span> win<span class="op">,</span> GTK_FILE_CHOOSER_ACTION_OPEN<span class="op">,</span></span>
|
||||
<span id="cb10-45"><a href="#cb10-45"></a> <span class="st">"Cancel"</span><span class="op">,</span> GTK_RESPONSE_CANCEL<span class="op">,</span></span>
|
||||
<span id="cb10-46"><a href="#cb10-46"></a> <span class="st">"Open"</span><span class="op">,</span> GTK_RESPONSE_ACCEPT<span class="op">,</span></span>
|
||||
<span id="cb10-47"><a href="#cb10-47"></a> NULL<span class="op">);</span></span>
|
||||
<span id="cb10-48"><a href="#cb10-48"></a> g_signal_connect <span class="op">(</span>dialog<span class="op">,</span> <span class="st">"response"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>open_dialog_response<span class="op">),</span> tv<span class="op">);</span></span>
|
||||
<span id="cb10-49"><a href="#cb10-49"></a> gtk_widget_show <span class="op">(</span>dialog<span class="op">);</span></span>
|
||||
<span id="cb10-50"><a href="#cb10-50"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>37-50: <code>tfe_text_view_open</code> function.</li>
|
||||
<li>44-47: Creates GtkFileChooserDialog. The title is “Open file”. Transient parent window is the top-level window of the application, which is given by the caller. The action is open mode. The buttons are Cancel and Open.</li>
|
||||
<li>48: connects the “response” signal of the dialog and <code>open_dialog_response</code> signal handler.</li>
|
||||
<li>44-47: Creates GtkFileChooserDialog. The title is “Open file”.
|
||||
Transient parent window is the top-level window of the application,
|
||||
which is given by the caller. The action is open mode. The buttons are
|
||||
Cancel and Open.</li>
|
||||
<li>48: connects the “response” signal of the dialog and
|
||||
<code>open_dialog_response</code> signal handler.</li>
|
||||
<li>49: Shows the dialog.</li>
|
||||
<li>1-35: <code>open_dialog_response</code> signal handler.</li>
|
||||
<li>10-11: If the response from GtkFileChooserDialog is not <code>GTK_RESPONSE_ACCEPT</code>, the user has clicked on the “Cancel” button or close button on the header bar. Then, “open-response” signal is emitted. The parameter of the signal is <code>TFE_OPEN_RESPONSE_CANCEL</code>.</li>
|
||||
<li>12-14: Gets the pointer to the Gfile by <code>gtk_file_chooser_get_file</code>. If it doesn’t point GFile, maybe an error has occurred. Then it emits “open-response” signal with the parameter <code>TFE_OPEN_RESPONSE_ERROR</code>.</li>
|
||||
<li>15-23: If an error occurs at file reading, then it decreases the reference count of the Gfile, shows a message dialog to report the error to the user and emits “open-response” signal with the parameter <code>TFE_OPEN_RESPONSE_ERROR</code>.</li>
|
||||
<li>24-33: If the file has successfully been read, then the text is inserted to GtkTextBuffer, frees the temporary buffer pointed by <code>contents</code> and sets <code>tv->file</code> to point the file (no duplication is not necessary). Then, it emits “open-response” signal with the parameter <code>TFE_OPEN_RESPONSE_SUCCESS</code> and emits “change-file” signal.</li>
|
||||
<li>10-11: If the response from GtkFileChooserDialog is not
|
||||
<code>GTK_RESPONSE_ACCEPT</code>, the user has clicked on the “Cancel”
|
||||
button or close button on the header bar. Then, “open-response” signal
|
||||
is emitted. The parameter of the signal is
|
||||
<code>TFE_OPEN_RESPONSE_CANCEL</code>.</li>
|
||||
<li>12-14: Gets the pointer to the Gfile by
|
||||
<code>gtk_file_chooser_get_file</code>. If it doesn’t point GFile, maybe
|
||||
an error has occurred. Then it emits “open-response” signal with the
|
||||
parameter <code>TFE_OPEN_RESPONSE_ERROR</code>.</li>
|
||||
<li>15-23: If an error occurs at file reading, then it decreases the
|
||||
reference count of the Gfile, shows a message dialog to report the error
|
||||
to the user and emits “open-response” signal with the parameter
|
||||
<code>TFE_OPEN_RESPONSE_ERROR</code>.</li>
|
||||
<li>24-33: If the file has successfully been read, then the text is
|
||||
inserted to GtkTextBuffer, frees the temporary buffer pointed by
|
||||
<code>contents</code> and sets <code>tv->file</code> to point the
|
||||
file (no duplication is not necessary). Then, it emits “open-response”
|
||||
signal with the parameter <code>TFE_OPEN_RESPONSE_SUCCESS</code> and
|
||||
emits “change-file” signal.</li>
|
||||
<li>34: destroys GtkFileCooserDialog.</li>
|
||||
</ul>
|
||||
<p>Now let’s think about the whole process between the caller and TfeTextView. It is shown in the following diagram and you would think that it is really complicated. Because signal is the only way for GtkFileChooserDialog to communicate with others. In Gtk3, <code>gtk_dialog_run</code> function is available. It simplifies the process. However, in Gtk4, <code>gtk_dialog_run</code> is unavailable any more.</p>
|
||||
<p>Now let’s think about the whole process between the caller and
|
||||
TfeTextView. It is shown in the following diagram and you would think
|
||||
that it is really complicated. Because signal is the only way for
|
||||
GtkFileChooserDialog to communicate with others. In GTK 3,
|
||||
<code>gtk_dialog_run</code> function is available. It simplifies the
|
||||
process. However, in GTK 4, <code>gtk_dialog_run</code> is unavailable
|
||||
any more.</p>
|
||||
<figure>
|
||||
<img src="image/open.png" alt="" /><figcaption>Caller and TfeTextView</figcaption>
|
||||
<img src="image/open.png" alt="Caller and TfeTextView" />
|
||||
<figcaption aria-hidden="true">Caller and TfeTextView</figcaption>
|
||||
</figure>
|
||||
<ol type="1">
|
||||
<li>A caller gets a pointer <code>tv</code> to a TfeTextView instance by calling <code>tfe_text_view_new</code>.</li>
|
||||
<li>The caller connects the handler (left bottom in the diagram) and the signal “open-response”.</li>
|
||||
<li>It calls <code>tfe_text_view_open</code> to prompt the user to select a file from GtkFileChooserDialog.</li>
|
||||
<li>The dialog emits a signal and it invokes the handler <code>open_dialog_response</code>.</li>
|
||||
<li>The handler reads the file and inserts the text into GtkTextBuffer and emits a signal to inform the status as a response code.</li>
|
||||
<li>A caller gets a pointer <code>tv</code> to a TfeTextView instance by
|
||||
calling <code>tfe_text_view_new</code>.</li>
|
||||
<li>The caller connects the handler (left bottom in the diagram) and the
|
||||
signal “open-response”.</li>
|
||||
<li>It calls <code>tfe_text_view_open</code> to prompt the user to
|
||||
select a file from GtkFileChooserDialog.</li>
|
||||
<li>The dialog emits a signal and it invokes the handler
|
||||
<code>open_dialog_response</code>.</li>
|
||||
<li>The handler reads the file and inserts the text into GtkTextBuffer
|
||||
and emits a signal to inform the status as a response code.</li>
|
||||
<li>The handler out of the TfeTextView receives the signal.</li>
|
||||
</ol>
|
||||
<h2 id="getting-gfile">Getting Gfile</h2>
|
||||
<p><code>gtk_text_view_get_file</code> is a simple function shown as follows.</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1"></a>GFile *</span>
|
||||
<span id="cb11-2"><a href="#cb11-2"></a>tfe_text_view_get_file (TfeTextView *tv) {</span>
|
||||
<span id="cb11-3"><a href="#cb11-3"></a> g_return_val_if_fail (TFE_IS_TEXT_VIEW (tv), NULL);</span>
|
||||
<p><code>gtk_text_view_get_file</code> is a simple function shown as
|
||||
follows.</p>
|
||||
<div class="sourceCode" id="cb11"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1"></a>GFile <span class="op">*</span></span>
|
||||
<span id="cb11-2"><a href="#cb11-2"></a>tfe_text_view_get_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-3"><a href="#cb11-3"></a> g_return_val_if_fail <span class="op">(</span>TFE_IS_TEXT_VIEW <span class="op">(</span>tv<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb11-4"><a href="#cb11-4"></a></span>
|
||||
<span id="cb11-5"><a href="#cb11-5"></a> <span class="cf">if</span> (G_IS_FILE (tv->file))</span>
|
||||
<span id="cb11-6"><a href="#cb11-6"></a> <span class="cf">return</span> g_file_dup (tv->file);</span>
|
||||
<span id="cb11-5"><a href="#cb11-5"></a> <span class="cf">if</span> <span class="op">(</span>G_IS_FILE <span class="op">(</span>tv<span class="op">-></span>file<span class="op">))</span></span>
|
||||
<span id="cb11-6"><a href="#cb11-6"></a> <span class="cf">return</span> g_file_dup <span class="op">(</span>tv<span class="op">-></span>file<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> NULL;</span>
|
||||
<span id="cb11-9"><a href="#cb11-9"></a>}</span></code></pre></div>
|
||||
<p>The important thing is to duplicate <code>tv->file</code>. Otherwise, if the caller frees the GFile object, <code>tv->file</code> is no more guaranteed to point the GFile. Another reason to use <code>g_file_dup</code> is that GFile isn’t thread-safe. If you use GFile in the different thread, the duplication is necessary. See <a href="https://docs.gtk.org/gio/method.File.dup.html">Gio API Reference, g_file_dup</a>.</p>
|
||||
<h2 id="the-api-document-and-source-file-of-tfetextview.c">The API document and source file of tfetextview.c</h2>
|
||||
<p>Refer API document of TfeTextView. Its original markdown file is under the directory <code>src/tfetextview</code>.</p>
|
||||
<p>All the source files are listed in <a href="sec16.html">Section 16</a>. You can find them under src/tfe5 and src/tfetextview directories.</p>
|
||||
<span id="cb11-8"><a href="#cb11-8"></a> <span class="cf">return</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb11-9"><a href="#cb11-9"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>The important thing is to duplicate <code>tv->file</code>.
|
||||
Otherwise, if the caller frees the GFile object,
|
||||
<code>tv->file</code> is no more guaranteed to point the GFile.
|
||||
Another reason to use <code>g_file_dup</code> is that GFile isn’t
|
||||
thread-safe. If you use GFile in the different thread, the duplication
|
||||
is necessary. See <a
|
||||
href="https://docs.gtk.org/gio/method.File.dup.html">Gio API Reference,
|
||||
g_file_dup</a>.</p>
|
||||
<h2 id="the-api-document-and-source-file-of-tfetextview.c">The API
|
||||
document and source file of tfetextview.c</h2>
|
||||
<p>Refer API document of TfeTextView. Its original markdown file is
|
||||
under the directory <code>src/tfetextview</code>.</p>
|
||||
<p>All the source files are listed in <a href="sec16.html">Section
|
||||
16</a>. You can find them under src/tfe5 and src/tfetextview
|
||||
directories.</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>
|
||||
|
|
340
docs/sec15.html
340
docs/sec15.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,7 +112,8 @@
|
|||
</div>
|
||||
</nav>
|
||||
<h1 id="tfeapplication.c">tfeapplication.c</h1>
|
||||
<p><code>tfeapplication.c</code> includes all the code other than <code>tfetxtview.c</code> and <code>tfenotebook.c</code>. It does:</p>
|
||||
<p><code>tfeapplication.c</code> includes all the code other than
|
||||
<code>tfetxtview.c</code> and <code>tfenotebook.c</code>. It does:</p>
|
||||
<ul>
|
||||
<li>Application support, mainly handling command line arguments.</li>
|
||||
<li>Builds widgets using ui file.</li>
|
||||
|
@ -120,191 +121,269 @@
|
|||
<li>Manages CSS.</li>
|
||||
</ul>
|
||||
<h2 id="main">main</h2>
|
||||
<p>The function <code>main</code> is the first invoked function in C language. It connects the command line given by the user and Gtk application.</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.tfe"</span></span>
|
||||
<p>The function <code>main</code> is the first invoked function in C
|
||||
language. It connects the command line given by the user and Gtk
|
||||
application.</p>
|
||||
<div class="sourceCode" id="cb1"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.tfe"</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2"></a></span>
|
||||
<span id="cb1-3"><a href="#cb1-3"></a><span class="dt">int</span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb1-5"><a href="#cb1-5"></a> GtkApplication *app;</span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a> <span class="dt">int</span> stat;</span>
|
||||
<span id="cb1-4"><a href="#cb1-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="cb1-5"><a href="#cb1-5"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7"></a></span>
|
||||
<span id="cb1-8"><a href="#cb1-8"></a> app = gtk_application_new (APPLICATION_ID, G_APPLICATION_HANDLES_OPEN);</span>
|
||||
<span id="cb1-8"><a href="#cb1-8"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_HANDLES_OPEN<span class="op">);</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9"></a></span>
|
||||
<span id="cb1-10"><a href="#cb1-10"></a> g_signal_connect (app, <span class="st">"startup"</span>, G_CALLBACK (app_startup), NULL);</span>
|
||||
<span id="cb1-11"><a href="#cb1-11"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</span>
|
||||
<span id="cb1-12"><a href="#cb1-12"></a> g_signal_connect (app, <span class="st">"open"</span>, G_CALLBACK (app_open), NULL);</span>
|
||||
<span id="cb1-10"><a href="#cb1-10"></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="cb1-11"><a href="#cb1-11"></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="cb1-12"><a href="#cb1-12"></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="cb1-13"><a href="#cb1-13"></a></span>
|
||||
<span id="cb1-14"><a href="#cb1-14"></a> stat =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb1-15"><a href="#cb1-15"></a> g_object_unref (app);</span>
|
||||
<span id="cb1-16"><a href="#cb1-16"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb1-17"><a href="#cb1-17"></a>}</span></code></pre></div>
|
||||
<span id="cb1-14"><a href="#cb1-14"></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="cb1-15"><a href="#cb1-15"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb1-16"><a href="#cb1-16"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb1-17"><a href="#cb1-17"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>1: Defines the application id. It is easy to find the application id, and better than the id is embedded in <code>gtk_application_new</code>.</li>
|
||||
<li>1: Defines the application id. It is easy to find the application
|
||||
id, and better than the id is embedded in
|
||||
<code>gtk_application_new</code>.</li>
|
||||
<li>8: Creates GtkApplication object.</li>
|
||||
<li>10-12: Connects “startup”, “activate” and “open” signals to their handlers.</li>
|
||||
<li>10-12: Connects “startup”, “activate” and “open” signals to their
|
||||
handlers.</li>
|
||||
<li>14: Runs the application.</li>
|
||||
<li>15-16: releases the reference to the application and returns the status.</li>
|
||||
<li>15-16: releases the reference to the application and returns the
|
||||
status.</li>
|
||||
</ul>
|
||||
<h2 id="startup-signal-handler">startup signal handler</h2>
|
||||
<p>Startup signal is emitted just after the GtkApplication instance is initialized. What the signal handler needs to do is the initialization of the application.</p>
|
||||
<p>Startup signal is emitted just after the GtkApplication instance is
|
||||
initialized. What the signal handler needs to do is the initialization
|
||||
of the application.</p>
|
||||
<ul>
|
||||
<li>Builds the widgets using ui file.</li>
|
||||
<li>Connects button signals and their handlers.</li>
|
||||
<li>Sets CSS.</li>
|
||||
</ul>
|
||||
<p>The handler is as follows.</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_startup (GApplication *application) {</span>
|
||||
<span id="cb2-3"><a href="#cb2-3"></a> GtkApplication *app = GTK_APPLICATION (application);</span>
|
||||
<span id="cb2-4"><a href="#cb2-4"></a> GtkBuilder *build;</span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a> GtkApplicationWindow *win;</span>
|
||||
<span id="cb2-6"><a href="#cb2-6"></a> GtkNotebook *nb;</span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a> GtkButton *btno;</span>
|
||||
<span id="cb2-8"><a href="#cb2-8"></a> GtkButton *btnn;</span>
|
||||
<span id="cb2-9"><a href="#cb2-9"></a> GtkButton *btns;</span>
|
||||
<span id="cb2-10"><a href="#cb2-10"></a> GtkButton *btnc;</span>
|
||||
<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_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3"></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="cb2-4"><a href="#cb2-4"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a> GtkApplicationWindow <span class="op">*</span>win<span class="op">;</span></span>
|
||||
<span id="cb2-6"><a href="#cb2-6"></a> GtkNotebook <span class="op">*</span>nb<span class="op">;</span></span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a> GtkButton <span class="op">*</span>btno<span class="op">;</span></span>
|
||||
<span id="cb2-8"><a href="#cb2-8"></a> GtkButton <span class="op">*</span>btnn<span class="op">;</span></span>
|
||||
<span id="cb2-9"><a href="#cb2-9"></a> GtkButton <span class="op">*</span>btns<span class="op">;</span></span>
|
||||
<span id="cb2-10"><a href="#cb2-10"></a> GtkButton <span class="op">*</span>btnc<span class="op">;</span></span>
|
||||
<span id="cb2-11"><a href="#cb2-11"></a></span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> build = gtk_builder_new_from_resource (<span class="st">"/com/github/ToshioCP/tfe/tfe.ui"</span>);</span>
|
||||
<span id="cb2-13"><a href="#cb2-13"></a> win = GTK_APPLICATION_WINDOW (gtk_builder_get_object (build, <span class="st">"win"</span>));</span>
|
||||
<span id="cb2-14"><a href="#cb2-14"></a> nb = GTK_NOTEBOOK (gtk_builder_get_object (build, <span class="st">"nb"</span>));</span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a> gtk_window_set_application (GTK_WINDOW (win), app);</span>
|
||||
<span id="cb2-16"><a href="#cb2-16"></a> btno = GTK_BUTTON (gtk_builder_get_object (build, <span class="st">"btno"</span>));</span>
|
||||
<span id="cb2-17"><a href="#cb2-17"></a> btnn = GTK_BUTTON (gtk_builder_get_object (build, <span class="st">"btnn"</span>));</span>
|
||||
<span id="cb2-18"><a href="#cb2-18"></a> btns = GTK_BUTTON (gtk_builder_get_object (build, <span class="st">"btns"</span>));</span>
|
||||
<span id="cb2-19"><a href="#cb2-19"></a> btnc = GTK_BUTTON (gtk_builder_get_object (build, <span class="st">"btnc"</span>));</span>
|
||||
<span id="cb2-20"><a href="#cb2-20"></a> g_signal_connect_swapped (btno, <span class="st">"clicked"</span>, G_CALLBACK (open_cb), nb);</span>
|
||||
<span id="cb2-21"><a href="#cb2-21"></a> g_signal_connect_swapped (btnn, <span class="st">"clicked"</span>, G_CALLBACK (new_cb), nb);</span>
|
||||
<span id="cb2-22"><a href="#cb2-22"></a> g_signal_connect_swapped (btns, <span class="st">"clicked"</span>, G_CALLBACK (save_cb), nb);</span>
|
||||
<span id="cb2-23"><a href="#cb2-23"></a> g_signal_connect_swapped (btnc, <span class="st">"clicked"</span>, G_CALLBACK (close_cb), nb);</span>
|
||||
<span id="cb2-24"><a href="#cb2-24"></a> g_object_unref(build);</span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">"/com/github/ToshioCP/tfe/tfe.ui"</span><span class="op">);</span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13"></a> win <span class="op">=</span> GTK_APPLICATION_WINDOW <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-14"><a href="#cb2-14"></a> nb <span class="op">=</span> GTK_NOTEBOOK <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"nb"</span><span class="op">));</span></span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> app<span class="op">);</span></span>
|
||||
<span id="cb2-16"><a href="#cb2-16"></a> btno <span class="op">=</span> GTK_BUTTON <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"btno"</span><span class="op">));</span></span>
|
||||
<span id="cb2-17"><a href="#cb2-17"></a> btnn <span class="op">=</span> GTK_BUTTON <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"btnn"</span><span class="op">));</span></span>
|
||||
<span id="cb2-18"><a href="#cb2-18"></a> btns <span class="op">=</span> GTK_BUTTON <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"btns"</span><span class="op">));</span></span>
|
||||
<span id="cb2-19"><a href="#cb2-19"></a> btnc <span class="op">=</span> GTK_BUTTON <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"btnc"</span><span class="op">));</span></span>
|
||||
<span id="cb2-20"><a href="#cb2-20"></a> g_signal_connect_swapped <span class="op">(</span>btno<span class="op">,</span> <span class="st">"clicked"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>open_cb<span class="op">),</span> nb<span class="op">);</span></span>
|
||||
<span id="cb2-21"><a href="#cb2-21"></a> g_signal_connect_swapped <span class="op">(</span>btnn<span class="op">,</span> <span class="st">"clicked"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>new_cb<span class="op">),</span> nb<span class="op">);</span></span>
|
||||
<span id="cb2-22"><a href="#cb2-22"></a> g_signal_connect_swapped <span class="op">(</span>btns<span class="op">,</span> <span class="st">"clicked"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>save_cb<span class="op">),</span> nb<span class="op">);</span></span>
|
||||
<span id="cb2-23"><a href="#cb2-23"></a> g_signal_connect_swapped <span class="op">(</span>btnc<span class="op">,</span> <span class="st">"clicked"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>close_cb<span class="op">),</span> nb<span class="op">);</span></span>
|
||||
<span id="cb2-24"><a href="#cb2-24"></a> g_object_unref<span class="op">(</span>build<span class="op">);</span></span>
|
||||
<span id="cb2-25"><a href="#cb2-25"></a></span>
|
||||
<span id="cb2-26"><a href="#cb2-26"></a>GdkDisplay *display;</span>
|
||||
<span id="cb2-26"><a href="#cb2-26"></a>GdkDisplay <span class="op">*</span>display<span class="op">;</span></span>
|
||||
<span id="cb2-27"><a href="#cb2-27"></a></span>
|
||||
<span id="cb2-28"><a href="#cb2-28"></a> display = gtk_widget_get_display (GTK_WIDGET (win));</span>
|
||||
<span id="cb2-29"><a href="#cb2-29"></a> GtkCssProvider *provider = gtk_css_provider_new ();</span>
|
||||
<span id="cb2-30"><a href="#cb2-30"></a> gtk_css_provider_load_from_data (provider, <span class="st">"textview {padding: 10px; font-family: monospace; font-size: 12pt;}"</span>, -<span class="dv">1</span>);</span>
|
||||
<span id="cb2-31"><a href="#cb2-31"></a> gtk_style_context_add_provider_for_display (display, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);</span>
|
||||
<span id="cb2-32"><a href="#cb2-32"></a>}</span></code></pre></div>
|
||||
<span id="cb2-28"><a href="#cb2-28"></a> display <span class="op">=</span> gtk_widget_get_display <span class="op">(</span>GTK_WIDGET <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb2-29"><a href="#cb2-29"></a> GtkCssProvider <span class="op">*</span>provider <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span>
|
||||
<span id="cb2-30"><a href="#cb2-30"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> <span class="st">"textview {padding: 10px; font-family: monospace; font-size: 12pt;}"</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
||||
<span id="cb2-31"><a href="#cb2-31"></a> gtk_style_context_add_provider_for_display <span class="op">(</span>display<span class="op">,</span> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">),</span> GTK_STYLE_PROVIDER_PRIORITY_APPLICATION<span class="op">);</span></span>
|
||||
<span id="cb2-32"><a href="#cb2-32"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>12-15: Builds widgets using ui file (resource). Connects the top-level window and the application with <code>gtk_window_set_application</code>.</li>
|
||||
<li>12-15: Builds widgets using ui file (resource). Connects the
|
||||
top-level window and the application with
|
||||
<code>gtk_window_set_application</code>.</li>
|
||||
<li>16-23: Gets buttons and connects their signals and handlers.</li>
|
||||
<li>24: Releases the reference to GtkBuilder.</li>
|
||||
<li>26-31: Sets CSS. CSS in Gtk is similar to CSS in HTML. You can set margin, border, padding, color, font and so on with CSS. In this program CSS is in line 30. It sets padding, font-family and font size of GtkTextView.</li>
|
||||
<li>26-28: GdkDisplay is used to set CSS. CSS will be explained in the next subsection.</li>
|
||||
<li>26-31: Sets CSS. CSS in Gtk is similar to CSS in HTML. You can set
|
||||
margin, border, padding, color, font and so on with CSS. In this program
|
||||
CSS is in line 30. It sets padding, font-family and font size of
|
||||
GtkTextView.</li>
|
||||
<li>26-28: GdkDisplay is used to set CSS. CSS will be explained in the
|
||||
next subsection.</li>
|
||||
</ul>
|
||||
<h2 id="css-in-gtk">CSS in Gtk</h2>
|
||||
<p>CSS is an abbreviation of Cascading Style Sheet. It is originally used with HTML to describe the presentation semantics of a document. You might have found that the widgets in Gtk is similar to a window in a browser. It implies that CSS can also be applied to Gtk windowing system.</p>
|
||||
<p>CSS is an abbreviation of Cascading Style Sheet. It is originally
|
||||
used with HTML to describe the presentation semantics of a document. You
|
||||
might have found that the widgets in Gtk is similar to a window in a
|
||||
browser. It implies that CSS can also be applied to Gtk windowing
|
||||
system.</p>
|
||||
<h3 id="css-nodes-selectors">CSS nodes, selectors</h3>
|
||||
<p>The syntax of CSS is as follows.</p>
|
||||
<pre><code>selector { color: yellow; padding-top: 10px; ...}</code></pre>
|
||||
<p>Every widget has CSS node. For example GtkTextView has <code>textview</code> node. If you want to set style to GtkTextView, substitute “textview” for the selector.</p>
|
||||
<p>Every widget has CSS node. For example GtkTextView has
|
||||
<code>textview</code> node. If you want to set style to GtkTextView,
|
||||
substitute “textview” for the selector.</p>
|
||||
<pre><code>textview {color: yellow; ...}</code></pre>
|
||||
<p>Class, ID and some other things can be applied to the selector like Web CSS. Refer to <a href="https://docs.gtk.org/gtk4/css-overview.html">Gtk4 API Reference, CSS in Gtk</a> for further information.</p>
|
||||
<p>Class, ID and some other things can be applied to the selector like
|
||||
Web CSS. Refer to <a
|
||||
href="https://docs.gtk.org/gtk4/css-overview.html">GTK 4 API Reference,
|
||||
CSS in Gtk</a> for further information.</p>
|
||||
<p>In line 30, the CSS is a string.</p>
|
||||
<pre><code>textview {padding: 10px; font-family: monospace; font-size: 12pt;}</code></pre>
|
||||
<ul>
|
||||
<li>padding is a space between the border and contents. This space makes the textview easier to read.</li>
|
||||
<li>font-family is a name of font. “monospace” is one of the generic family font keywords.</li>
|
||||
<li>padding is a space between the border and contents. This space makes
|
||||
the textview easier to read.</li>
|
||||
<li>font-family is a name of font. “monospace” is one of the generic
|
||||
family font keywords.</li>
|
||||
<li>font-size is set to 12pt.</li>
|
||||
</ul>
|
||||
<h3 id="gtkstylecontext-gtkcssprovider-and-gdkdisplay">GtkStyleContext, GtkCSSProvider and GdkDisplay</h3>
|
||||
<p>GtkStyleContext is an object that stores styling information affecting a widget. Each widget is connected to the corresponding GtkStyleContext. You can get the context by <code>gtk_widget_get_style_context</code>.</p>
|
||||
<p>GtkCssProvider is an object which parses CSS in order to style widgets.</p>
|
||||
<p>To apply your CSS to widgets, you need to add GtkStyleProvider (the interface of GtkCSSProvider) to GtkStyleContext. However, instead, you can add it to GdkDisplay of the window (usually top-level window).</p>
|
||||
<h3 id="gtkstylecontext-gtkcssprovider-and-gdkdisplay">GtkStyleContext,
|
||||
GtkCSSProvider and GdkDisplay</h3>
|
||||
<p>GtkStyleContext is an object that stores styling information
|
||||
affecting a widget. Each widget is connected to the corresponding
|
||||
GtkStyleContext. You can get the context by
|
||||
<code>gtk_widget_get_style_context</code>.</p>
|
||||
<p>GtkCssProvider is an object which parses CSS in order to style
|
||||
widgets.</p>
|
||||
<p>To apply your CSS to widgets, you need to add GtkStyleProvider (the
|
||||
interface of GtkCSSProvider) to GtkStyleContext. However, instead, you
|
||||
can add it to GdkDisplay of the window (usually top-level window).</p>
|
||||
<p>Look at the source file of <code>startup</code> handler again.</p>
|
||||
<ul>
|
||||
<li>28: The display is obtained by <code>gtk_widget_get_display</code>.</li>
|
||||
<li>28: The display is obtained by
|
||||
<code>gtk_widget_get_display</code>.</li>
|
||||
<li>29: Creates a GtkCssProvider instance.</li>
|
||||
<li>30: Puts the CSS into the provider.</li>
|
||||
<li>31: Adds the provider to the display. The last argument of <code>gtk_style_context_add_provider_for_display</code> is the priority of the style provider. <code>GTK_STYLE_PROVIDER_PRIORITY_APPLICATION</code> is a priority for application-specific style information. <code>GTK_STYLE_PROVIDER_PRIORITY_USER</code> is also often used and it is the highest priority. So, <code>GTK_STYLE_PROVIDER_PRIORITY_USER</code> is often used to a specific widget.</li>
|
||||
<li>31: Adds the provider to the display. The last argument of
|
||||
<code>gtk_style_context_add_provider_for_display</code> is the priority
|
||||
of the style provider.
|
||||
<code>GTK_STYLE_PROVIDER_PRIORITY_APPLICATION</code> is a priority for
|
||||
application-specific style information.
|
||||
<code>GTK_STYLE_PROVIDER_PRIORITY_USER</code> is also often used and it
|
||||
is the highest priority. So,
|
||||
<code>GTK_STYLE_PROVIDER_PRIORITY_USER</code> is often used to a
|
||||
specific widget.</li>
|
||||
</ul>
|
||||
<p>It is possible to add the provider to the context of GtkTextView instead of GdkDiplay. To do so, rewrite <code>tfe_text_view_new</code>. First, get the GtkStyleContext object of a TfeTextView object. Then adds the CSS provider to the context.</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"></a>GtkWidget *</span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a>tfe_text_view_new (<span class="dt">void</span>) {</span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a> GtkWidget *tv;</span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a></span>
|
||||
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a> tv = gtk_widget_new (TFE_TYPE_TEXT_VIEW, NULL);</span>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a></span>
|
||||
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a> GtkStyleContext *context;</span>
|
||||
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a></span>
|
||||
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a> context = gtk_widget_get_style_context (GTK_WIDGET (tv));</span>
|
||||
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a> GtkCssProvider *provider = gtk_css_provider_new ();</span>
|
||||
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a> gtk_css_provider_load_from_data (provider, <span class="st">"textview {padding: 10px; font-family: monospace; font-size: 12pt;}"</span>, -<span class="dv">1</span>);</span>
|
||||
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a> gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER);</span>
|
||||
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a></span>
|
||||
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a> <span class="cf">return</span> tv;</span>
|
||||
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a>}</span></code></pre></div>
|
||||
<p>It is possible to add the provider to the context of GtkTextView
|
||||
instead of GdkDiplay. To do so, rewrite <code>tfe_text_view_new</code>.
|
||||
First, get the GtkStyleContext object of a TfeTextView object. Then adds
|
||||
the CSS provider to the context.</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>GtkWidget <span class="op">*</span></span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>tfe_text_view_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> GtkWidget <span class="op">*</span>tv<span class="op">;</span></span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> tv <span class="op">=</span> gtk_widget_new <span class="op">(</span>TFE_TYPE_TEXT_VIEW<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a> GtkStyleContext <span class="op">*</span>context<span class="op">;</span></span>
|
||||
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a> context <span class="op">=</span> gtk_widget_get_style_context <span class="op">(</span>GTK_WIDGET <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a> GtkCssProvider <span class="op">*</span>provider <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span>
|
||||
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> <span class="st">"textview {padding: 10px; font-family: monospace; font-size: 12pt;}"</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
||||
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a> gtk_style_context_add_provider <span class="op">(</span>context<span class="op">,</span> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">),</span> GTK_STYLE_PROVIDER_PRIORITY_USER<span class="op">);</span></span>
|
||||
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> tv<span class="op">;</span></span>
|
||||
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>CSS in the context takes precedence over CSS in the display.</p>
|
||||
<h2 id="activate-and-open-handler">activate and open handler</h2>
|
||||
<p>The handler of “activate” and “open” signal are <code>app_activate</code> and <code>app_open</code> respectively. They just create a new GtkNotebookPage.</p>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2"></a>app_activate (GApplication *application) {</span>
|
||||
<span id="cb7-3"><a href="#cb7-3"></a> GtkApplication *app = GTK_APPLICATION (application);</span>
|
||||
<span id="cb7-4"><a href="#cb7-4"></a> GtkWidget *win = GTK_WIDGET (gtk_application_get_active_window (app));</span>
|
||||
<span id="cb7-5"><a href="#cb7-5"></a> GtkWidget *boxv = gtk_window_get_child (GTK_WINDOW (win));</span>
|
||||
<span id="cb7-6"><a href="#cb7-6"></a> GtkNotebook *nb = GTK_NOTEBOOK (gtk_widget_get_last_child (boxv));</span>
|
||||
<p>The handler of “activate” and “open” signal are
|
||||
<code>app_activate</code> and <code>app_open</code> respectively. They
|
||||
just create a new GtkNotebookPage.</p>
|
||||
<div class="sourceCode" id="cb7"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb7-3"><a href="#cb7-3"></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-4"><a href="#cb7-4"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_application_get_active_window <span class="op">(</span>app<span class="op">));</span></span>
|
||||
<span id="cb7-5"><a href="#cb7-5"></a> GtkWidget <span class="op">*</span>boxv <span class="op">=</span> gtk_window_get_child <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb7-6"><a href="#cb7-6"></a> GtkNotebook <span class="op">*</span>nb <span class="op">=</span> GTK_NOTEBOOK <span class="op">(</span>gtk_widget_get_last_child <span class="op">(</span>boxv<span class="op">));</span></span>
|
||||
<span id="cb7-7"><a href="#cb7-7"></a></span>
|
||||
<span id="cb7-8"><a href="#cb7-8"></a> notebook_page_new (nb);</span>
|
||||
<span id="cb7-9"><a href="#cb7-9"></a> gtk_widget_show (GTK_WIDGET (win));</span>
|
||||
<span id="cb7-10"><a href="#cb7-10"></a>}</span>
|
||||
<span id="cb7-8"><a href="#cb7-8"></a> notebook_page_new <span class="op">(</span>nb<span class="op">);</span></span>
|
||||
<span id="cb7-9"><a href="#cb7-9"></a> gtk_widget_show <span class="op">(</span>GTK_WIDGET <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb7-10"><a href="#cb7-10"></a><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">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-13"><a href="#cb7-13"></a>app_open (GApplication *application, GFile ** files, gint n_files, <span class="dt">const</span> gchar *hint) {</span>
|
||||
<span id="cb7-14"><a href="#cb7-14"></a> GtkApplication *app = GTK_APPLICATION (application);</span>
|
||||
<span id="cb7-15"><a href="#cb7-15"></a> GtkWidget *win = GTK_WIDGET (gtk_application_get_active_window (app));</span>
|
||||
<span id="cb7-16"><a href="#cb7-16"></a> GtkWidget *boxv = gtk_window_get_child (GTK_WINDOW (win));</span>
|
||||
<span id="cb7-17"><a href="#cb7-17"></a> GtkNotebook *nb = GTK_NOTEBOOK (gtk_widget_get_last_child (boxv));</span>
|
||||
<span id="cb7-18"><a href="#cb7-18"></a> <span class="dt">int</span> i;</span>
|
||||
<span id="cb7-13"><a href="#cb7-13"></a>app_open <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">,</span> GFile <span class="op">**</span> files<span class="op">,</span> gint n_files<span class="op">,</span> <span class="dt">const</span> gchar <span class="op">*</span>hint<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb7-14"><a href="#cb7-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="cb7-15"><a href="#cb7-15"></a> GtkWidget <span class="op">*</span>win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_application_get_active_window <span class="op">(</span>app<span class="op">));</span></span>
|
||||
<span id="cb7-16"><a href="#cb7-16"></a> GtkWidget <span class="op">*</span>boxv <span class="op">=</span> gtk_window_get_child <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb7-17"><a href="#cb7-17"></a> GtkNotebook <span class="op">*</span>nb <span class="op">=</span> GTK_NOTEBOOK <span class="op">(</span>gtk_widget_get_last_child <span class="op">(</span>boxv<span class="op">));</span></span>
|
||||
<span id="cb7-18"><a href="#cb7-18"></a> <span class="dt">int</span> i<span class="op">;</span></span>
|
||||
<span id="cb7-19"><a href="#cb7-19"></a></span>
|
||||
<span id="cb7-20"><a href="#cb7-20"></a> <span class="cf">for</span> (i = <span class="dv">0</span>; i < n_files; i++)</span>
|
||||
<span id="cb7-21"><a href="#cb7-21"></a> notebook_page_new_with_file (nb, files[i]);</span>
|
||||
<span id="cb7-22"><a href="#cb7-22"></a> <span class="cf">if</span> (gtk_notebook_get_n_pages (nb) == <span class="dv">0</span>)</span>
|
||||
<span id="cb7-23"><a href="#cb7-23"></a> notebook_page_new (nb);</span>
|
||||
<span id="cb7-24"><a href="#cb7-24"></a> gtk_widget_show (win);</span>
|
||||
<span id="cb7-25"><a href="#cb7-25"></a>}</span></code></pre></div>
|
||||
<span id="cb7-20"><a href="#cb7-20"></a> <span class="cf">for</span> <span class="op">(</span>i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> n_files<span class="op">;</span> i<span class="op">++)</span></span>
|
||||
<span id="cb7-21"><a href="#cb7-21"></a> notebook_page_new_with_file <span class="op">(</span>nb<span class="op">,</span> files<span class="op">[</span>i<span class="op">]);</span></span>
|
||||
<span id="cb7-22"><a href="#cb7-22"></a> <span class="cf">if</span> <span class="op">(</span>gtk_notebook_get_n_pages <span class="op">(</span>nb<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb7-23"><a href="#cb7-23"></a> notebook_page_new <span class="op">(</span>nb<span class="op">);</span></span>
|
||||
<span id="cb7-24"><a href="#cb7-24"></a> gtk_widget_show <span class="op">(</span>win<span class="op">);</span></span>
|
||||
<span id="cb7-25"><a href="#cb7-25"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>1-10: <code>app_activate</code>.</li>
|
||||
<li>8-10: Creates a new page and shows the window.</li>
|
||||
<li>12-25: <code>app_open</code>.</li>
|
||||
<li>20-21: Creates notebook pages with files.</li>
|
||||
<li>22-23: If no page has created, maybe because of read error, then it creates an empty page.</li>
|
||||
<li>22-23: If no page has created, maybe because of read error, then it
|
||||
creates an empty page.</li>
|
||||
<li>24: Shows the window.</li>
|
||||
</ul>
|
||||
<p>These codes have become really simple thanks to tfenotebook.c and tfetextview.c.</p>
|
||||
<p>These codes have become really simple thanks to tfenotebook.c and
|
||||
tfetextview.c.</p>
|
||||
<h2 id="primary-instance">Primary instance</h2>
|
||||
<p>Only one GApplication instance can be run at a time per session. The session is a bit difficult concept and also platform-dependent, but roughly speaking, it corresponds to a graphical desktop login. When you use your PC, you probably login first, then your desktop appears until you log off. This is the session.</p>
|
||||
<p>However, Linux is multi process OS and you can run two or more instances of the same application. Isn’t it a contradiction?</p>
|
||||
<p>When first instance is launched, then it registers itself with its application ID (for example, <code>com.github.ToshioCP.tfe</code>). Just after the registration, startup signal is emitted, then activate or open signal is emitted and the instance’s main loop runs. I wrote “startup signal is emitted just after the application instance is initialized” in the prior subsection. More precisely, it is emitted just after the registration.</p>
|
||||
<p>If another instance which has the same application ID is invoked, it also tries to register itself. Because this is the second instance, the registration of the ID has already done, so it fails. Because of the failure startup signal isn’t emitted. After that, activate or open signal is emitted in the primary instance, not the second instance. The primary instance receives the signal and its handler is invoked. On the other hand, the second instance doesn’t receive the signal and it immediately quits.</p>
|
||||
<p>Only one GApplication instance can be run at a time per session. The
|
||||
session is a bit difficult concept and also platform-dependent, but
|
||||
roughly speaking, it corresponds to a graphical desktop login. When you
|
||||
use your PC, you probably login first, then your desktop appears until
|
||||
you log off. This is the session.</p>
|
||||
<p>However, Linux is multi process OS and you can run two or more
|
||||
instances of the same application. Isn’t it a contradiction?</p>
|
||||
<p>When first instance is launched, then it registers itself with its
|
||||
application ID (for example, <code>com.github.ToshioCP.tfe</code>). Just
|
||||
after the registration, startup signal is emitted, then activate or open
|
||||
signal is emitted and the instance’s main loop runs. I wrote “startup
|
||||
signal is emitted just after the application instance is initialized” in
|
||||
the prior subsection. More precisely, it is emitted just after the
|
||||
registration.</p>
|
||||
<p>If another instance which has the same application ID is invoked, it
|
||||
also tries to register itself. Because this is the second instance, the
|
||||
registration of the ID has already done, so it fails. Because of the
|
||||
failure startup signal isn’t emitted. After that, activate or open
|
||||
signal is emitted in the primary instance, not the second instance. The
|
||||
primary instance receives the signal and its handler is invoked. On the
|
||||
other hand, the second instance doesn’t receive the signal and it
|
||||
immediately quits.</p>
|
||||
<p>Try to run two instances in a row.</p>
|
||||
<pre><code>$ ./_build/tfe &
|
||||
[1] 84453
|
||||
$ ./build/tfe tfeapplication.c
|
||||
$</code></pre>
|
||||
<p>First, the primary instance opens a window. Then, after the second instance is run, a new notebook page with the contents of <code>tfeapplication.c</code> appears in the primary instance’s window. This is because the open signal is emitted in the primary instance. The second instance immediately quits so shell prompt soon appears.</p>
|
||||
<h2 id="a-series-of-handlers-correspond-to-the-button-signals">a series of handlers correspond to the button signals</h2>
|
||||
<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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb9-2"><a href="#cb9-2"></a>open_cb (GtkNotebook *nb) {</span>
|
||||
<span id="cb9-3"><a href="#cb9-3"></a> notebook_page_open (nb);</span>
|
||||
<span id="cb9-4"><a href="#cb9-4"></a>}</span>
|
||||
<p>First, the primary instance opens a window. Then, after the second
|
||||
instance is run, a new notebook page with the contents of
|
||||
<code>tfeapplication.c</code> appears in the primary instance’s window.
|
||||
This is because the open signal is emitted in the primary instance. The
|
||||
second instance immediately quits so shell prompt soon appears.</p>
|
||||
<h2 id="a-series-of-handlers-correspond-to-the-button-signals">a series
|
||||
of handlers correspond to the button signals</h2>
|
||||
<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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb9-2"><a href="#cb9-2"></a>open_cb <span class="op">(</span>GtkNotebook <span class="op">*</span>nb<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb9-3"><a href="#cb9-3"></a> notebook_page_open <span class="op">(</span>nb<span class="op">);</span></span>
|
||||
<span id="cb9-4"><a href="#cb9-4"></a><span class="op">}</span></span>
|
||||
<span id="cb9-5"><a href="#cb9-5"></a></span>
|
||||
<span id="cb9-6"><a href="#cb9-6"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb9-7"><a href="#cb9-7"></a>new_cb (GtkNotebook *nb) {</span>
|
||||
<span id="cb9-8"><a href="#cb9-8"></a> notebook_page_new (nb);</span>
|
||||
<span id="cb9-9"><a href="#cb9-9"></a>}</span>
|
||||
<span id="cb9-7"><a href="#cb9-7"></a>new_cb <span class="op">(</span>GtkNotebook <span class="op">*</span>nb<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb9-8"><a href="#cb9-8"></a> notebook_page_new <span class="op">(</span>nb<span class="op">);</span></span>
|
||||
<span id="cb9-9"><a href="#cb9-9"></a><span class="op">}</span></span>
|
||||
<span id="cb9-10"><a href="#cb9-10"></a></span>
|
||||
<span id="cb9-11"><a href="#cb9-11"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb9-12"><a href="#cb9-12"></a>save_cb (GtkNotebook *nb) {</span>
|
||||
<span id="cb9-13"><a href="#cb9-13"></a> notebook_page_save (nb);</span>
|
||||
<span id="cb9-14"><a href="#cb9-14"></a>}</span>
|
||||
<span id="cb9-12"><a href="#cb9-12"></a>save_cb <span class="op">(</span>GtkNotebook <span class="op">*</span>nb<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb9-13"><a href="#cb9-13"></a> notebook_page_save <span class="op">(</span>nb<span class="op">);</span></span>
|
||||
<span id="cb9-14"><a href="#cb9-14"></a><span class="op">}</span></span>
|
||||
<span id="cb9-15"><a href="#cb9-15"></a></span>
|
||||
<span id="cb9-16"><a href="#cb9-16"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb9-17"><a href="#cb9-17"></a>close_cb (GtkNotebook *nb) {</span>
|
||||
<span id="cb9-18"><a href="#cb9-18"></a> notebook_page_close (GTK_NOTEBOOK (nb));</span>
|
||||
<span id="cb9-19"><a href="#cb9-19"></a>}</span></code></pre></div>
|
||||
<p><code>open_cb</code>, <code>new_cb</code>, <code>save_cb</code> and <code>close_cb</code> just call corresponding notebook page functions.</p>
|
||||
<span id="cb9-17"><a href="#cb9-17"></a>close_cb <span class="op">(</span>GtkNotebook <span class="op">*</span>nb<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb9-18"><a href="#cb9-18"></a> notebook_page_close <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">));</span></span>
|
||||
<span id="cb9-19"><a href="#cb9-19"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p><code>open_cb</code>, <code>new_cb</code>, <code>save_cb</code> and
|
||||
<code>close_cb</code> just call corresponding notebook page
|
||||
functions.</p>
|
||||
<h2 id="meson.build">meson.build</h2>
|
||||
<div class="sourceCode" id="cb10"><pre class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb10-1"><a href="#cb10-1"></a>project('tfe', 'c')</span>
|
||||
<div class="sourceCode" id="cb10"><pre
|
||||
class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb10-1"><a href="#cb10-1"></a>project('tfe', 'c')</span>
|
||||
<span id="cb10-2"><a href="#cb10-2"></a></span>
|
||||
<span id="cb10-3"><a href="#cb10-3"></a>gtkdep = dependency('gtk4')</span>
|
||||
<span id="cb10-4"><a href="#cb10-4"></a></span>
|
||||
|
@ -314,13 +393,20 @@ $</code></pre>
|
|||
<span id="cb10-8"><a href="#cb10-8"></a>sourcefiles=files('tfeapplication.c', 'tfenotebook.c', '../tfetextview/tfetextview.c')</span>
|
||||
<span id="cb10-9"><a href="#cb10-9"></a></span>
|
||||
<span id="cb10-10"><a href="#cb10-10"></a>executable('tfe', sourcefiles, resources, dependencies: gtkdep)</span></code></pre></div>
|
||||
<p>In this file, just the source file names are modified from the prior version.</p>
|
||||
<p>In this file, just the source file names are modified from the prior
|
||||
version.</p>
|
||||
<h2 id="source-files">source files</h2>
|
||||
<p>The source files of the text editor <code>tfe</code> will be shown in the next section.</p>
|
||||
<p>You can also download the files from the <a href="https://github.com/ToshioCP/Gtk4-tutorial">repository</a>. There are two options.</p>
|
||||
<p>The source files of the text editor <code>tfe</code> will be shown in
|
||||
the next section.</p>
|
||||
<p>You can also download the files from the <a
|
||||
href="https://github.com/ToshioCP/Gtk4-tutorial">repository</a>. There
|
||||
are two options.</p>
|
||||
<ul>
|
||||
<li>Use git and clone.</li>
|
||||
<li>Run your browser and open the <a href="https://github.com/ToshioCP/Gtk4-tutorial">top page</a>. Then click on “Code” button and click “Download ZIP” in the popup menu. After that, unzip the archive file.</li>
|
||||
<li>Run your browser and open the <a
|
||||
href="https://github.com/ToshioCP/Gtk4-tutorial">top page</a>. Then
|
||||
click on “Code” button and click “Download ZIP” in the popup menu. After
|
||||
that, unzip the archive file.</li>
|
||||
</ul>
|
||||
<p>If you use git, run the terminal and type the following.</p>
|
||||
<pre><code>$ git clone https://github.com/ToshioCP/Gtk4-tutorial.git</code></pre>
|
||||
|
|
461
docs/sec18.html
461
docs/sec18.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,228 +112,336 @@
|
|||
</div>
|
||||
</nav>
|
||||
<h1 id="stateful-action">Stateful action</h1>
|
||||
<p>Some actions have states. The typical values of states is boolean or string. However, other types of states are possible if you want.</p>
|
||||
<p>There’s an example <code>menu2_int16.c</code> in the <code>src/men</code> directory. It behaves the same as <code>menu2.c</code>. But it uses gint16 type of states instead of string type.</p>
|
||||
<p>Some actions have states. The typical values of states is boolean or
|
||||
string. However, other types of states are possible if you want.</p>
|
||||
<p>There’s an example <code>menu2_int16.c</code> in the
|
||||
<code>src/men</code> directory. It behaves the same as
|
||||
<code>menu2.c</code>. But it uses gint16 type of states instead of
|
||||
string type.</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 described after the explanation of this code.</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"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a>app_activate (GApplication *app, gpointer user_data) {</span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a> ... ... ...</span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a> GSimpleAction *act_fullscreen = g_simple_action_new_stateful (<span class="st">"fullscreen"</span>,</span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a> NULL, g_variant_new_boolean (FALSE));</span>
|
||||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a> GMenuItem *menu_item_fullscreen = g_menu_item_new (<span class="st">"Full Screen"</span>, <span class="st">"win.fullscreen"</span>);</span>
|
||||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a> g_signal_connect (act_fullscreen, <span class="st">"change-state"</span>, G_CALLBACK (fullscreen_changed), win);</span>
|
||||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a> ... ... ...</span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a>}</span></code></pre></div>
|
||||
<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 described after
|
||||
the explanation of this code.</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><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></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="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4" 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-5"><a href="#cb1-5" 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-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>
|
||||
<span id="cb1-7"><a href="#cb1-7" 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-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><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 GVariant value which is the boolean value <code>FALSE</code>.</li>
|
||||
<li><code>menu_item_fullscreen</code> is a GMenuItem instance. There are two arguments. The first argument “Full Screen” is a 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>
|
||||
<li>connects the action <code>act_fullscreen</code> and the “change-state” signal 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><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 GVariant value
|
||||
which is the boolean value <code>FALSE</code>.</li>
|
||||
<li><code>menu_item_fullscreen</code> is a GMenuItem instance. There are
|
||||
two arguments. The first argument “Full Screen” is a 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>
|
||||
<li>connects the action <code>act_fullscreen</code> and the
|
||||
“change-state” signal 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>
|
||||
</ul>
|
||||
<p>The following is the “change-state” signal handler.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>fullscreen_changed(GSimpleAction *action, GVariant *value, gpointer win) {</span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a> <span class="cf">if</span> (g_variant_get_boolean (value))</span>
|
||||
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a> gtk_window_maximize (GTK_WINDOW (win));</span>
|
||||
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a> <span class="cf">else</span></span>
|
||||
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a> gtk_window_unmaximize (GTK_WINDOW (win));</span>
|
||||
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a> g_simple_action_set_state (action, value);</span>
|
||||
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a>}</span></code></pre></div>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></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> gpointer win<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></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" aria-hidden="true" tabindex="-1"></a> gtk_window_maximize <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">else</span></span>
|
||||
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> gtk_window_unmaximize <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></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" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>There are 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 unmaximizes.</li>
|
||||
<li>Sets the state of the action with <code>value</code>. Note: the second argument was the toggled state value, but at this stage the state of the action has the original value. So, you need to set the state with the new value by <code>g_simple_action_set_state</code>.</li>
|
||||
<li>There are 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 unmaximizes.</li>
|
||||
<li>Sets the state of the action with <code>value</code>. Note: the
|
||||
second argument was the toggled state value, but at this stage the state
|
||||
of the action 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>
|
||||
<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>GVarient 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"></a>GVariant *value = g_variant_new_boolean (TRUE);</span></code></pre></div>
|
||||
<p>GVarient 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"></a>GVariant *value2 = g_variant_new_string (<span class="st">"Hello"</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 by 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"></a>gboolean <span class="dt">bool</span> = g_variant_get_boolean (value);</span></code></pre></div>
|
||||
<p>Because <code>value</code> has been created as a boolean type GVariant and <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"></a><span class="dt">const</span> <span class="dt">char</span> *str = g_variant_get_string (value2, NULL);</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 length of the string will be set by the function. If it is NULL, nothing happens. The returned string <code>str</code> can’t be changed.</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 certain widget. One action is connected to the three menus. The action has a state which values are “red”, “green” and “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"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a>app_activate (GApplication *app, gpointer user_data) {</span>
|
||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a> ... ... ...</span>
|
||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a> GSimpleAction *act_color = g_simple_action_new_stateful (<span class="st">"color"</span>,</span>
|
||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a> g_variant_type_new(<span class="st">"s"</span>), g_variant_new_string (<span class="st">"red"</span>));</span>
|
||||
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a> GMenuItem *menu_item_red = g_menu_item_new (<span class="st">"Red"</span>, <span class="st">"win.color::red"</span>);</span>
|
||||
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a> GMenuItem *menu_item_green = g_menu_item_new (<span class="st">"Green"</span>, <span class="st">"win.color::green"</span>);</span>
|
||||
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a> GMenuItem *menu_item_blue = g_menu_item_new (<span class="st">"Blue"</span>, <span class="st">"win.color::blue"</span>);</span>
|
||||
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a> g_signal_connect (act_color, <span class="st">"activate"</span>, G_CALLBACK (color_activated), win);</span>
|
||||
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a> ... ... ...</span>
|
||||
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a>}</span></code></pre></div>
|
||||
<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 by
|
||||
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>Because <code>value</code> has been created as a boolean type
|
||||
GVariant and <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 length of the
|
||||
string will be set by the function. If it is NULL, nothing happens. The
|
||||
returned string <code>str</code> can’t be changed.</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 certain widget. One action is connected to the three menus. The action
|
||||
has a state which values are “red”, “green” and “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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></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="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> GSimpleAction <span class="op">*</span>act_color <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">"color"</span><span class="op">,</span></span>
|
||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> g_variant_type_new<span class="op">(</span><span class="st">"s"</span><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-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">"win.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">"win.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">"win.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> win<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>
|
||||
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li><code>act_color</code> is 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. GVariantType will be explained in the next subsection. The function <code>g_variant_new_string ("red")</code> returns a GVariant value which has the string value “red”.</li>
|
||||
<li><code>menu_item_red</code> is a GMenuItem instance. There are 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 “win”, 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>connects the action <code>act_color</code> and the “activate” signal 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. No handler is connected to “change-state” signal. Then the default behavior is to call <code>g_simple_action_set_state()</code> to set the state to the requested value.</li>
|
||||
<li><code>act_color</code> is 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. GVariantType will be
|
||||
explained in the next subsection. The function
|
||||
<code>g_variant_new_string ("red")</code> returns a GVariant value which
|
||||
has the string value “red”.</li>
|
||||
<li><code>menu_item_red</code> is a GMenuItem instance. There are 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 “win”, 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>connects the action <code>act_color</code> and the “activate” signal
|
||||
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. No handler is connected
|
||||
to “change-state” signal. Then the default behavior is to call
|
||||
<code>g_simple_action_set_state()</code> to set the state to the
|
||||
requested value.</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"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a>color_activated(GSimpleAction *action, GVariant *parameter, gpointer win) {</span>
|
||||
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a> <span class="dt">char</span> *color = g_strdup_printf (<span class="st">"label#lb {background-color: %s;}"</span>,</span>
|
||||
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a> g_variant_get_string (parameter, NULL));</span>
|
||||
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a> gtk_css_provider_load_from_data (provider, color, -<span class="dv">1</span>);</span>
|
||||
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a> g_free (color);</span>
|
||||
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a> g_action_change_state (G_ACTION (action), parameter);</span>
|
||||
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>}</span></code></pre></div>
|
||||
<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> gpointer win<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>There are three parameters. The first parameter is the action which emits the “activate” signal. The second parameter is the parameter given to the action. It is a color specified by the menu. The third parameter is a user data which is set in <code>g_signal_connect</code>.</li>
|
||||
<li><code>color</code> is a CSS string created by <code>g_strdup_printf</code>. The parameter of <code>g_strdup_printf</code> is the same as printf C standard function. <code>g_variant_get_string</code> gets the string contained in <code>parameter</code>. You mustn’t change or free the string.</li>
|
||||
<li>There are three parameters. The first parameter is the action which
|
||||
emits the “activate” signal. The second parameter is the parameter given
|
||||
to the action. It is a color specified by the menu. The third parameter
|
||||
is a user data which is set in <code>g_signal_connect</code>.</li>
|
||||
<li><code>color</code> is a CSS string created by
|
||||
<code>g_strdup_printf</code>. The parameter of
|
||||
<code>g_strdup_printf</code> is the same as printf C standard function.
|
||||
<code>g_variant_get_string</code> gets the string contained in
|
||||
<code>parameter</code>. You mustn’t change or free the string.</li>
|
||||
<li>Sets the color of the css provider.</li>
|
||||
<li>Frees the string <code>color</code>.</li>
|
||||
<li>Changes the state by <code>g_action_change_state</code>. The function just sets the state of the action to the parameter by <code>g_simple_action_set_state</code>. Therefore, you can use <code>g_simple_action_set_state</code> instead of <code>g_action_change_state</code>.</li>
|
||||
<li>Changes the state by <code>g_action_change_state</code>. The
|
||||
function just sets the state of the action to the parameter by
|
||||
<code>g_simple_action_set_state</code>. Therefore, you can use
|
||||
<code>g_simple_action_set_state</code> instead of
|
||||
<code>g_action_change_state</code>.</li>
|
||||
</ul>
|
||||
<p>Note: If you have set a “change-state” signal handler, <code>g_action_change_state</code> will emit “change-state” signal instead of calling <code>g_simple_action_set_state</code>.</p>
|
||||
<p>Note: If you have set a “change-state” signal handler,
|
||||
<code>g_action_change_state</code> will emit “change-state” signal
|
||||
instead of calling <code>g_simple_action_set_state</code>.</p>
|
||||
<h3 id="gvarianttype">GVariantType</h3>
|
||||
<p>GVariantType gives a type of GVariant. GVariant can contain many kinds of types. And the type often needs to be recognized at runtime. GVariantType provides such functionality.</p>
|
||||
<p>GVariantType gives a type of GVariant. GVariant can contain many
|
||||
kinds of types. And the type often needs to be recognized at runtime.
|
||||
GVariantType provides such functionality.</p>
|
||||
<p>GVariantType is created with a string which expresses a type.</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>
|
||||
<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="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb9-5"><a href="#cb9-5"></a> GVariantType *vtype = g_variant_type_new (<span class="st">"s"</span>);</span>
|
||||
<span id="cb9-6"><a href="#cb9-6"></a> <span class="dt">const</span> <span class="dt">char</span> *type_string = g_variant_type_peek_string (vtype);</span>
|
||||
<span id="cb9-7"><a href="#cb9-7"></a> g_print (<span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span>,type_string);</span>
|
||||
<span id="cb9-8"><a href="#cb9-8"></a>}</span></code></pre></div>
|
||||
<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><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li><code>g_variant_type_new</code> creates GVariantType. It uses a type string “s” which means string.</li>
|
||||
<li><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.</li>
|
||||
<li><code>g_variant_type_new</code> creates GVariantType. It uses a type
|
||||
string “s” which means string.</li>
|
||||
<li><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.</li>
|
||||
<li>prints the string to the terminal.</li>
|
||||
</ul>
|
||||
<h2 id="example-code">Example code</h2>
|
||||
<p>The following code includes stateful actions above. This program has menus like this:</p>
|
||||
<p>The following code includes stateful actions above. This program has
|
||||
menus like this:</p>
|
||||
<figure>
|
||||
<img src="image/menu2.png" alt="" /><figcaption>menu2</figcaption>
|
||||
<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, which is the child widget of 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>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, which is the child widget of 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>
|
||||
<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="dt">static</span> GtkCssProvider *provider;</span>
|
||||
<span id="cb10-3"><a href="#cb10-3"></a><span class="dt">static</span> GtkCssProvider <span class="op">*</span>provider<span class="op">;</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4"></a></span>
|
||||
<span id="cb10-5"><a href="#cb10-5"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-6"><a href="#cb10-6"></a>fullscreen_changed(GSimpleAction *action, GVariant *value, gpointer win) {</span>
|
||||
<span id="cb10-7"><a href="#cb10-7"></a> <span class="cf">if</span> (g_variant_get_boolean (value))</span>
|
||||
<span id="cb10-8"><a href="#cb10-8"></a> gtk_window_maximize (GTK_WINDOW (win));</span>
|
||||
<span id="cb10-6"><a href="#cb10-6"></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> gpointer win<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb10-7"><a href="#cb10-7"></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-8"><a href="#cb10-8"></a> gtk_window_maximize <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb10-9"><a href="#cb10-9"></a> <span class="cf">else</span></span>
|
||||
<span id="cb10-10"><a href="#cb10-10"></a> gtk_window_unmaximize (GTK_WINDOW (win));</span>
|
||||
<span id="cb10-11"><a href="#cb10-11"></a> g_simple_action_set_state (action, value);</span>
|
||||
<span id="cb10-12"><a href="#cb10-12"></a>}</span>
|
||||
<span id="cb10-10"><a href="#cb10-10"></a> gtk_window_unmaximize <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb10-11"><a href="#cb10-11"></a> g_simple_action_set_state <span class="op">(</span>action<span class="op">,</span> value<span class="op">);</span></span>
|
||||
<span id="cb10-12"><a href="#cb10-12"></a><span class="op">}</span></span>
|
||||
<span id="cb10-13"><a href="#cb10-13"></a></span>
|
||||
<span id="cb10-14"><a href="#cb10-14"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-15"><a href="#cb10-15"></a>color_activated(GSimpleAction *action, GVariant *parameter, gpointer win) {</span>
|
||||
<span id="cb10-16"><a href="#cb10-16"></a> <span class="dt">char</span> *color = g_strdup_printf (<span class="st">"label#lb {background-color: %s;}"</span>, g_variant_get_string (parameter, NULL));</span>
|
||||
<span id="cb10-17"><a href="#cb10-17"></a> gtk_css_provider_load_from_data (provider, color, -<span class="dv">1</span>);</span>
|
||||
<span id="cb10-18"><a href="#cb10-18"></a> g_free (color);</span>
|
||||
<span id="cb10-19"><a href="#cb10-19"></a> g_action_change_state (G_ACTION (action), parameter);</span>
|
||||
<span id="cb10-20"><a href="#cb10-20"></a>}</span>
|
||||
<span id="cb10-15"><a href="#cb10-15"></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> gpointer win<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb10-16"><a href="#cb10-16"></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-17"><a href="#cb10-17"></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-18"><a href="#cb10-18"></a> g_free <span class="op">(</span>color<span class="op">);</span></span>
|
||||
<span id="cb10-19"><a href="#cb10-19"></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-20"><a href="#cb10-20"></a><span class="op">}</span></span>
|
||||
<span id="cb10-21"><a href="#cb10-21"></a></span>
|
||||
<span id="cb10-22"><a href="#cb10-22"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-23"><a href="#cb10-23"></a>quit_activated(GSimpleAction *action, GVariant *parameter, gpointer app)</span>
|
||||
<span id="cb10-24"><a href="#cb10-24"></a>{</span>
|
||||
<span id="cb10-25"><a href="#cb10-25"></a> g_application_quit (G_APPLICATION(app));</span>
|
||||
<span id="cb10-26"><a href="#cb10-26"></a>}</span>
|
||||
<span id="cb10-23"><a href="#cb10-23"></a>quit_activated<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer app<span class="op">)</span></span>
|
||||
<span id="cb10-24"><a href="#cb10-24"></a><span class="op">{</span></span>
|
||||
<span id="cb10-25"><a href="#cb10-25"></a> g_application_quit <span class="op">(</span>G_APPLICATION<span class="op">(</span>app<span class="op">));</span></span>
|
||||
<span id="cb10-26"><a href="#cb10-26"></a><span class="op">}</span></span>
|
||||
<span id="cb10-27"><a href="#cb10-27"></a></span>
|
||||
<span id="cb10-28"><a href="#cb10-28"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-29"><a href="#cb10-29"></a>app_activate (GApplication *app, gpointer user_data) {</span>
|
||||
<span id="cb10-30"><a href="#cb10-30"></a> GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));</span>
|
||||
<span id="cb10-31"><a href="#cb10-31"></a> gtk_window_set_title (GTK_WINDOW (win), <span class="st">"menu2"</span>);</span>
|
||||
<span id="cb10-32"><a href="#cb10-32"></a> gtk_window_set_default_size (GTK_WINDOW (win), <span class="dv">400</span>, <span class="dv">300</span>);</span>
|
||||
<span id="cb10-29"><a href="#cb10-29"></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="cb10-30"><a href="#cb10-30"></a> GtkWidget <span class="op">*</span>win <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-31"><a href="#cb10-31"></a> gtk_window_set_title <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> <span class="st">"menu2"</span><span class="op">);</span></span>
|
||||
<span id="cb10-32"><a href="#cb10-32"></a> gtk_window_set_default_size <span class="op">(</span>GTK_WINDOW <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-33"><a href="#cb10-33"></a></span>
|
||||
<span id="cb10-34"><a href="#cb10-34"></a> GtkWidget *lb = gtk_label_new (NULL);</span>
|
||||
<span id="cb10-35"><a href="#cb10-35"></a> gtk_widget_set_name (lb, <span class="st">"lb"</span>); <span class="co">/* the name is used by CSS Selector */</span></span>
|
||||
<span id="cb10-36"><a href="#cb10-36"></a> gtk_window_set_child (GTK_WINDOW (win), lb);</span>
|
||||
<span id="cb10-34"><a href="#cb10-34"></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-35"><a href="#cb10-35"></a> gtk_widget_set_name <span class="op">(</span>lb<span class="op">,</span> <span class="st">"lb"</span><span class="op">);</span> <span class="co">/* the name is used by CSS Selector */</span></span>
|
||||
<span id="cb10-36"><a href="#cb10-36"></a> gtk_window_set_child <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> lb<span class="op">);</span></span>
|
||||
<span id="cb10-37"><a href="#cb10-37"></a></span>
|
||||
<span id="cb10-38"><a href="#cb10-38"></a> GSimpleAction *act_fullscreen</span>
|
||||
<span id="cb10-39"><a href="#cb10-39"></a> = g_simple_action_new_stateful (<span class="st">"fullscreen"</span>, NULL, g_variant_new_boolean (FALSE));</span>
|
||||
<span id="cb10-40"><a href="#cb10-40"></a> GSimpleAction *act_color</span>
|
||||
<span id="cb10-41"><a href="#cb10-41"></a> = g_simple_action_new_stateful (<span class="st">"color"</span>, g_variant_type_new(<span class="st">"s"</span>), g_variant_new_string (<span class="st">"red"</span>));</span>
|
||||
<span id="cb10-42"><a href="#cb10-42"></a> GSimpleAction *act_quit</span>
|
||||
<span id="cb10-43"><a href="#cb10-43"></a> = g_simple_action_new (<span class="st">"quit"</span>, NULL);</span>
|
||||
<span id="cb10-38"><a href="#cb10-38"></a> GSimpleAction <span class="op">*</span>act_fullscreen</span>
|
||||
<span id="cb10-39"><a href="#cb10-39"></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-40"><a href="#cb10-40"></a> GSimpleAction <span class="op">*</span>act_color</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">"color"</span><span class="op">,</span> g_variant_type_new<span class="op">(</span><span class="st">"s"</span><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-42"><a href="#cb10-42"></a> GSimpleAction <span class="op">*</span>act_quit</span>
|
||||
<span id="cb10-43"><a href="#cb10-43"></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-44"><a href="#cb10-44"></a></span>
|
||||
<span id="cb10-45"><a href="#cb10-45"></a> GMenu *menubar = g_menu_new ();</span>
|
||||
<span id="cb10-46"><a href="#cb10-46"></a> GMenu *menu = g_menu_new ();</span>
|
||||
<span id="cb10-47"><a href="#cb10-47"></a> GMenu *section1 = g_menu_new ();</span>
|
||||
<span id="cb10-48"><a href="#cb10-48"></a> GMenu *section2 = g_menu_new ();</span>
|
||||
<span id="cb10-49"><a href="#cb10-49"></a> GMenu *section3 = g_menu_new ();</span>
|
||||
<span id="cb10-50"><a href="#cb10-50"></a> GMenuItem *menu_item_fullscreen = g_menu_item_new (<span class="st">"Full Screen"</span>, <span class="st">"win.fullscreen"</span>);</span>
|
||||
<span id="cb10-51"><a href="#cb10-51"></a> GMenuItem *menu_item_red = g_menu_item_new (<span class="st">"Red"</span>, <span class="st">"win.color::red"</span>);</span>
|
||||
<span id="cb10-52"><a href="#cb10-52"></a> GMenuItem *menu_item_green = g_menu_item_new (<span class="st">"Green"</span>, <span class="st">"win.color::green"</span>);</span>
|
||||
<span id="cb10-53"><a href="#cb10-53"></a> GMenuItem *menu_item_blue = g_menu_item_new (<span class="st">"Blue"</span>, <span class="st">"win.color::blue"</span>);</span>
|
||||
<span id="cb10-54"><a href="#cb10-54"></a> GMenuItem *menu_item_quit = g_menu_item_new (<span class="st">"Quit"</span>, <span class="st">"app.quit"</span>);</span>
|
||||
<span id="cb10-45"><a href="#cb10-45"></a> GMenu <span class="op">*</span>menubar <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||||
<span id="cb10-46"><a href="#cb10-46"></a> GMenu <span class="op">*</span>menu <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||||
<span id="cb10-47"><a href="#cb10-47"></a> GMenu <span class="op">*</span>section1 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||||
<span id="cb10-48"><a href="#cb10-48"></a> GMenu <span class="op">*</span>section2 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||||
<span id="cb10-49"><a href="#cb10-49"></a> GMenu <span class="op">*</span>section3 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
|
||||
<span id="cb10-50"><a href="#cb10-50"></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-51"><a href="#cb10-51"></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">"win.color::red"</span><span class="op">);</span></span>
|
||||
<span id="cb10-52"><a href="#cb10-52"></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">"win.color::green"</span><span class="op">);</span></span>
|
||||
<span id="cb10-53"><a href="#cb10-53"></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">"win.color::blue"</span><span class="op">);</span></span>
|
||||
<span id="cb10-54"><a href="#cb10-54"></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-55"><a href="#cb10-55"></a></span>
|
||||
<span id="cb10-56"><a href="#cb10-56"></a> g_signal_connect (act_fullscreen, <span class="st">"change-state"</span>, G_CALLBACK (fullscreen_changed), win);</span>
|
||||
<span id="cb10-57"><a href="#cb10-57"></a> g_signal_connect (act_color, <span class="st">"activate"</span>, G_CALLBACK (color_activated), win);</span>
|
||||
<span id="cb10-58"><a href="#cb10-58"></a> g_signal_connect (act_quit, <span class="st">"activate"</span>, G_CALLBACK (quit_activated), app);</span>
|
||||
<span id="cb10-59"><a href="#cb10-59"></a> g_action_map_add_action (G_ACTION_MAP (win), G_ACTION (act_fullscreen));</span>
|
||||
<span id="cb10-60"><a href="#cb10-60"></a> g_action_map_add_action (G_ACTION_MAP (win), G_ACTION (act_color));</span>
|
||||
<span id="cb10-61"><a href="#cb10-61"></a> g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_quit));</span>
|
||||
<span id="cb10-56"><a href="#cb10-56"></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-57"><a href="#cb10-57"></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> win<span class="op">);</span></span>
|
||||
<span id="cb10-58"><a href="#cb10-58"></a> g_signal_connect <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>quit_activated<span class="op">),</span> app<span class="op">);</span></span>
|
||||
<span id="cb10-59"><a href="#cb10-59"></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-60"><a href="#cb10-60"></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_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> g_menu_append_item (section1, menu_item_fullscreen);</span>
|
||||
<span id="cb10-64"><a href="#cb10-64"></a> g_menu_append_item (section2, menu_item_red);</span>
|
||||
<span id="cb10-65"><a href="#cb10-65"></a> g_menu_append_item (section2, menu_item_green);</span>
|
||||
<span id="cb10-66"><a href="#cb10-66"></a> g_menu_append_item (section2, menu_item_blue);</span>
|
||||
<span id="cb10-67"><a href="#cb10-67"></a> g_menu_append_item (section3, menu_item_quit);</span>
|
||||
<span id="cb10-68"><a href="#cb10-68"></a> g_object_unref (menu_item_red);</span>
|
||||
<span id="cb10-69"><a href="#cb10-69"></a> g_object_unref (menu_item_green);</span>
|
||||
<span id="cb10-70"><a href="#cb10-70"></a> g_object_unref (menu_item_blue);</span>
|
||||
<span id="cb10-71"><a href="#cb10-71"></a> g_object_unref (menu_item_fullscreen);</span>
|
||||
<span id="cb10-72"><a href="#cb10-72"></a> g_object_unref (menu_item_quit);</span>
|
||||
<span id="cb10-63"><a href="#cb10-63"></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-64"><a href="#cb10-64"></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-65"><a href="#cb10-65"></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-66"><a href="#cb10-66"></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-67"><a href="#cb10-67"></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-68"><a href="#cb10-68"></a> g_object_unref <span class="op">(</span>menu_item_red<span class="op">);</span></span>
|
||||
<span id="cb10-69"><a href="#cb10-69"></a> g_object_unref <span class="op">(</span>menu_item_green<span class="op">);</span></span>
|
||||
<span id="cb10-70"><a href="#cb10-70"></a> g_object_unref <span class="op">(</span>menu_item_blue<span class="op">);</span></span>
|
||||
<span id="cb10-71"><a href="#cb10-71"></a> g_object_unref <span class="op">(</span>menu_item_fullscreen<span class="op">);</span></span>
|
||||
<span id="cb10-72"><a href="#cb10-72"></a> g_object_unref <span class="op">(</span>menu_item_quit<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_section (menu, NULL, G_MENU_MODEL (section1));</span>
|
||||
<span id="cb10-75"><a href="#cb10-75"></a> g_menu_append_section (menu, <span class="st">"Color"</span>, G_MENU_MODEL (section2));</span>
|
||||
<span id="cb10-76"><a href="#cb10-76"></a> g_menu_append_section (menu, NULL, G_MENU_MODEL (section3));</span>
|
||||
<span id="cb10-77"><a href="#cb10-77"></a> g_menu_append_submenu (menubar, <span class="st">"Menu"</span>, G_MENU_MODEL (menu));</span>
|
||||
<span id="cb10-74"><a href="#cb10-74"></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-75"><a href="#cb10-75"></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-76"><a href="#cb10-76"></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-77"><a href="#cb10-77"></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-78"><a href="#cb10-78"></a></span>
|
||||
<span id="cb10-79"><a href="#cb10-79"></a> gtk_application_set_menubar (GTK_APPLICATION (app), G_MENU_MODEL (menubar));</span>
|
||||
<span id="cb10-80"><a href="#cb10-80"></a> gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);</span>
|
||||
<span id="cb10-79"><a href="#cb10-79"></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-80"><a href="#cb10-80"></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-81"><a href="#cb10-81"></a></span>
|
||||
<span id="cb10-82"><a href="#cb10-82"></a><span class="co">/* GtkCssProvider *provider = gtk_css_provider_new ();*/</span></span>
|
||||
<span id="cb10-83"><a href="#cb10-83"></a> provider = gtk_css_provider_new ();</span>
|
||||
<span id="cb10-84"><a href="#cb10-84"></a> GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (win));</span>
|
||||
<span id="cb10-85"><a href="#cb10-85"></a> gtk_css_provider_load_from_data (provider, <span class="st">"label#lb {background-color: red;}"</span>, -<span class="dv">1</span>);</span>
|
||||
<span id="cb10-86"><a href="#cb10-86"></a> gtk_style_context_add_provider_for_display (display, GTK_STYLE_PROVIDER (provider),</span>
|
||||
<span id="cb10-87"><a href="#cb10-87"></a> GTK_STYLE_PROVIDER_PRIORITY_USER);</span>
|
||||
<span id="cb10-83"><a href="#cb10-83"></a> provider <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span>
|
||||
<span id="cb10-84"><a href="#cb10-84"></a> GdkDisplay <span class="op">*</span>display <span class="op">=</span> gtk_widget_get_display <span class="op">(</span>GTK_WIDGET <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb10-85"><a href="#cb10-85"></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-86"><a href="#cb10-86"></a> gtk_style_context_add_provider_for_display <span class="op">(</span>display<span class="op">,</span> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">),</span></span>
|
||||
<span id="cb10-87"><a href="#cb10-87"></a> GTK_STYLE_PROVIDER_PRIORITY_USER<span class="op">);</span></span>
|
||||
<span id="cb10-88"><a href="#cb10-88"></a></span>
|
||||
<span id="cb10-89"><a href="#cb10-89"></a><span class="co">/* gtk_widget_show (win);*/</span></span>
|
||||
<span id="cb10-90"><a href="#cb10-90"></a> gtk_window_present (GTK_WINDOW (win));</span>
|
||||
<span id="cb10-91"><a href="#cb10-91"></a>}</span>
|
||||
<span id="cb10-90"><a href="#cb10-90"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb10-91"><a href="#cb10-91"></a><span class="op">}</span></span>
|
||||
<span id="cb10-92"><a href="#cb10-92"></a></span>
|
||||
<span id="cb10-93"><a href="#cb10-93"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.menu2"</span></span>
|
||||
<span id="cb10-94"><a href="#cb10-94"></a></span>
|
||||
<span id="cb10-95"><a href="#cb10-95"></a><span class="dt">int</span></span>
|
||||
<span id="cb10-96"><a href="#cb10-96"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb10-97"><a href="#cb10-97"></a> GtkApplication *app;</span>
|
||||
<span id="cb10-98"><a href="#cb10-98"></a> <span class="dt">int</span> stat;</span>
|
||||
<span id="cb10-96"><a href="#cb10-96"></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-97"><a href="#cb10-97"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb10-98"><a href="#cb10-98"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb10-99"><a href="#cb10-99"></a></span>
|
||||
<span id="cb10-100"><a href="#cb10-100"></a> app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);</span>
|
||||
<span id="cb10-101"><a href="#cb10-101"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</span>
|
||||
<span id="cb10-100"><a href="#cb10-100"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_FLAGS_NONE<span class="op">);</span></span>
|
||||
<span id="cb10-101"><a href="#cb10-101"></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-102"><a href="#cb10-102"></a></span>
|
||||
<span id="cb10-103"><a href="#cb10-103"></a> stat =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb10-104"><a href="#cb10-104"></a> g_object_unref (app);</span>
|
||||
<span id="cb10-105"><a href="#cb10-105"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb10-106"><a href="#cb10-106"></a>}</span></code></pre></div>
|
||||
<span id="cb10-103"><a href="#cb10-103"></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-104"><a href="#cb10-104"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb10-105"><a href="#cb10-105"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb10-106"><a href="#cb10-106"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>5-26: Signal handlers. They have already been explained.</li>
|
||||
<li>30-36: <code>win</code> and <code>lb</code> are GtkApplicationWindow and GtkLabel respectively. <code>win</code> has a title “menu2” and its default size is 400x300. <code>lb</code> is named as “lb”. The name is used in CSS. <code>lb</code> is set to <code>win</code> as a child.</li>
|
||||
<li>30-36: <code>win</code> and <code>lb</code> are GtkApplicationWindow
|
||||
and GtkLabel respectively. <code>win</code> has a title “menu2” and its
|
||||
default size is 400x300. <code>lb</code> is named as “lb”. The name is
|
||||
used in CSS. <code>lb</code> is set to <code>win</code> as a child.</li>
|
||||
<li>38-43: Three actions are defined. They are:
|
||||
<ul>
|
||||
<li>stateful and has no parameter. It has a toggle state.</li>
|
||||
|
@ -341,10 +449,33 @@
|
|||
<li>stateless and has no parameter.</li>
|
||||
</ul></li>
|
||||
<li>45-54: Creates GMenu and GMenuItem. There are three sections.</li>
|
||||
<li>56-61: Signals are connected to handlers. And actions are added to GActionMap. Because <code>act_fullscreen</code> and <code>act_color</code> have “win” prefix and belong to GtkApplicationWindow, they are added to <code>win</code>. GtkApplicationWindow implements GActionModel interface like GtkApplication. <code>act_quit</code> has “app” prefix and belongs to GtkApplication. It is added to <code>app</code>.</li>
|
||||
<li>63-77: Connects and builds the menus. Useless GMenuItem are freed.</li>
|
||||
<li>79-80: GMenuModel <code>menubar</code> is inserted to <code>app</code>. Sets show menubar property of <code>win</code> to <code>TRUE</code>. Note: <code>gtk_application_window_set_show_menubar</code> creates GtkPopoverMenubar from GMenuModel. This is a different point between Gtk3 and Gtk4. And you can use GtkPopoverMenubar directly and set it as a descendant widget of the window. You may use GtkBox as a child widget of the window and insert GtkPopoverMenubar as the first child of the box.</li>
|
||||
<li>82-87: Sets CSS. <code>provider</code> is GtkCssProvider which is defined in line three as a static variable. Its CSS data is: <code>label#lb {background-color: red;}</code>. “label#lb” is called selector. “label” is the node of GtkLabel. “#” precedes an ID which is an identifiable name of the widget. “lb” is the name of GtkLabel <code>lb</code>. (See line 35). The style is surrounded by open and close braces. The style is applied to GtkLabel which has a name “lb”. Other GtkLabel have no effect from this. The provider is added to GdkDisplay.</li>
|
||||
<li>56-61: Signals are connected to handlers. And actions are added to
|
||||
GActionMap. Because <code>act_fullscreen</code> and
|
||||
<code>act_color</code> have “win” prefix and belong to
|
||||
GtkApplicationWindow, they are added to <code>win</code>.
|
||||
GtkApplicationWindow implements GActionModel interface like
|
||||
GtkApplication. <code>act_quit</code> has “app” prefix and belongs to
|
||||
GtkApplication. It is added to <code>app</code>.</li>
|
||||
<li>63-77: Connects and builds the menus. Useless GMenuItem are
|
||||
freed.</li>
|
||||
<li>79-80: GMenuModel <code>menubar</code> is inserted to
|
||||
<code>app</code>. Sets show menubar property of <code>win</code> to
|
||||
<code>TRUE</code>. Note:
|
||||
<code>gtk_application_window_set_show_menubar</code> creates
|
||||
GtkPopoverMenubar from GMenuModel. This is a different point between GTK
|
||||
3 and GTK 4. And you can use GtkPopoverMenubar directly and set it as a
|
||||
descendant widget of the window. You may use GtkBox as a child widget of
|
||||
the window and insert GtkPopoverMenubar as the first child of the
|
||||
box.</li>
|
||||
<li>82-87: Sets CSS. <code>provider</code> is GtkCssProvider which is
|
||||
defined in line three as a static variable. Its CSS data is:
|
||||
<code>label#lb {background-color: red;}</code>. “label#lb” is called
|
||||
selector. “label” is the node of GtkLabel. “#” precedes an ID which is
|
||||
an identifiable name of the widget. “lb” is the name of GtkLabel
|
||||
<code>lb</code>. (See line 35). The style is surrounded by open and
|
||||
close braces. The style is applied to GtkLabel which has a name “lb”.
|
||||
Other GtkLabel have no effect from this. The provider is added to
|
||||
GdkDisplay.</li>
|
||||
<li>90: Shows the window.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
241
docs/sec2.html
241
docs/sec2.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;}
|
||||
|
@ -111,27 +111,38 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 id="installing-gtk4-into-linux-distributions">Installing Gtk4 into Linux distributions</h1>
|
||||
<p>This section describes how to install Gtk4 into Linux distributions.</p>
|
||||
<p>This tutorial is without any warranty. If you want to install Gtk4 to your computer, do it at your own risk.</p>
|
||||
<p>The information in this section is the one on April/27/2022. The words ‘at present’ and/or ‘now’ in this section means ‘April/27/2022’.</p>
|
||||
<p>There are three possible way to install Gtk4.</p>
|
||||
<h1 id="installing-gtk-4-into-linux-distributions">Installing GTK 4 into
|
||||
Linux distributions</h1>
|
||||
<p>This section describes how to install GTK 4 into Linux
|
||||
distributions.</p>
|
||||
<p>This tutorial is without any warranty. If you want to install GTK 4
|
||||
to your computer, do it at your own risk.</p>
|
||||
<p>The information in this section is the one on April/27/2022. The
|
||||
words ‘at present’ and/or ‘now’ in this section means
|
||||
‘April/27/2022’.</p>
|
||||
<p>There are three possible way to install GTK 4.</p>
|
||||
<ul>
|
||||
<li>Install it from the distribution packages.</li>
|
||||
<li>Build it from the source file.</li>
|
||||
<li>Install a Gnome 40 distribution with the gnome-boxes.</li>
|
||||
<li>Install a GNOME 40 distribution with the GNOME Boxes.</li>
|
||||
</ul>
|
||||
<h2 id="installation-from-the-distribution-packages">Installation from the distribution packages</h2>
|
||||
<p>The first way is easy to install. It is a recommended way. I’ve installed Gtk4 packages in Ubuntu 21.04. (Now, my Ubuntu version is 21.10).</p>
|
||||
<h2 id="installation-from-the-distribution-packages">Installation from
|
||||
the distribution packages</h2>
|
||||
<p>The first way is easy to install. It is a recommended way. I’ve
|
||||
installed GTK 4 packages in Ubuntu 21.04. (Now, my Ubuntu version is
|
||||
21.10).</p>
|
||||
<pre><code>$ sudo apt-get install libgtk-4-bin libgtk-4-common libgtk-4-dev libgtk-4-doc</code></pre>
|
||||
<p>Fedora, Arch, Debian and OpenSUSE are also possible. See <a href="https://www.gtk.org/docs/installations/linux#installing-gtk-from-packages">Installing GTK from packages</a>. The following table shows the distributions which support Gtk4.</p>
|
||||
<p>Fedora, Arch, Debian and OpenSUSE are also possible. See <a
|
||||
href="https://www.gtk.org/docs/installations/linux#installing-gtk-from-packages">Installing
|
||||
GTK from packages</a>. The following table shows the distributions which
|
||||
support GTK 4.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="header">
|
||||
<th style="text-align: center;">Distribution</th>
|
||||
<th style="text-align: center;">version</th>
|
||||
<th style="text-align: center;">Gtk4</th>
|
||||
<th style="text-align: center;">Gnome40</th>
|
||||
<th style="text-align: center;">GTK 4</th>
|
||||
<th style="text-align: center;">GNOME 40</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -139,75 +150,106 @@
|
|||
<td style="text-align: center;">Fedora</td>
|
||||
<td style="text-align: center;">36</td>
|
||||
<td style="text-align: center;">4.4.2</td>
|
||||
<td style="text-align: center;">Gnome42</td>
|
||||
<td style="text-align: center;">GNOME 42</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: center;">Ubuntu</td>
|
||||
<td style="text-align: center;">22.04lts</td>
|
||||
<td style="text-align: center;">4.4</td>
|
||||
<td style="text-align: center;">Gnome41(4.6.2)</td>
|
||||
<td style="text-align: center;">GNOME 41(4.6.2)</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td style="text-align: center;">Debian</td>
|
||||
<td style="text-align: center;">bookworm(testing)</td>
|
||||
<td style="text-align: center;">4.6.5</td>
|
||||
<td style="text-align: center;">Gnome42</td>
|
||||
<td style="text-align: center;">GNOME 42</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: center;">Arch</td>
|
||||
<td style="text-align: center;">rolling release</td>
|
||||
<td style="text-align: center;">4.6.5</td>
|
||||
<td style="text-align: center;">Gnome42</td>
|
||||
<td style="text-align: center;">GNOME 42</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td style="text-align: center;">Gentoo</td>
|
||||
<td style="text-align: center;">rolling release</td>
|
||||
<td style="text-align: center;">4.6.5</td>
|
||||
<td style="text-align: center;">Gnome42</td>
|
||||
<td style="text-align: center;">GNOME 42</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: center;">OpenSUSE</td>
|
||||
<td style="text-align: center;">Tumbleweed(rolling release)</td>
|
||||
<td style="text-align: center;">4.6.5</td>
|
||||
<td style="text-align: center;">Gnome42</td>
|
||||
<td style="text-align: center;">GNOME 42</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>If you’ve installed Gtk4 from the packages, you don’t need to read the rest of this section.</p>
|
||||
<h2 id="installation-from-the-source-file">Installation from the source file</h2>
|
||||
<p>If your operating system doesn’t have Gtk4 packages, you need to build it from the source. Or, if you want the latest version of Gtk4 (4.6.3), you also need to build it from the source.</p>
|
||||
<p>I installed Gtk4 from the source in January 2021. So, the following information is old, especially for the version of each software. For the latest information, see <a href="https://docs.gtk.org/gtk4/building.html">Gtk API Reference, Building GTK</a>.</p>
|
||||
<h3 id="prerequisites-for-gtk4-installation">Prerequisites for Gtk4 installation</h3>
|
||||
<p>If you’ve installed GTK 4 from the packages, you don’t need to read
|
||||
the rest of this section.</p>
|
||||
<h2 id="installation-from-the-source-file">Installation from the source
|
||||
file</h2>
|
||||
<p>If your operating system doesn’t have GTK 4 packages, you need to
|
||||
build it from the source. Or, if you want the latest version of GTK 4
|
||||
(4.6.3), you also need to build it from the source.</p>
|
||||
<p>I installed GTK 4 from the source in January 2021. So, the following
|
||||
information is old, especially for the version of each software. For the
|
||||
latest information, see <a
|
||||
href="https://docs.gtk.org/gtk4/building.html">GTK API Reference,
|
||||
Building GTK</a>.</p>
|
||||
<h3 id="prerequisites-for-gtk-4-installation">Prerequisites for GTK 4
|
||||
installation</h3>
|
||||
<ul>
|
||||
<li>Linux operating system. For example, Ubuntu 20.10 or 20.04LTS. Other distributions might be OK.</li>
|
||||
<li>Packages for development such as gcc, meson, ninja, git, wget and so on.</li>
|
||||
<li>Linux operating system. For example, Ubuntu 20.10 or 20.04LTS. Other
|
||||
distributions might be OK.</li>
|
||||
<li>Packages for development such as gcc, meson, ninja, git, wget and so
|
||||
on.</li>
|
||||
<li>Dev package is necessary for each software below.</li>
|
||||
</ul>
|
||||
<h3 id="installation-target">Installation target</h3>
|
||||
<p>I installed Gtk4 under the directory <code>$HOME/local</code>. This is a private user area.</p>
|
||||
<p>If you want to install it in the system area, <code>/opt/gtk4</code> is one of good choices. <a href="https://docs.gtk.org/gtk4/building.html">Gtk API Reference, Building GTK</a> gives an installation example to <code>/opt/gtk4</code>.</p>
|
||||
<p>Don’t install it to <code>/usr/local</code> which is the default. It is used by Ubuntu applications which are not build on Gtk4. Therefore, the risk is high and probably bad things will happen. Actually I did it and I needed to reinstall Ubuntu.</p>
|
||||
<p>I installed GTK 4 under the directory <code>$HOME/local</code>. This
|
||||
is a private user area.</p>
|
||||
<p>If you want to install it in the system area, <code>/opt/gtk4</code>
|
||||
is one of good choices. <a
|
||||
href="https://docs.gtk.org/gtk4/building.html">GTK API Reference,
|
||||
Building GTK</a> gives an installation example to
|
||||
<code>/opt/gtk4</code>.</p>
|
||||
<p>Don’t install it to <code>/usr/local</code> which is the default. It
|
||||
is used by Ubuntu applications which are not build on GTK 4. Therefore,
|
||||
the risk is high and probably bad things will happen. Actually I did it
|
||||
and I needed to reinstall Ubuntu.</p>
|
||||
<h3 id="installation-to-ubuntu-20.10">Installation to Ubuntu 20.10</h3>
|
||||
<p>Most of the necessary libraries are included by Ubuntu 20.10. Therefore, they can be installed with <code>apt-get</code> command. You don’t need to install them from the source tarballs. You can skip the subsections below about prerequisite library installation (Glib, Pango, Gdk-pixbuf and Gtk-doc).</p>
|
||||
<h3 id="glib-installation">Glib installation</h3>
|
||||
<p>If your Ubuntu is 20.04LTS, you need to install prerequisite libraries from the tarballs. Check the version of your library and if it is lower than the necessary version, install it from the source.</p>
|
||||
<p>Most of the necessary libraries are included by Ubuntu 20.10.
|
||||
Therefore, they can be installed with <code>apt-get</code> command. You
|
||||
don’t need to install them from the source tarballs. You can skip the
|
||||
subsections below about prerequisite library installation (GLib, Pango,
|
||||
GdkPixbuf and GTK-doc).</p>
|
||||
<h3 id="glib-installation">GLib installation</h3>
|
||||
<p>If your Ubuntu is 20.04LTS, you need to install prerequisite
|
||||
libraries from the tarballs. Check the version of your library and if it
|
||||
is lower than the necessary version, install it from the source.</p>
|
||||
<p>For example,</p>
|
||||
<pre><code>$ pkg-config --modversion glib-2.0
|
||||
2.64.6</code></pre>
|
||||
<p>The necessary version is 2.66.0 or higher. Therefore, the example above shows that you need to install Glib.</p>
|
||||
<p>I installed 2.67.1 which was the latest version at that time (January 2021). Download Glib source files from the repository, then decompress and extract files.</p>
|
||||
<p>The necessary version is 2.66.0 or higher. Therefore, the example
|
||||
above shows that you need to install GLib.</p>
|
||||
<p>I installed 2.67.1 which was the latest version at that time (January
|
||||
2021). Download GLib source files from the repository, then decompress
|
||||
and extract files.</p>
|
||||
<pre><code>$ wget https://download.gnome.org/sources/glib/2.67/glib-2.67.1.tar.xz
|
||||
$ tar -Jxf glib-2.67.1.tar.xz</code></pre>
|
||||
<p>Some packages are required to build Glib. You can find them if you run meson.</p>
|
||||
<p>Some packages are required to build GLib. You can find them if you
|
||||
run meson.</p>
|
||||
<pre><code>$ meson --prefix $HOME/local _build</code></pre>
|
||||
<p>Use apt-get and install the prerequisites. For example,</p>
|
||||
<pre><code>$ sudo apt-get install -y libpcre2-dev libffi-dev</code></pre>
|
||||
<p>After that, compile Glib.</p>
|
||||
<p>After that, compile GLib.</p>
|
||||
<pre><code>$ rm -rf _build
|
||||
$ meson --prefix $HOME/local _build
|
||||
$ ninja -C _build
|
||||
$ ninja -C _build install</code></pre>
|
||||
<p>Set several environment variables so that the Glib libraries installed can be used by build tools. Make a text file below and save it as <code>env.sh</code></p>
|
||||
<p>Set several environment variables so that the GLib libraries
|
||||
installed can be used by build tools. Make a text file below and save it
|
||||
as <code>env.sh</code></p>
|
||||
<pre><code># compiler
|
||||
CPPFLAGS="-I$HOME/local/include"
|
||||
LDFLAGS="-L$HOME/local/lib"
|
||||
|
@ -219,41 +261,65 @@ PATH="$HOME/local/bin:$PATH"
|
|||
export LD_LIBRARY_PATH PATH
|
||||
# gsetting
|
||||
export GSETTINGS_SCHEMA_DIR=$HOME/local/share/glib-2.0/schemas</code></pre>
|
||||
<p>Then, use . (dot) or source command to include these commands to the current bash.</p>
|
||||
<p>Then, use . (dot) or source command to include these commands to the
|
||||
current bash.</p>
|
||||
<pre><code>$ . env.sh</code></pre>
|
||||
<p>or</p>
|
||||
<pre><code>$ source env.sh</code></pre>
|
||||
<p>This command carries out the commands in <code>env.sh</code> and changes the environment variables above in the current shell.</p>
|
||||
<p>This command carries out the commands in <code>env.sh</code> and
|
||||
changes the environment variables above in the current shell.</p>
|
||||
<h3 id="pango-installation">Pango installation</h3>
|
||||
<p>Download and untar.</p>
|
||||
<pre><code>$ wget https://download.gnome.org/sources/pango/1.48/pango-1.48.0.tar.xz
|
||||
$ tar -Jxf pango-1.48.0.tar.xz</code></pre>
|
||||
<p>Try meson and check the required packages. Install all the prerequisites. Then, compile and install Pango.</p>
|
||||
<p>Try meson and check the required packages. Install all the
|
||||
prerequisites. Then, compile and install Pango.</p>
|
||||
<pre><code>$ meson --prefix $HOME/local _build
|
||||
$ ninja -C _build
|
||||
$ ninja -C _build install</code></pre>
|
||||
<p>It installs Pango-1.0.gir under <code>$HOME/local/share/gir-1.0</code>. If you installed Pango without <code>--prefix</code> option, then it would be located at <code>/usr/local/share/gir-1.0</code>. This directory (/usr/local/share) is used by applications. They find the directory by the environment variable <code>XDG_DATA_DIRS</code>. It is a text file which keep the list of ‘share’ directories like <code>/usr/share</code>, <code>usr/local/share</code> and so on. Now <code>$HOME/local/share</code> needs to be added to <code>XDG_DATA_DIRS</code>, or error will occur in the later compilation.</p>
|
||||
<p>It installs Pango-1.0.gir under
|
||||
<code>$HOME/local/share/gir-1.0</code>. If you installed Pango without
|
||||
<code>--prefix</code> option, then it would be located at
|
||||
<code>/usr/local/share/gir-1.0</code>. This directory (/usr/local/share)
|
||||
is used by applications. They find the directory by the environment
|
||||
variable <code>XDG_DATA_DIRS</code>. It is a text file which keep the
|
||||
list of ‘share’ directories like <code>/usr/share</code>,
|
||||
<code>usr/local/share</code> and so on. Now
|
||||
<code>$HOME/local/share</code> needs to be added to
|
||||
<code>XDG_DATA_DIRS</code>, or error will occur in the later
|
||||
compilation.</p>
|
||||
<pre><code>$ export XDG_DATA_DIRS=$HOME/local/share:$XDG_DATA_DIRS</code></pre>
|
||||
<h3 id="gdk-pixbuf-and-gtk-doc-installation">Gdk-pixbuf and Gtk-doc installation</h3>
|
||||
<h3 id="gdkpixbuf-and-gtk-doc-installation">GdkPixbuf and GTK-Doc
|
||||
installation</h3>
|
||||
<p>Download and untar.</p>
|
||||
<pre><code>$ wget https://download.gnome.org/sources/gdk-pixbuf/2.42/gdk-pixbuf-2.42.2.tar.xz
|
||||
$ tar -Jxf gdk-pixbuf-2.42.2.tar.xz
|
||||
$ wget https://download.gnome.org/sources/gtk-doc/1.33/gtk-doc-1.33.1.tar.xz
|
||||
$ tar -Jxf gtk-doc-1.33.1.tar.xz</code></pre>
|
||||
<p>Same as before, install prerequisite packages, then compile and install them.</p>
|
||||
<p>The installation of Gtk-doc put <code>gtk-doc.pc</code> under <code>$HOME/local/share/pkgconfig</code>. This file is used by pkg-config, which is one of the build tools. The directory needs to be added to the environment variable <code>PKG_CONFIG_PATH</code></p>
|
||||
<p>Same as before, install prerequisite packages, then compile and
|
||||
install them.</p>
|
||||
<p>The installation of GTK-Doc put <code>gtk-doc.pc</code> under
|
||||
<code>$HOME/local/share/pkgconfig</code>. This file is used by
|
||||
pkg-config, which is one of the build tools. The directory needs to be
|
||||
added to the environment variable <code>PKG_CONFIG_PATH</code></p>
|
||||
<pre><code>$ export PKG_CONFIG_PATH="$HOME/local/share/pkgconfig:$PKG_CONFIG_PATH"</code></pre>
|
||||
<h3 id="gtk4-installation">Gtk4 installation</h3>
|
||||
<p>If you want the latest development version of Gtk4, use git and clone the repository.</p>
|
||||
<pre><code>$ git clone https://gitlab.gnome.org/GNOME/gtk.git</code></pre>
|
||||
<p>If you want a stable version of Gtk4, then download it from <a href="https://download.gnome.org/sources/gtk/">Gnome source website</a>. The latest version is 4.3.1 (13/June/2021).</p>
|
||||
<h3 id="gtk-4-installation">GTK 4 installation</h3>
|
||||
<p>If you want the latest development version of GTK 4, use git and
|
||||
clone the repository.</p>
|
||||
<pre><code>$ git clone https://gitlab.gnome.org/gnome/gtk.git</code></pre>
|
||||
<p>If you want a stable version of GTK 4, then download it from <a
|
||||
href="https://download.gnome.org/sources/gtk/">GNOME source website</a>.
|
||||
The latest version is 4.3.1 (13/June/2021).</p>
|
||||
<p>Compile and install it.</p>
|
||||
<pre><code>$ meson --prefix $HOME/local _build
|
||||
$ ninja -C _build
|
||||
$ ninja -C _build install</code></pre>
|
||||
<p>If you want to know more information, refer to <a href="https://docs.gtk.org/gtk4/building.html">Gtk4 API Reference, Building GTK</a>.</p>
|
||||
<p>If you want to know more information, refer to <a
|
||||
href="https://docs.gtk.org/gtk4/building.html">GTK 4 API Reference,
|
||||
Building GTK</a>.</p>
|
||||
<h3 id="modify-env.sh">Modify env.sh</h3>
|
||||
<p>Because environment variables disappear when you log out, you need to add them again. Modify <code>env.sh</code>.</p>
|
||||
<p>Because environment variables disappear when you log out, you need to
|
||||
add them again. Modify <code>env.sh</code>.</p>
|
||||
<pre><code># compiler
|
||||
CPPFLAGS="-I$HOME/local/include"
|
||||
LDFLAGS="-L$HOME/local/lib"
|
||||
|
@ -271,20 +337,34 @@ export XDG_DATA_DIRS
|
|||
export GSETTINGS_SCHEMA_DIR=$HOME/local/share/glib-2.0/schemas
|
||||
# girepository-1.0
|
||||
export GI_TYPELIB_PATH=$HOME/local/lib/x86_64-linux-gnu/girepository-1.0</code></pre>
|
||||
<p>Include this file by . (dot) command before using Gtk4 libraries.</p>
|
||||
<p>You may think you can add them in your <code>.profile</code>. But it’s a wrong decision. Never write them to your <code>.profile</code>. The environment variables above are necessary only when you compile and run Gtk4 applications. Otherwise it’s not necessary. If you changed the environment variables above and run Gtk3 applications, it probably causes serious damage.</p>
|
||||
<h3 id="compiling-gtk4-applications">Compiling Gtk4 applications</h3>
|
||||
<p>Before you compile Gtk4 applications, define environment variables above.</p>
|
||||
<p>Include this file by . (dot) command before using GTK 4
|
||||
libraries.</p>
|
||||
<p>You may think you can add them in your <code>.profile</code>. But
|
||||
it’s a wrong decision. Never write them to your <code>.profile</code>.
|
||||
The environment variables above are necessary only when you compile and
|
||||
run GTK 4 applications. Otherwise it’s not necessary. If you changed the
|
||||
environment variables above and run GTK 3 applications, it probably
|
||||
causes serious damage.</p>
|
||||
<h3 id="compiling-gtk-4-applications">Compiling GTK 4 applications</h3>
|
||||
<p>Before you compile GTK 4 applications, define environment variables
|
||||
above.</p>
|
||||
<pre><code>$ . env.sh</code></pre>
|
||||
<p>After that you can compile them without anything. For example, to compile <code>sample.c</code>, type the following.</p>
|
||||
<p>After that you can compile them without anything. For example, to
|
||||
compile <code>sample.c</code>, type the following.</p>
|
||||
<pre><code>$ gcc `pkg-config --cflags gtk4` sample.c `pkg-config --libs gtk4`</code></pre>
|
||||
<p>To know how to compile Gtk4 applications, refer to the section 3 (GtkApplication and GtkApplicationWindow) and after.</p>
|
||||
<h2 id="installing-fedora-34-with-gnome-boxes">Installing Fedora 34 with gnome-boxes</h2>
|
||||
<p>The last part of this section is about Gnome40 and gnome-boxes. Gnome 40 is a new version of Gnome desktop system. And Gtk4 is installed in the distribution. See <a href="https://forty.gnome.org/">Gnome 40 website</a> first.</p>
|
||||
<p><em>However, Gnome40 is not necessary to compile and run Gtk4 applications.</em></p>
|
||||
<p>To know how to compile GTK 4 applications, refer to the section 3
|
||||
(GtkApplication and GtkApplicationWindow) and after.</p>
|
||||
<h2 id="installing-fedora-34-with-gnome-boxes">Installing Fedora 34 with
|
||||
GNOME Boxes</h2>
|
||||
<p>The last part of this section is about GNOME 40 and GNOME Boxes.
|
||||
GNOME 40 is a new version of GNOME desktop system. And GTK 4 is
|
||||
installed in the distribution. See <a
|
||||
href="https://forty.gnome.org/">GNOME 40 website</a> first.</p>
|
||||
<p><em>However, GNOME 40 is not necessary to compile and run GTK 4
|
||||
applications.</em></p>
|
||||
<p>There are seven choices at present.</p>
|
||||
<ul>
|
||||
<li>Gnome OS</li>
|
||||
<li>GNOME OS</li>
|
||||
<li>Arch Linux</li>
|
||||
<li>Gentoo Linux</li>
|
||||
<li>Fedora 36</li>
|
||||
|
@ -292,29 +372,47 @@ export GI_TYPELIB_PATH=$HOME/local/lib/x86_64-linux-gnu/girepository-1.0</code><
|
|||
<li>Ubuntu 22.04</li>
|
||||
<li>Debian bookworm</li>
|
||||
</ul>
|
||||
<p>I’ve installed Fedora 34 with gnome-boxes. My OS was Ubuntu 21.04 at that time. Gnome-boxes creates a virtual machine in Ubuntu and Fedora will be installed to that virtual machine.</p>
|
||||
<p>I’ve installed Fedora 34 with GNOME Boxes. My OS was Ubuntu 21.04 at
|
||||
that time. GNOME Boxes creates a virtual machine in Ubuntu and Fedora
|
||||
will be installed to that virtual machine.</p>
|
||||
<p>The instruction is as follows.</p>
|
||||
<ol type="1">
|
||||
<li>Download Fedora 34 iso file. There is an link at the end of <a href="https://forty.gnome.org/">Gnome 40 website</a>.</li>
|
||||
<li>Download Fedora 34 iso file. There is an link at the end of <a
|
||||
href="https://forty.gnome.org/">GNOME 40 website</a>.</li>
|
||||
<li>Install gnome-boxes with apt-get command.</li>
|
||||
</ol>
|
||||
<pre><code>$ sudo apt-get install gnome-boxes</code></pre>
|
||||
<ol start="3" type="1">
|
||||
<li>Run gnome-boxes.</li>
|
||||
<li>Click on <code>+</code> button on the top left corner and launch a box creation wizard by clicking <code>Create a Virtual Machine ...</code>. Then a dialog appears. Click on <code>Operationg System Image File</code> and select the iso file you have downloaded.</li>
|
||||
<li>Then, the Fedora’s installer is executed. Follow the instructions by the installer. At the end of the installation, the installer instructs to reboot the system. Click on the right of the title bar and select reboot or shutdown.</li>
|
||||
<li>Your display is back to the initial window of gnome-boxes, but there is a button <code>Fedora 34 Workstation</code> on the upper left of the window. Click on the button then Fedora will be executed.</li>
|
||||
<li>Run GNOME Boxes.</li>
|
||||
<li>Click on <code>+</code> button on the top left corner and launch a
|
||||
box creation wizard by clicking
|
||||
<code>Create a Virtual Machine ...</code>. Then a dialog appears. Click
|
||||
on <code>Operationg System Image File</code> and select the iso file you
|
||||
have downloaded.</li>
|
||||
<li>Then, the Fedora’s installer is executed. Follow the instructions by
|
||||
the installer. At the end of the installation, the installer instructs
|
||||
to reboot the system. Click on the right of the title bar and select
|
||||
reboot or shutdown.</li>
|
||||
<li>Your display is back to the initial window of GNOME Boxes, but there
|
||||
is a button <code>Fedora 34 Workstation</code> on the upper left of the
|
||||
window. Click on the button then Fedora will be executed.</li>
|
||||
<li>A setup dialog appears. Setup Fedora according to the wizard.</li>
|
||||
</ol>
|
||||
<p>Now you can use Fedora. It includes Gtk4 libraries already. But you need to install the Gtk4 development package. Use <code>dnf</code> to install <code>gtk4.x86_64</code> package.</p>
|
||||
<p>Now you can use Fedora. It includes GTK 4 libraries already. But you
|
||||
need to install the GTK 4 development package. Use <code>dnf</code> to
|
||||
install <code>gtk4.x86_64</code> package.</p>
|
||||
<pre><code>$ sudo dnf install gtk4.x86_64</code></pre>
|
||||
<h3 id="gtk4-compilation-test">Gtk4 compilation test</h3>
|
||||
<p>You can test the Gtk4 development packages by compiling files which are based on Gtk4. I’ve tried compiling <code>tfe</code> text editor, which is written in section 21.</p>
|
||||
<h3 id="gtk-4-compilation-test">GTK 4 compilation test</h3>
|
||||
<p>You can test the GTK 4 development packages by compiling files which
|
||||
are based on GTK 4. I’ve tried compiling <code>tfe</code> text editor,
|
||||
which is written in section 21.</p>
|
||||
<ol type="1">
|
||||
<li>Run Firefox.</li>
|
||||
<li>Open this website (<a href="https://github.com/ToshioCP/Gtk4-tutorial">Gtk4-Tutorial</a>).</li>
|
||||
<li>Open this website (<a
|
||||
href="https://github.com/ToshioCP/Gtk4-tutorial">Gtk4-Tutorial</a>).</li>
|
||||
<li>Click on the green button labeled <code>Code</code>.</li>
|
||||
<li>Select <code>Download ZIP</code> and download the codes from the repository.</li>
|
||||
<li>Select <code>Download ZIP</code> and download the codes from the
|
||||
repository.</li>
|
||||
<li>Unzip the file.</li>
|
||||
<li>Change your current directory to <code>src/tfe7</code>.</li>
|
||||
<li>Compile it.</li>
|
||||
|
@ -372,7 +470,8 @@ Running custom install script '/usr/bin/glib-compile-schemas /usr/local/shar
|
|||
<li>Execute it.</li>
|
||||
</ol>
|
||||
<pre><code>$ tfe</code></pre>
|
||||
<p>Then, the window of <code>tfe</code> text editor appears. The compilation and execution have succeeded.</p>
|
||||
<p>Then, the window of <code>tfe</code> text editor appears. The
|
||||
compilation and execution have succeeded.</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>
|
||||
|
|
1585
docs/sec20.html
1585
docs/sec20.html
File diff suppressed because it is too large
Load diff
1053
docs/sec21.html
1053
docs/sec21.html
File diff suppressed because it is too large
Load diff
483
docs/sec24.html
483
docs/sec24.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;}
|
||||
|
@ -111,10 +111,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 id="combine-gtkdrawingarea-and-tfetextview">Combine GtkDrawingArea and TfeTextView</h1>
|
||||
<p>Now, we will make a new application which has GtkDrawingArea and TfeTextView in it. Its name is “color”. If you write a name of a color in TfeTextView and click on the <code>run</code> button, then the color of GtkDrawingArea changes to the color given by you.</p>
|
||||
<h1 id="combine-gtkdrawingarea-and-tfetextview">Combine GtkDrawingArea
|
||||
and TfeTextView</h1>
|
||||
<p>Now, we will make a new application which has GtkDrawingArea and
|
||||
TfeTextView in it. Its name is “color”. If you write a name of a color
|
||||
in TfeTextView and click on the <code>run</code> button, then the color
|
||||
of GtkDrawingArea changes to the color given by you.</p>
|
||||
<figure>
|
||||
<img src="image/color.png" alt="" /><figcaption>color</figcaption>
|
||||
<img src="image/color.png" alt="color" />
|
||||
<figcaption aria-hidden="true">color</figcaption>
|
||||
</figure>
|
||||
<p>The following colors are available.</p>
|
||||
<ul>
|
||||
|
@ -129,255 +134,310 @@
|
|||
<li>light: Make the color of the drawing area lighter.</li>
|
||||
<li>dark: Make the color of the drawing area darker.</li>
|
||||
</ul>
|
||||
<p>This application can only do very simple things. However, it tells us that if we add powerful parser to it, we will be able to make it more efficient. I want to show it to you in the later section by making a turtle graphics language like Logo program language.</p>
|
||||
<p>This application can only do very simple things. However, it tells us
|
||||
that if we add powerful parser to it, we will be able to make it more
|
||||
efficient. I want to show it to you in the later section by making a
|
||||
turtle graphics language like Logo program language.</p>
|
||||
<p>In this section, we focus on how to bind the two objects.</p>
|
||||
<h2 id="color.ui-and-color.gresource.xml">Color.ui and color.gresource.xml</h2>
|
||||
<p>First, We need to make the ui file of the widgets. The image in the previous subsection gives us the structure of the widgets. Title bar, four buttons in the tool bar and two widgets textview and drawing area. The ui file is as follows.</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw"><?xml</span> version="1.0" encoding="UTF-8"<span class="kw">?></span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw"><interface></span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkApplicationWindow"</span><span class="ot"> id=</span><span class="st">"win"</span><span class="kw">></span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"title"</span><span class="kw">></span>color changer<span class="kw"></property></span></span>
|
||||
<span id="cb1-5"><a href="#cb1-5"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"default-width"</span><span class="kw">></span>600<span class="kw"></property></span></span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"default-height"</span><span class="kw">></span>400<span class="kw"></property></span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-8"><a href="#cb1-8"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxv"</span><span class="kw">></span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"orientation"</span><span class="kw">></span>GTK_ORIENTATION_VERTICAL<span class="kw"></property></span></span>
|
||||
<span id="cb1-10"><a href="#cb1-10"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-11"><a href="#cb1-11"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxh1"</span><span class="kw">></span></span>
|
||||
<span id="cb1-12"><a href="#cb1-12"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"orientation"</span><span class="kw">></span>GTK_ORIENTATION_HORIZONTAL<span class="kw"></property></span></span>
|
||||
<span id="cb1-13"><a href="#cb1-13"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-14"><a href="#cb1-14"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy1"</span><span class="kw">></span></span>
|
||||
<span id="cb1-15"><a href="#cb1-15"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"width-chars"</span><span class="kw">></span>10<span class="kw"></property></span></span>
|
||||
<span id="cb1-16"><a href="#cb1-16"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-17"><a href="#cb1-17"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-18"><a href="#cb1-18"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-19"><a href="#cb1-19"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btnr"</span><span class="kw">></span></span>
|
||||
<span id="cb1-20"><a href="#cb1-20"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"label"</span><span class="kw">></span>Run<span class="kw"></property></span></span>
|
||||
<span id="cb1-21"><a href="#cb1-21"></a> <span class="kw"><signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"run_cb"</span><span class="kw">></signal></span></span>
|
||||
<span id="cb1-22"><a href="#cb1-22"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-23"><a href="#cb1-23"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-24"><a href="#cb1-24"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-25"><a href="#cb1-25"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btno"</span><span class="kw">></span></span>
|
||||
<span id="cb1-26"><a href="#cb1-26"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"label"</span><span class="kw">></span>Open<span class="kw"></property></span></span>
|
||||
<span id="cb1-27"><a href="#cb1-27"></a> <span class="kw"><signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"open_cb"</span><span class="kw">></signal></span></span>
|
||||
<span id="cb1-28"><a href="#cb1-28"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-29"><a href="#cb1-29"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-30"><a href="#cb1-30"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-31"><a href="#cb1-31"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy2"</span><span class="kw">></span></span>
|
||||
<span id="cb1-32"><a href="#cb1-32"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"hexpand"</span><span class="kw">></span>TRUE<span class="kw"></property></span></span>
|
||||
<span id="cb1-33"><a href="#cb1-33"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-34"><a href="#cb1-34"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-35"><a href="#cb1-35"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-36"><a href="#cb1-36"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btns"</span><span class="kw">></span></span>
|
||||
<span id="cb1-37"><a href="#cb1-37"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"label"</span><span class="kw">></span>Save<span class="kw"></property></span></span>
|
||||
<span id="cb1-38"><a href="#cb1-38"></a> <span class="kw"><signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"save_cb"</span><span class="kw">></signal></span></span>
|
||||
<span id="cb1-39"><a href="#cb1-39"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-40"><a href="#cb1-40"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-41"><a href="#cb1-41"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-42"><a href="#cb1-42"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btnc"</span><span class="kw">></span></span>
|
||||
<span id="cb1-43"><a href="#cb1-43"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"label"</span><span class="kw">></span>Close<span class="kw"></property></span></span>
|
||||
<span id="cb1-44"><a href="#cb1-44"></a> <span class="kw"><signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"close_cb"</span><span class="kw">></signal></span></span>
|
||||
<span id="cb1-45"><a href="#cb1-45"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-46"><a href="#cb1-46"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-47"><a href="#cb1-47"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-48"><a href="#cb1-48"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy3"</span><span class="kw">></span></span>
|
||||
<span id="cb1-49"><a href="#cb1-49"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"width-chars"</span><span class="kw">></span>10<span class="kw"></property></span></span>
|
||||
<span id="cb1-50"><a href="#cb1-50"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-51"><a href="#cb1-51"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-52"><a href="#cb1-52"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-53"><a href="#cb1-53"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-54"><a href="#cb1-54"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-55"><a href="#cb1-55"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxh2"</span><span class="kw">></span></span>
|
||||
<span id="cb1-56"><a href="#cb1-56"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"orientation"</span><span class="kw">></span>GTK_ORIENTATION_HORIZONTAL<span class="kw"></property></span></span>
|
||||
<span id="cb1-57"><a href="#cb1-57"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"homogeneous"</span><span class="kw">></span>TRUE<span class="kw"></property></span></span>
|
||||
<span id="cb1-58"><a href="#cb1-58"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-59"><a href="#cb1-59"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkScrolledWindow"</span><span class="ot"> id=</span><span class="st">"scr"</span><span class="kw">></span></span>
|
||||
<span id="cb1-60"><a href="#cb1-60"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"hexpand"</span><span class="kw">></span>TRUE<span class="kw"></property></span></span>
|
||||
<span id="cb1-61"><a href="#cb1-61"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"vexpand"</span><span class="kw">></span>TRUE<span class="kw"></property></span></span>
|
||||
<span id="cb1-62"><a href="#cb1-62"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-63"><a href="#cb1-63"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"TfeTextView"</span><span class="ot"> id=</span><span class="st">"tv"</span><span class="kw">></span></span>
|
||||
<span id="cb1-64"><a href="#cb1-64"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"wrap-mode"</span><span class="kw">></span>GTK_WRAP_WORD_CHAR<span class="kw"></property></span></span>
|
||||
<span id="cb1-65"><a href="#cb1-65"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-66"><a href="#cb1-66"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-67"><a href="#cb1-67"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-68"><a href="#cb1-68"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-69"><a href="#cb1-69"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb1-70"><a href="#cb1-70"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkDrawingArea"</span><span class="ot"> id=</span><span class="st">"da"</span><span class="kw">></span></span>
|
||||
<span id="cb1-71"><a href="#cb1-71"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"hexpand"</span><span class="kw">></span>TRUE<span class="kw"></property></span></span>
|
||||
<span id="cb1-72"><a href="#cb1-72"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"vexpand"</span><span class="kw">></span>TRUE<span class="kw"></property></span></span>
|
||||
<span id="cb1-73"><a href="#cb1-73"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-74"><a href="#cb1-74"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-75"><a href="#cb1-75"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-76"><a href="#cb1-76"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-77"><a href="#cb1-77"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-78"><a href="#cb1-78"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb1-79"><a href="#cb1-79"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb1-80"><a href="#cb1-80"></a><span class="kw"></interface></span></span></code></pre></div>
|
||||
<h2 id="color.ui-and-color.gresource.xml">Color.ui and
|
||||
color.gresource.xml</h2>
|
||||
<p>First, We need to make the ui file of the widgets. The image in the
|
||||
previous subsection gives us the structure of the widgets. Title bar,
|
||||
four buttons in the tool bar and two widgets textview and drawing area.
|
||||
The ui file is as follows.</p>
|
||||
<div class="sourceCode" id="cb1"><pre
|
||||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb1-1"><a href="#cb1-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2"></a><<span class="kw">interface</span>></span>
|
||||
<span id="cb1-3"><a href="#cb1-3"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkApplicationWindow"</span><span class="ot"> id=</span><span class="st">"win"</span>></span>
|
||||
<span id="cb1-4"><a href="#cb1-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"title"</span>>color changer</<span class="kw">property</span>></span>
|
||||
<span id="cb1-5"><a href="#cb1-5"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-width"</span>>600</<span class="kw">property</span>></span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-height"</span>>400</<span class="kw">property</span>></span>
|
||||
<span id="cb1-7"><a href="#cb1-7"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-8"><a href="#cb1-8"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxv"</span>></span>
|
||||
<span id="cb1-9"><a href="#cb1-9"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_VERTICAL</<span class="kw">property</span>></span>
|
||||
<span id="cb1-10"><a href="#cb1-10"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-11"><a href="#cb1-11"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxh1"</span>></span>
|
||||
<span id="cb1-12"><a href="#cb1-12"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_HORIZONTAL</<span class="kw">property</span>></span>
|
||||
<span id="cb1-13"><a href="#cb1-13"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-14"><a href="#cb1-14"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy1"</span>></span>
|
||||
<span id="cb1-15"><a href="#cb1-15"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"width-chars"</span>>10</<span class="kw">property</span>></span>
|
||||
<span id="cb1-16"><a href="#cb1-16"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-17"><a href="#cb1-17"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-18"><a href="#cb1-18"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-19"><a href="#cb1-19"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btnr"</span>></span>
|
||||
<span id="cb1-20"><a href="#cb1-20"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Run</<span class="kw">property</span>></span>
|
||||
<span id="cb1-21"><a href="#cb1-21"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"run_cb"</span>></<span class="kw">signal</span>></span>
|
||||
<span id="cb1-22"><a href="#cb1-22"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-23"><a href="#cb1-23"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-24"><a href="#cb1-24"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-25"><a href="#cb1-25"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btno"</span>></span>
|
||||
<span id="cb1-26"><a href="#cb1-26"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Open</<span class="kw">property</span>></span>
|
||||
<span id="cb1-27"><a href="#cb1-27"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"open_cb"</span>></<span class="kw">signal</span>></span>
|
||||
<span id="cb1-28"><a href="#cb1-28"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-29"><a href="#cb1-29"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-30"><a href="#cb1-30"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-31"><a href="#cb1-31"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy2"</span>></span>
|
||||
<span id="cb1-32"><a href="#cb1-32"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
||||
<span id="cb1-33"><a href="#cb1-33"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-34"><a href="#cb1-34"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-35"><a href="#cb1-35"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-36"><a href="#cb1-36"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btns"</span>></span>
|
||||
<span id="cb1-37"><a href="#cb1-37"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Save</<span class="kw">property</span>></span>
|
||||
<span id="cb1-38"><a href="#cb1-38"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"save_cb"</span>></<span class="kw">signal</span>></span>
|
||||
<span id="cb1-39"><a href="#cb1-39"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-40"><a href="#cb1-40"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-41"><a href="#cb1-41"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-42"><a href="#cb1-42"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btnc"</span>></span>
|
||||
<span id="cb1-43"><a href="#cb1-43"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Close</<span class="kw">property</span>></span>
|
||||
<span id="cb1-44"><a href="#cb1-44"></a> <<span class="kw">signal</span><span class="ot"> name=</span><span class="st">"clicked"</span><span class="ot"> handler=</span><span class="st">"close_cb"</span>></<span class="kw">signal</span>></span>
|
||||
<span id="cb1-45"><a href="#cb1-45"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-46"><a href="#cb1-46"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-47"><a href="#cb1-47"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-48"><a href="#cb1-48"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy3"</span>></span>
|
||||
<span id="cb1-49"><a href="#cb1-49"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"width-chars"</span>>10</<span class="kw">property</span>></span>
|
||||
<span id="cb1-50"><a href="#cb1-50"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-51"><a href="#cb1-51"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-52"><a href="#cb1-52"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-53"><a href="#cb1-53"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-54"><a href="#cb1-54"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-55"><a href="#cb1-55"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxh2"</span>></span>
|
||||
<span id="cb1-56"><a href="#cb1-56"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_HORIZONTAL</<span class="kw">property</span>></span>
|
||||
<span id="cb1-57"><a href="#cb1-57"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"homogeneous"</span>>TRUE</<span class="kw">property</span>></span>
|
||||
<span id="cb1-58"><a href="#cb1-58"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-59"><a href="#cb1-59"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkScrolledWindow"</span><span class="ot"> id=</span><span class="st">"scr"</span>></span>
|
||||
<span id="cb1-60"><a href="#cb1-60"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
||||
<span id="cb1-61"><a href="#cb1-61"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
||||
<span id="cb1-62"><a href="#cb1-62"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-63"><a href="#cb1-63"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"TfeTextView"</span><span class="ot"> id=</span><span class="st">"tv"</span>></span>
|
||||
<span id="cb1-64"><a href="#cb1-64"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"wrap-mode"</span>>GTK_WRAP_WORD_CHAR</<span class="kw">property</span>></span>
|
||||
<span id="cb1-65"><a href="#cb1-65"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-66"><a href="#cb1-66"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-67"><a href="#cb1-67"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-68"><a href="#cb1-68"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-69"><a href="#cb1-69"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb1-70"><a href="#cb1-70"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkDrawingArea"</span><span class="ot"> id=</span><span class="st">"da"</span>></span>
|
||||
<span id="cb1-71"><a href="#cb1-71"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"hexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
||||
<span id="cb1-72"><a href="#cb1-72"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"vexpand"</span>>TRUE</<span class="kw">property</span>></span>
|
||||
<span id="cb1-73"><a href="#cb1-73"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-74"><a href="#cb1-74"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-75"><a href="#cb1-75"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-76"><a href="#cb1-76"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-77"><a href="#cb1-77"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-78"><a href="#cb1-78"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb1-79"><a href="#cb1-79"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb1-80"><a href="#cb1-80"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||
<ul>
|
||||
<li>10-53: This part is the tool bar which has four buttons, <code>Run</code>, <code>Open</code>, <code>Save</code> and <code>Close</code>. This is similar to the toolbar of tfe text editor in <a href="sec9.html">Section 9</a>. There are two differences. <code>Run</code> button replaces <code>New</code> button. A signal element is added to each button object. It has “name” attribute which is a signal name and “handler” attribute which is the name of its signal handler function. Options “-WI, –export-dynamic” CFLAG is necessary when you compile the application. You can achieve this by adding “export_dynamic: true” argument to executable function in <code>meson.build</code>. And be careful that the handler must be defined without ‘static’ class.</li>
|
||||
<li>54-76: Puts GtkScrolledWindow and GtkDrawingArea into GtkBox. GtkBox has “homogeneous property” with TRUE value, so the two children have the same width in the box. TfeTextView is a child of GtkScrolledWindow.</li>
|
||||
<li>10-53: This part is the tool bar which has four buttons,
|
||||
<code>Run</code>, <code>Open</code>, <code>Save</code> and
|
||||
<code>Close</code>. This is similar to the toolbar of tfe text editor in
|
||||
<a href="sec9.html">Section 9</a>. There are two differences.
|
||||
<code>Run</code> button replaces <code>New</code> button. A signal
|
||||
element is added to each button object. It has “name” attribute which is
|
||||
a signal name and “handler” attribute which is the name of its signal
|
||||
handler function. Options “-WI, –export-dynamic” CFLAG is necessary when
|
||||
you compile the application. You can achieve this by adding
|
||||
“export_dynamic: true” argument to executable function in
|
||||
<code>meson.build</code>. And be careful that the handler must be
|
||||
defined without ‘static’ class.</li>
|
||||
<li>54-76: Puts GtkScrolledWindow and GtkDrawingArea into GtkBox. GtkBox
|
||||
has “homogeneous property” with TRUE value, so the two children have the
|
||||
same width in the box. TfeTextView is a child of GtkScrolledWindow.</li>
|
||||
</ul>
|
||||
<p>The xml file for the resource compiler is almost same as before. Just substitute “color” for “tfe”.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw"><?xml</span> version="1.0" encoding="UTF-8"<span class="kw">?></span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2"></a><span class="kw"><gresources></span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3"></a> <span class="kw"><gresource</span><span class="ot"> prefix=</span><span class="st">"/com/github/ToshioCP/color"</span><span class="kw">></span></span>
|
||||
<span id="cb2-4"><a href="#cb2-4"></a> <span class="kw"><file></span>color.ui<span class="kw"></file></span></span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a> <span class="kw"></gresource></span></span>
|
||||
<span id="cb2-6"><a href="#cb2-6"></a><span class="kw"></gresources></span></span></code></pre></div>
|
||||
<h2 id="tfetextview.h-tfetextview.c-and-color.h">Tfetextview.h, tfetextview.c and color.h</h2>
|
||||
<p>First two files are the same as before. Color.h just includes tfetextview.h.</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<p>The xml file for the resource compiler is almost same as before. Just
|
||||
substitute “color” for “tfe”.</p>
|
||||
<div class="sourceCode" id="cb2"><pre
|
||||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb2-1"><a href="#cb2-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2"></a><<span class="kw">gresources</span>></span>
|
||||
<span id="cb2-3"><a href="#cb2-3"></a> <<span class="kw">gresource</span><span class="ot"> prefix=</span><span class="st">"/com/github/ToshioCP/color"</span>></span>
|
||||
<span id="cb2-4"><a href="#cb2-4"></a> <<span class="kw">file</span>>color.ui</<span class="kw">file</span>></span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a> </<span class="kw">gresource</span>></span>
|
||||
<span id="cb2-6"><a href="#cb2-6"></a></<span class="kw">gresources</span>></span></code></pre></div>
|
||||
<h2 id="tfetextview.h-tfetextview.c-and-color.h">Tfetextview.h,
|
||||
tfetextview.c and color.h</h2>
|
||||
<p>First two files are the same as before. Color.h just includes
|
||||
tfetextview.h.</p>
|
||||
<div class="sourceCode" id="cb3"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb3-2"><a href="#cb3-2"></a></span>
|
||||
<span id="cb3-3"><a href="#cb3-3"></a><span class="pp">#include </span><span class="im">"../tfetextview/tfetextview.h"</span></span></code></pre></div>
|
||||
<h2 id="colorapplication.c">Colorapplication.c</h2>
|
||||
<p>This is the main file. It deals with:</p>
|
||||
<ul>
|
||||
<li>Building widgets by GtkBuilder.</li>
|
||||
<li>Setting a drawing function of GtkDrawingArea. And connecting a handler to “resize” signal on GtkDrawingArea.</li>
|
||||
<li>Implementing each call back functions. Particularly, <code>Run</code> signal handler is the point in this program.</li>
|
||||
<li>Setting a drawing function of GtkDrawingArea. And connecting a
|
||||
handler to “resize” signal on GtkDrawingArea.</li>
|
||||
<li>Implementing each call back functions. Particularly,
|
||||
<code>Run</code> signal handler is the point in this program.</li>
|
||||
</ul>
|
||||
<p>The following is <code>colorapplication.c</code>.</p>
|
||||
<div class="sourceCode" id="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">"color.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">"color.h"</span></span>
|
||||
<span id="cb4-2"><a href="#cb4-2"></a></span>
|
||||
<span id="cb4-3"><a href="#cb4-3"></a><span class="dt">static</span> GtkWidget *win;</span>
|
||||
<span id="cb4-4"><a href="#cb4-4"></a><span class="dt">static</span> GtkWidget *tv;</span>
|
||||
<span id="cb4-5"><a href="#cb4-5"></a><span class="dt">static</span> GtkWidget *da;</span>
|
||||
<span id="cb4-3"><a href="#cb4-3"></a><span class="dt">static</span> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
||||
<span id="cb4-4"><a href="#cb4-4"></a><span class="dt">static</span> GtkWidget <span class="op">*</span>tv<span class="op">;</span></span>
|
||||
<span id="cb4-5"><a href="#cb4-5"></a><span class="dt">static</span> GtkWidget <span class="op">*</span>da<span class="op">;</span></span>
|
||||
<span id="cb4-6"><a href="#cb4-6"></a></span>
|
||||
<span id="cb4-7"><a href="#cb4-7"></a><span class="dt">static</span> cairo_surface_t *surface = NULL;</span>
|
||||
<span id="cb4-7"><a href="#cb4-7"></a><span class="dt">static</span> cairo_surface_t <span class="op">*</span>surface <span class="op">=</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb4-8"><a href="#cb4-8"></a></span>
|
||||
<span id="cb4-9"><a href="#cb4-9"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb4-10"><a href="#cb4-10"></a>run (<span class="dt">void</span>) {</span>
|
||||
<span id="cb4-11"><a href="#cb4-11"></a> GtkTextBuffer *tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
|
||||
<span id="cb4-12"><a href="#cb4-12"></a> GtkTextIter start_iter;</span>
|
||||
<span id="cb4-13"><a href="#cb4-13"></a> GtkTextIter end_iter;</span>
|
||||
<span id="cb4-14"><a href="#cb4-14"></a> <span class="dt">char</span> *contents;</span>
|
||||
<span id="cb4-15"><a href="#cb4-15"></a> cairo_t *cr;</span>
|
||||
<span id="cb4-10"><a href="#cb4-10"></a>run <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-11"><a href="#cb4-11"></a> GtkTextBuffer <span class="op">*</span>tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb4-12"><a href="#cb4-12"></a> GtkTextIter start_iter<span class="op">;</span></span>
|
||||
<span id="cb4-13"><a href="#cb4-13"></a> GtkTextIter end_iter<span class="op">;</span></span>
|
||||
<span id="cb4-14"><a href="#cb4-14"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span>
|
||||
<span id="cb4-15"><a href="#cb4-15"></a> cairo_t <span class="op">*</span>cr<span class="op">;</span></span>
|
||||
<span id="cb4-16"><a href="#cb4-16"></a></span>
|
||||
<span id="cb4-17"><a href="#cb4-17"></a> gtk_text_buffer_get_bounds (tb, &start_iter, &end_iter);</span>
|
||||
<span id="cb4-18"><a href="#cb4-18"></a> contents = gtk_text_buffer_get_text (tb, &start_iter, &end_iter, FALSE);</span>
|
||||
<span id="cb4-19"><a href="#cb4-19"></a> <span class="cf">if</span> (surface) {</span>
|
||||
<span id="cb4-20"><a href="#cb4-20"></a> cr = cairo_create (surface);</span>
|
||||
<span id="cb4-21"><a href="#cb4-21"></a> <span class="cf">if</span> (g_strcmp0 (<span class="st">"red"</span>, contents) == <span class="dv">0</span>)</span>
|
||||
<span id="cb4-22"><a href="#cb4-22"></a> cairo_set_source_rgb (cr, <span class="dv">1</span>, <span class="dv">0</span>, <span class="dv">0</span>);</span>
|
||||
<span id="cb4-23"><a href="#cb4-23"></a> <span class="cf">else</span> <span class="cf">if</span> (g_strcmp0 (<span class="st">"green"</span>, contents) == <span class="dv">0</span>)</span>
|
||||
<span id="cb4-24"><a href="#cb4-24"></a> cairo_set_source_rgb (cr, <span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">0</span>);</span>
|
||||
<span id="cb4-25"><a href="#cb4-25"></a> <span class="cf">else</span> <span class="cf">if</span> (g_strcmp0 (<span class="st">"blue"</span>, contents) == <span class="dv">0</span>)</span>
|
||||
<span id="cb4-26"><a href="#cb4-26"></a> cairo_set_source_rgb (cr, <span class="dv">0</span>, <span class="dv">0</span>, <span class="dv">1</span>);</span>
|
||||
<span id="cb4-27"><a href="#cb4-27"></a> <span class="cf">else</span> <span class="cf">if</span> (g_strcmp0 (<span class="st">"white"</span>, contents) == <span class="dv">0</span>)</span>
|
||||
<span id="cb4-28"><a href="#cb4-28"></a> cairo_set_source_rgb (cr, <span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">1</span>);</span>
|
||||
<span id="cb4-29"><a href="#cb4-29"></a> <span class="cf">else</span> <span class="cf">if</span> (g_strcmp0 (<span class="st">"black"</span>, contents) == <span class="dv">0</span>)</span>
|
||||
<span id="cb4-30"><a href="#cb4-30"></a> cairo_set_source_rgb (cr, <span class="dv">0</span>, <span class="dv">0</span>, <span class="dv">0</span>);</span>
|
||||
<span id="cb4-31"><a href="#cb4-31"></a> <span class="cf">else</span> <span class="cf">if</span> (g_strcmp0 (<span class="st">"light"</span>, contents) == <span class="dv">0</span>)</span>
|
||||
<span id="cb4-32"><a href="#cb4-32"></a> cairo_set_source_rgba (cr, <span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">1</span>, <span class="fl">0.5</span>);</span>
|
||||
<span id="cb4-33"><a href="#cb4-33"></a> <span class="cf">else</span> <span class="cf">if</span> (g_strcmp0 (<span class="st">"dark"</span>, contents) == <span class="dv">0</span>)</span>
|
||||
<span id="cb4-34"><a href="#cb4-34"></a> cairo_set_source_rgba (cr, <span class="dv">0</span>, <span class="dv">0</span>, <span class="dv">0</span>, <span class="fl">0.5</span>);</span>
|
||||
<span id="cb4-17"><a href="#cb4-17"></a> gtk_text_buffer_get_bounds <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">);</span></span>
|
||||
<span id="cb4-18"><a href="#cb4-18"></a> contents <span class="op">=</span> gtk_text_buffer_get_text <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">,</span> FALSE<span class="op">);</span></span>
|
||||
<span id="cb4-19"><a href="#cb4-19"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-20"><a href="#cb4-20"></a> cr <span class="op">=</span> cairo_create <span class="op">(</span>surface<span class="op">);</span></span>
|
||||
<span id="cb4-21"><a href="#cb4-21"></a> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"red"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb4-22"><a href="#cb4-22"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||
<span id="cb4-23"><a href="#cb4-23"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"green"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb4-24"><a href="#cb4-24"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||
<span id="cb4-25"><a href="#cb4-25"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"blue"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb4-26"><a href="#cb4-26"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span>
|
||||
<span id="cb4-27"><a href="#cb4-27"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"white"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb4-28"><a href="#cb4-28"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span>
|
||||
<span id="cb4-29"><a href="#cb4-29"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"black"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb4-30"><a href="#cb4-30"></a> cairo_set_source_rgb <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||
<span id="cb4-31"><a href="#cb4-31"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"light"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb4-32"><a href="#cb4-32"></a> cairo_set_source_rgba <span class="op">(</span>cr<span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="fl">0.5</span><span class="op">);</span></span>
|
||||
<span id="cb4-33"><a href="#cb4-33"></a> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>g_strcmp0 <span class="op">(</span><span class="st">"dark"</span><span class="op">,</span> contents<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
|
||||
<span id="cb4-34"><a href="#cb4-34"></a> cairo_set_source_rgba <span class="op">(</span>cr<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="fl">0.5</span><span class="op">);</span></span>
|
||||
<span id="cb4-35"><a href="#cb4-35"></a> <span class="cf">else</span></span>
|
||||
<span id="cb4-36"><a href="#cb4-36"></a> cairo_set_source_surface (cr, surface, <span class="dv">0</span>, <span class="dv">0</span>);</span>
|
||||
<span id="cb4-37"><a href="#cb4-37"></a> cairo_paint (cr);</span>
|
||||
<span id="cb4-38"><a href="#cb4-38"></a> cairo_destroy (cr);</span>
|
||||
<span id="cb4-39"><a href="#cb4-39"></a> }</span>
|
||||
<span id="cb4-40"><a href="#cb4-40"></a> g_free (contents);</span>
|
||||
<span id="cb4-41"><a href="#cb4-41"></a>}</span>
|
||||
<span id="cb4-36"><a href="#cb4-36"></a> cairo_set_source_surface <span class="op">(</span>cr<span class="op">,</span> surface<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||
<span id="cb4-37"><a href="#cb4-37"></a> cairo_paint <span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-38"><a href="#cb4-38"></a> cairo_destroy <span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-39"><a href="#cb4-39"></a> <span class="op">}</span></span>
|
||||
<span id="cb4-40"><a href="#cb4-40"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span>
|
||||
<span id="cb4-41"><a href="#cb4-41"></a><span class="op">}</span></span>
|
||||
<span id="cb4-42"><a href="#cb4-42"></a></span>
|
||||
<span id="cb4-43"><a href="#cb4-43"></a><span class="dt">void</span></span>
|
||||
<span id="cb4-44"><a href="#cb4-44"></a>run_cb (GtkWidget *btnr) {</span>
|
||||
<span id="cb4-45"><a href="#cb4-45"></a> run ();</span>
|
||||
<span id="cb4-46"><a href="#cb4-46"></a> gtk_widget_queue_draw (GTK_WIDGET (da));</span>
|
||||
<span id="cb4-47"><a href="#cb4-47"></a>}</span>
|
||||
<span id="cb4-44"><a href="#cb4-44"></a>run_cb <span class="op">(</span>GtkWidget <span class="op">*</span>btnr<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-45"><a href="#cb4-45"></a> run <span class="op">();</span></span>
|
||||
<span id="cb4-46"><a href="#cb4-46"></a> gtk_widget_queue_draw <span class="op">(</span>GTK_WIDGET <span class="op">(</span>da<span class="op">));</span></span>
|
||||
<span id="cb4-47"><a href="#cb4-47"></a><span class="op">}</span></span>
|
||||
<span id="cb4-48"><a href="#cb4-48"></a></span>
|
||||
<span id="cb4-49"><a href="#cb4-49"></a><span class="dt">void</span></span>
|
||||
<span id="cb4-50"><a href="#cb4-50"></a>open_cb (GtkWidget *btno) {</span>
|
||||
<span id="cb4-51"><a href="#cb4-51"></a> tfe_text_view_open (TFE_TEXT_VIEW (tv), GTK_WINDOW (win));</span>
|
||||
<span id="cb4-52"><a href="#cb4-52"></a>}</span>
|
||||
<span id="cb4-50"><a href="#cb4-50"></a>open_cb <span class="op">(</span>GtkWidget <span class="op">*</span>btno<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-51"><a href="#cb4-51"></a> tfe_text_view_open <span class="op">(</span>TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">),</span> GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb4-52"><a href="#cb4-52"></a><span class="op">}</span></span>
|
||||
<span id="cb4-53"><a href="#cb4-53"></a></span>
|
||||
<span id="cb4-54"><a href="#cb4-54"></a><span class="dt">void</span></span>
|
||||
<span id="cb4-55"><a href="#cb4-55"></a>save_cb (GtkWidget *btns) {</span>
|
||||
<span id="cb4-56"><a href="#cb4-56"></a> tfe_text_view_save (TFE_TEXT_VIEW (tv));</span>
|
||||
<span id="cb4-57"><a href="#cb4-57"></a>}</span>
|
||||
<span id="cb4-55"><a href="#cb4-55"></a>save_cb <span class="op">(</span>GtkWidget <span class="op">*</span>btns<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-56"><a href="#cb4-56"></a> tfe_text_view_save <span class="op">(</span>TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb4-57"><a href="#cb4-57"></a><span class="op">}</span></span>
|
||||
<span id="cb4-58"><a href="#cb4-58"></a></span>
|
||||
<span id="cb4-59"><a href="#cb4-59"></a><span class="dt">void</span></span>
|
||||
<span id="cb4-60"><a href="#cb4-60"></a>close_cb (GtkWidget *btnc) {</span>
|
||||
<span id="cb4-61"><a href="#cb4-61"></a> <span class="cf">if</span> (surface)</span>
|
||||
<span id="cb4-62"><a href="#cb4-62"></a> cairo_surface_destroy (surface);</span>
|
||||
<span id="cb4-63"><a href="#cb4-63"></a> gtk_window_destroy (GTK_WINDOW (win));</span>
|
||||
<span id="cb4-64"><a href="#cb4-64"></a>}</span>
|
||||
<span id="cb4-60"><a href="#cb4-60"></a>close_cb <span class="op">(</span>GtkWidget <span class="op">*</span>btnc<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-61"><a href="#cb4-61"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span></span>
|
||||
<span id="cb4-62"><a href="#cb4-62"></a> cairo_surface_destroy <span class="op">(</span>surface<span class="op">);</span></span>
|
||||
<span id="cb4-63"><a href="#cb4-63"></a> gtk_window_destroy <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb4-64"><a href="#cb4-64"></a><span class="op">}</span></span>
|
||||
<span id="cb4-65"><a href="#cb4-65"></a></span>
|
||||
<span id="cb4-66"><a href="#cb4-66"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb4-67"><a href="#cb4-67"></a>resize_cb (GtkDrawingArea *drawing_area, <span class="dt">int</span> width, <span class="dt">int</span> height, gpointer user_data) {</span>
|
||||
<span id="cb4-68"><a href="#cb4-68"></a> <span class="cf">if</span> (surface)</span>
|
||||
<span id="cb4-69"><a href="#cb4-69"></a> cairo_surface_destroy (surface);</span>
|
||||
<span id="cb4-70"><a href="#cb4-70"></a> surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);</span>
|
||||
<span id="cb4-71"><a href="#cb4-71"></a> run ();</span>
|
||||
<span id="cb4-72"><a href="#cb4-72"></a>}</span>
|
||||
<span id="cb4-67"><a href="#cb4-67"></a>resize_cb <span class="op">(</span>GtkDrawingArea <span class="op">*</span>drawing_area<span class="op">,</span> <span class="dt">int</span> width<span class="op">,</span> <span class="dt">int</span> height<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-68"><a href="#cb4-68"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span></span>
|
||||
<span id="cb4-69"><a href="#cb4-69"></a> cairo_surface_destroy <span class="op">(</span>surface<span class="op">);</span></span>
|
||||
<span id="cb4-70"><a href="#cb4-70"></a> surface <span class="op">=</span> cairo_image_surface_create <span class="op">(</span>CAIRO_FORMAT_ARGB32<span class="op">,</span> width<span class="op">,</span> height<span class="op">);</span></span>
|
||||
<span id="cb4-71"><a href="#cb4-71"></a> run <span class="op">();</span></span>
|
||||
<span id="cb4-72"><a href="#cb4-72"></a><span class="op">}</span></span>
|
||||
<span id="cb4-73"><a href="#cb4-73"></a></span>
|
||||
<span id="cb4-74"><a href="#cb4-74"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb4-75"><a href="#cb4-75"></a>draw_func (GtkDrawingArea *drawing_area, cairo_t *cr, <span class="dt">int</span> width, <span class="dt">int</span> height, gpointer user_data) {</span>
|
||||
<span id="cb4-76"><a href="#cb4-76"></a> <span class="cf">if</span> (surface) {</span>
|
||||
<span id="cb4-77"><a href="#cb4-77"></a> cairo_set_source_surface (cr, surface, <span class="dv">0</span>, <span class="dv">0</span>);</span>
|
||||
<span id="cb4-78"><a href="#cb4-78"></a> cairo_paint (cr);</span>
|
||||
<span id="cb4-79"><a href="#cb4-79"></a> }</span>
|
||||
<span id="cb4-80"><a href="#cb4-80"></a>}</span>
|
||||
<span id="cb4-75"><a href="#cb4-75"></a>draw_func <span class="op">(</span>GtkDrawingArea <span class="op">*</span>drawing_area<span class="op">,</span> cairo_t <span class="op">*</span>cr<span class="op">,</span> <span class="dt">int</span> width<span class="op">,</span> <span class="dt">int</span> height<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-76"><a href="#cb4-76"></a> <span class="cf">if</span> <span class="op">(</span>surface<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-77"><a href="#cb4-77"></a> cairo_set_source_surface <span class="op">(</span>cr<span class="op">,</span> surface<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||
<span id="cb4-78"><a href="#cb4-78"></a> cairo_paint <span class="op">(</span>cr<span class="op">);</span></span>
|
||||
<span id="cb4-79"><a href="#cb4-79"></a> <span class="op">}</span></span>
|
||||
<span id="cb4-80"><a href="#cb4-80"></a><span class="op">}</span></span>
|
||||
<span id="cb4-81"><a href="#cb4-81"></a></span>
|
||||
<span id="cb4-82"><a href="#cb4-82"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb4-83"><a href="#cb4-83"></a>app_activate (GApplication *application) {</span>
|
||||
<span id="cb4-84"><a href="#cb4-84"></a> gtk_widget_show (win);</span>
|
||||
<span id="cb4-85"><a href="#cb4-85"></a>}</span>
|
||||
<span id="cb4-83"><a href="#cb4-83"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-84"><a href="#cb4-84"></a> gtk_widget_show <span class="op">(</span>win<span class="op">);</span></span>
|
||||
<span id="cb4-85"><a href="#cb4-85"></a><span class="op">}</span></span>
|
||||
<span id="cb4-86"><a href="#cb4-86"></a></span>
|
||||
<span id="cb4-87"><a href="#cb4-87"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb4-88"><a href="#cb4-88"></a>app_startup (GApplication *application) {</span>
|
||||
<span id="cb4-89"><a href="#cb4-89"></a> GtkApplication *app = GTK_APPLICATION (application);</span>
|
||||
<span id="cb4-90"><a href="#cb4-90"></a> GtkBuilder *build;</span>
|
||||
<span id="cb4-88"><a href="#cb4-88"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-89"><a href="#cb4-89"></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="cb4-90"><a href="#cb4-90"></a> GtkBuilder <span class="op">*</span>build<span class="op">;</span></span>
|
||||
<span id="cb4-91"><a href="#cb4-91"></a></span>
|
||||
<span id="cb4-92"><a href="#cb4-92"></a> build = gtk_builder_new_from_resource (<span class="st">"/com/github/ToshioCP/color/color.ui"</span>);</span>
|
||||
<span id="cb4-93"><a href="#cb4-93"></a> win = GTK_WIDGET (gtk_builder_get_object (build, <span class="st">"win"</span>));</span>
|
||||
<span id="cb4-94"><a href="#cb4-94"></a> gtk_window_set_application (GTK_WINDOW (win), app);</span>
|
||||
<span id="cb4-95"><a href="#cb4-95"></a> tv = GTK_WIDGET (gtk_builder_get_object (build, <span class="st">"tv"</span>));</span>
|
||||
<span id="cb4-96"><a href="#cb4-96"></a> da = GTK_WIDGET (gtk_builder_get_object (build, <span class="st">"da"</span>));</span>
|
||||
<span id="cb4-97"><a href="#cb4-97"></a> g_object_unref(build);</span>
|
||||
<span id="cb4-98"><a href="#cb4-98"></a> g_signal_connect (GTK_DRAWING_AREA (da), <span class="st">"resize"</span>, G_CALLBACK (resize_cb), NULL);</span>
|
||||
<span id="cb4-99"><a href="#cb4-99"></a> gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), draw_func, NULL, NULL);</span>
|
||||
<span id="cb4-92"><a href="#cb4-92"></a> build <span class="op">=</span> gtk_builder_new_from_resource <span class="op">(</span><span class="st">"/com/github/ToshioCP/color/color.ui"</span><span class="op">);</span></span>
|
||||
<span id="cb4-93"><a href="#cb4-93"></a> win <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"win"</span><span class="op">));</span></span>
|
||||
<span id="cb4-94"><a href="#cb4-94"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> app<span class="op">);</span></span>
|
||||
<span id="cb4-95"><a href="#cb4-95"></a> tv <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"tv"</span><span class="op">));</span></span>
|
||||
<span id="cb4-96"><a href="#cb4-96"></a> da <span class="op">=</span> GTK_WIDGET <span class="op">(</span>gtk_builder_get_object <span class="op">(</span>build<span class="op">,</span> <span class="st">"da"</span><span class="op">));</span></span>
|
||||
<span id="cb4-97"><a href="#cb4-97"></a> g_object_unref<span class="op">(</span>build<span class="op">);</span></span>
|
||||
<span id="cb4-98"><a href="#cb4-98"></a> g_signal_connect <span class="op">(</span>GTK_DRAWING_AREA <span class="op">(</span>da<span class="op">),</span> <span class="st">"resize"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>resize_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb4-99"><a href="#cb4-99"></a> gtk_drawing_area_set_draw_func <span class="op">(</span>GTK_DRAWING_AREA <span class="op">(</span>da<span class="op">),</span> draw_func<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb4-100"><a href="#cb4-100"></a></span>
|
||||
<span id="cb4-101"><a href="#cb4-101"></a>GdkDisplay *display;</span>
|
||||
<span id="cb4-101"><a href="#cb4-101"></a>GdkDisplay <span class="op">*</span>display<span class="op">;</span></span>
|
||||
<span id="cb4-102"><a href="#cb4-102"></a></span>
|
||||
<span id="cb4-103"><a href="#cb4-103"></a> display = gtk_widget_get_display (GTK_WIDGET (win));</span>
|
||||
<span id="cb4-104"><a href="#cb4-104"></a> GtkCssProvider *provider = gtk_css_provider_new ();</span>
|
||||
<span id="cb4-105"><a href="#cb4-105"></a> gtk_css_provider_load_from_data (provider, <span class="st">"textview {padding: 10px; font-family: monospace; font-size: 12pt;}"</span>, -<span class="dv">1</span>);</span>
|
||||
<span id="cb4-106"><a href="#cb4-106"></a> gtk_style_context_add_provider_for_display (display, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER);</span>
|
||||
<span id="cb4-107"><a href="#cb4-107"></a>}</span>
|
||||
<span id="cb4-103"><a href="#cb4-103"></a> display <span class="op">=</span> gtk_widget_get_display <span class="op">(</span>GTK_WIDGET <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb4-104"><a href="#cb4-104"></a> GtkCssProvider <span class="op">*</span>provider <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span>
|
||||
<span id="cb4-105"><a href="#cb4-105"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> <span class="st">"textview {padding: 10px; font-family: monospace; font-size: 12pt;}"</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
||||
<span id="cb4-106"><a href="#cb4-106"></a> gtk_style_context_add_provider_for_display <span class="op">(</span>display<span class="op">,</span> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">),</span> GTK_STYLE_PROVIDER_PRIORITY_USER<span class="op">);</span></span>
|
||||
<span id="cb4-107"><a href="#cb4-107"></a><span class="op">}</span></span>
|
||||
<span id="cb4-108"><a href="#cb4-108"></a></span>
|
||||
<span id="cb4-109"><a href="#cb4-109"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.color"</span></span>
|
||||
<span id="cb4-110"><a href="#cb4-110"></a></span>
|
||||
<span id="cb4-111"><a href="#cb4-111"></a><span class="dt">int</span></span>
|
||||
<span id="cb4-112"><a href="#cb4-112"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb4-113"><a href="#cb4-113"></a> GtkApplication *app;</span>
|
||||
<span id="cb4-114"><a href="#cb4-114"></a> <span class="dt">int</span> stat;</span>
|
||||
<span id="cb4-112"><a href="#cb4-112"></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-113"><a href="#cb4-113"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb4-114"><a href="#cb4-114"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb4-115"><a href="#cb4-115"></a></span>
|
||||
<span id="cb4-116"><a href="#cb4-116"></a> app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);</span>
|
||||
<span id="cb4-116"><a href="#cb4-116"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_FLAGS_NONE<span class="op">);</span></span>
|
||||
<span id="cb4-117"><a href="#cb4-117"></a></span>
|
||||
<span id="cb4-118"><a href="#cb4-118"></a> g_signal_connect (app, <span class="st">"startup"</span>, G_CALLBACK (app_startup), NULL);</span>
|
||||
<span id="cb4-119"><a href="#cb4-119"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</span>
|
||||
<span id="cb4-118"><a href="#cb4-118"></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="cb4-119"><a href="#cb4-119"></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-120"><a href="#cb4-120"></a></span>
|
||||
<span id="cb4-121"><a href="#cb4-121"></a> stat =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb4-122"><a href="#cb4-122"></a> g_object_unref (app);</span>
|
||||
<span id="cb4-123"><a href="#cb4-123"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb4-124"><a href="#cb4-124"></a>}</span></code></pre></div>
|
||||
<span id="cb4-121"><a href="#cb4-121"></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-122"><a href="#cb4-122"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb4-123"><a href="#cb4-123"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb4-124"><a href="#cb4-124"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>109-124: The function <code>main</code> is almost same as before but there are some differences. The application ID is “com.github.ToshioCP.color”. <code>G_APPLICATION_FLAGS_NONE</code> is specified so no open signal handler is necessary.</li>
|
||||
<li>109-124: The function <code>main</code> is almost same as before but
|
||||
there are some differences. The application ID is
|
||||
“com.github.ToshioCP.color”. <code>G_APPLICATION_FLAGS_NONE</code> is
|
||||
specified so no open signal handler is necessary.</li>
|
||||
<li>87-107: Startup handler.</li>
|
||||
<li>92-97: Builds widgets. The pointers of the top window, TfeTextView and GtkDrawingArea objects are stored to static variables <code>win</code>, <code>tv</code> and <code>da</code> respectively. This is because these objects are often used in handlers. They never be rewritten so they’re thread safe.</li>
|
||||
<li>92-97: Builds widgets. The pointers of the top window, TfeTextView
|
||||
and GtkDrawingArea objects are stored to static variables
|
||||
<code>win</code>, <code>tv</code> and <code>da</code> respectively. This
|
||||
is because these objects are often used in handlers. They never be
|
||||
rewritten so they’re thread safe.</li>
|
||||
<li>98: connects “resize” signal and the handler.</li>
|
||||
<li>99: sets the drawing function.</li>
|
||||
<li>82-85: Activate handler, which just shows the widgets.</li>
|
||||
<li>74-80: The drawing function. It just copies <code>surface</code> to destination.</li>
|
||||
<li>66-72: Resize handler. Re-creates the surface to fit its width and height for the drawing area and paints by calling the function <code>run</code>.</li>
|
||||
<li>59-64: Close handler. It destroys <code>surface</code> if it exists. Then it destroys the top-level window and quits the application.</li>
|
||||
<li>49-57: Open and save handler. They just call the corresponding functions of TfeTextView.</li>
|
||||
<li>43-47: Run handler. It calls run function to paint the surface. After that <code>gtk_widget_queue_draw</code> is called. This function adds the widget (GtkDrawingArea) to the queue to be redrawn. It is important to know that the window is redrawn whenever it is necessary. For example, when another window is moved and uncovers part of the widget, or when the window containing it is resized. But repainting <code>surface</code> is not automatically notified to gtk. Therefore, you need to call <code>gtk_widget_queue_draw</code> to redraw the widget.</li>
|
||||
<li>9-41: Run function paints the surface. First, it gets the contents of GtkTextBuffer. Then it compares it to “red”, “green” and so on. If it matches the color, then the surface is painted the color. If it matches “light” or “dark”, then the color of the surface is lightened or darkened respectively. Alpha channel is used.</li>
|
||||
<li>74-80: The drawing function. It just copies <code>surface</code> to
|
||||
destination.</li>
|
||||
<li>66-72: Resize handler. Re-creates the surface to fit its width and
|
||||
height for the drawing area and paints by calling the function
|
||||
<code>run</code>.</li>
|
||||
<li>59-64: Close handler. It destroys <code>surface</code> if it exists.
|
||||
Then it destroys the top-level window and quits the application.</li>
|
||||
<li>49-57: Open and save handler. They just call the corresponding
|
||||
functions of TfeTextView.</li>
|
||||
<li>43-47: Run handler. It calls run function to paint the surface.
|
||||
After that <code>gtk_widget_queue_draw</code> is called. This function
|
||||
adds the widget (GtkDrawingArea) to the queue to be redrawn. It is
|
||||
important to know that the window is redrawn whenever it is necessary.
|
||||
For example, when another window is moved and uncovers part of the
|
||||
widget, or when the window containing it is resized. But repainting
|
||||
<code>surface</code> is not automatically notified to gtk. Therefore,
|
||||
you need to call <code>gtk_widget_queue_draw</code> to redraw the
|
||||
widget.</li>
|
||||
<li>9-41: Run function paints the surface. First, it gets the contents
|
||||
of GtkTextBuffer. Then it compares it to “red”, “green” and so on. If it
|
||||
matches the color, then the surface is painted the color. If it matches
|
||||
“light” or “dark”, then the color of the surface is lightened or
|
||||
darkened respectively. Alpha channel is used.</li>
|
||||
</ul>
|
||||
<h2 id="meson.build">Meson.build</h2>
|
||||
<p>This file is almost same as before. An argument “export_dynamic: true” is added to executable function.</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb5-1"><a href="#cb5-1"></a>project('color', 'c')</span>
|
||||
<p>This file is almost same as before. An argument “export_dynamic:
|
||||
true” is added to executable function.</p>
|
||||
<div class="sourceCode" id="cb5"><pre
|
||||
class="sourceCode numberSource numberLines"><code class="sourceCode"><span id="cb5-1"><a href="#cb5-1"></a>project('color', 'c')</span>
|
||||
<span id="cb5-2"><a href="#cb5-2"></a></span>
|
||||
<span id="cb5-3"><a href="#cb5-3"></a>gtkdep = dependency('gtk4')</span>
|
||||
<span id="cb5-4"><a href="#cb5-4"></a></span>
|
||||
|
@ -388,15 +448,24 @@
|
|||
<span id="cb5-9"><a href="#cb5-9"></a></span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a>executable('color', sourcefiles, resources, dependencies: gtkdep, export_dynamic: true)</span></code></pre></div>
|
||||
<h2 id="compile-and-execute-it">Compile and execute it</h2>
|
||||
<p>First you need to export some variables (refer to <a href="sec2.html">Section 2</a>) if you’ve installed Gtk4 from the source. If you’ve installed Gtk4 from the distribution packages, you don’t need to do this.</p>
|
||||
<p>First you need to export some variables (refer to <a
|
||||
href="sec2.html">Section 2</a>) if you’ve installed GTK 4 from the
|
||||
source. If you’ve installed GTK 4 from the distribution packages, you
|
||||
don’t need to do this.</p>
|
||||
<pre><code>$ . env.sh</code></pre>
|
||||
<p>Then type the following to compile it.</p>
|
||||
<pre><code>$ meson _build
|
||||
$ ninja -C _build</code></pre>
|
||||
<p>The application is made in <code>_build</code> directory. Type the following to execute it.</p>
|
||||
<p>The application is made in <code>_build</code> directory. Type the
|
||||
following to execute it.</p>
|
||||
<pre><code>$ _build/color</code></pre>
|
||||
<p>Type “red”, “green”, “blue”, “white”, black“,”light" or “dark” in the TfeTextView. Then, click on <code>Run</code> button. Make sure the color of GtkDrawingArea changes.</p>
|
||||
<p>In this program TfeTextView is used to change the color. You can use buttons or menus instead of textview. Probably it is more appropriate. Using textview is unnatural. It is a good practice to make such application by yourself.</p>
|
||||
<p>Type “red”, “green”, “blue”, “white”, black”, “light” or “dark” in
|
||||
the TfeTextView. Then, click on <code>Run</code> button. Make sure the
|
||||
color of GtkDrawingArea changes.</p>
|
||||
<p>In this program TfeTextView is used to change the color. You can use
|
||||
buttons or menus instead of textview. Probably it is more appropriate.
|
||||
Using textview is unnatural. It is a good practice to make such
|
||||
application by yourself.</p>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
|
589
docs/sec26.html
589
docs/sec26.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,188 +112,284 @@
|
|||
</div>
|
||||
</nav>
|
||||
<h1 id="gtklistview">GtkListView</h1>
|
||||
<p>Gtk4 has added new list objects GtkListView, GtkGridView and GtkColumnView. The new feature is described in <a href="https://docs.gtk.org/gtk4/section-list-widget.html">Gtk API Reference, List Widget Overview</a>.</p>
|
||||
<p>Gtk4 has other means to implement lists. They are GtkListBox and GtkTreeView which are took over from Gtk3. There’s an article in <a href="https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/">Gtk Development blog</a> about list widgets by Matthias Clasen. He described why GtkListView are developed to replace GtkListBox and GtkTreeView.</p>
|
||||
<p>I want to explain GtkListView and its related objects in this tutorial.</p>
|
||||
<p>GTK 4 has added new list objects GtkListView, GtkGridView and
|
||||
GtkColumnView. The new feature is described in <a
|
||||
href="https://docs.gtk.org/gtk4/section-list-widget.html">Gtk API
|
||||
Reference, List Widget Overview</a>.</p>
|
||||
<p>GTK 4 has other means to implement lists. They are GtkListBox and
|
||||
GtkTreeView which are took over from GTK 3. There’s an article in <a
|
||||
href="https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/">Gtk
|
||||
Development blog</a> about list widgets by Matthias Clasen. He described
|
||||
why GtkListView are developed to replace GtkListBox and GtkTreeView.</p>
|
||||
<p>I want to explain GtkListView and its related objects in this
|
||||
tutorial.</p>
|
||||
<h2 id="outline">Outline</h2>
|
||||
<p>A list is a sequential data structure. For example, an ordered string sequence “one”, “two”, “three”, “four” is a list. Each element of the list is called item. A list is like an array, but in many cases it is implemented with pointers which point to the next item of the list. And it has a start 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 it starts from zero (zero-based).</p>
|
||||
<p>Gio provides GListModel interface. It is a zero-based list of the same type of GObject objects, or objects that implement the same interface. An object implements GListModel is usually 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>A list is a sequential data structure. For example, an ordered string
|
||||
sequence “one”, “two”, “three”, “four” is a list. Each element of the
|
||||
list is called item. A list is like an array, but in many cases it is
|
||||
implemented with pointers which point to the next item of the list. And
|
||||
it has a start 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 it starts from
|
||||
zero (zero-based).</p>
|
||||
<p>Gio provides GListModel interface. It is a zero-based list of the
|
||||
same type of GObject objects, or objects that implement the same
|
||||
interface. An object implements GListModel is usually 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>
|
||||
<figure>
|
||||
<img src="image/list.png" alt="" /><figcaption>List</figcaption>
|
||||
<img src="image/list.png" alt="List" />
|
||||
<figcaption aria-hidden="true">List</figcaption>
|
||||
</figure>
|
||||
<p>The instruction to build the whole list related objects is:</p>
|
||||
<ol type="1">
|
||||
<li>Implement the list object which implements GListModel.</li>
|
||||
<li>Build widgets and put GtkListView as a child of GtkScrolledWindow.</li>
|
||||
<li>Build widgets and put GtkListView as a child of
|
||||
GtkScrolledWindow.</li>
|
||||
<li>Set GtkListItemFactory.</li>
|
||||
</ol>
|
||||
<h2 id="glistmodel">GListModel</h2>
|
||||
<p>If you want to make a list of strings with GListModel, for example, “one”, “two”, “three”, “four”, note that strings can’t be items of the list. Because GListModel is a list of GObject objects and strings aren’t GObject objects. So, you need a wrapper which is a GObject and contains a string. GtkStringObject is the wrapper object and GStringList, implements GListModel, is a list of GtkStringObject.</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"></a><span class="dt">char</span> *array[] = {<span class="st">"one"</span>, <span class="st">"two"</span>, <span class="st">"three"</span>, <span class="st">"four"</span>, NULL};</span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a>GtkStringList *stringlist = gtk_string_list_new ((<span class="dt">const</span> <span class="dt">char</span> * <span class="dt">const</span> *) array);</span></code></pre></div>
|
||||
<p>The function <code>gtk_string_list_new</code> creates GtkStringList object. Its items are GtkStringObject objects which contain the strings “one”, “two”, “three” and “four”. There are functions to add items to the list or remove items from the list.</p>
|
||||
<p>If you want to make a list of strings with GListModel, for example,
|
||||
“one”, “two”, “three”, “four”, note that strings can’t be items of the
|
||||
list. Because GListModel is a list of GObject objects and strings aren’t
|
||||
GObject objects. So, you need a wrapper which is a GObject and contains
|
||||
a string. GtkStringObject is the wrapper object and GStringList,
|
||||
implements GListModel, is a list of GtkStringObject.</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><span class="dt">char</span> <span class="op">*</span>array<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><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 class="op">};</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>GtkStringList <span class="op">*</span>stringlist <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></code></pre></div>
|
||||
<p>The function <code>gtk_string_list_new</code> creates GtkStringList
|
||||
object. Its items are GtkStringObject objects which contain the strings
|
||||
“one”, “two”, “three” and “four”. There are functions to add items to
|
||||
the list or remove items from the list.</p>
|
||||
<ul>
|
||||
<li><code>gtk_string_list_append</code> appends an item to the list</li>
|
||||
<li><code>gtk_string_list_remove</code> removes an item from the list</li>
|
||||
<li><code>gtk_string_list_get_string</code> gets a string in the list</li>
|
||||
<li><code>gtk_string_list_remove</code> removes an item from the
|
||||
list</li>
|
||||
<li><code>gtk_string_list_get_string</code> gets a string in the
|
||||
list</li>
|
||||
</ul>
|
||||
<p>See <a href="https://docs.gtk.org/gtk4/class.StringList.html">Gtk4 API Reference, GtkStringList</a> for further information.</p>
|
||||
<p>See <a href="https://docs.gtk.org/gtk4/class.StringList.html">GTK 4
|
||||
API Reference, GtkStringList</a> for further information.</p>
|
||||
<p>I’ll explain the other list objects later.</p>
|
||||
<h2 id="gtkselectionmodel">GtkSelectionModel</h2>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<ul>
|
||||
<li>GtkMultiSelection supports multiple selection.</li>
|
||||
<li>GtkNoSelection supports no selection. This is a wrapper to GListModel when GtkSelectionModel is needed.</li>
|
||||
<li>GtkNoSelection supports no selection. This is a wrapper to
|
||||
GListModel when GtkSelectionModel is needed.</li>
|
||||
<li>GtkSingleSelection supports single selection.</li>
|
||||
</ul>
|
||||
<h2 id="gtklistview-1">GtkListView</h2>
|
||||
<p>GtkListView is a widget to show GListModel items. GtkListItem is used by GtkListView to represent items of a list model. But, GtkListItem itself is not a widget, so a user needs to set a widget, for example GtkLabel, as a child of GtkListItem to display an item of the list model. “item” property of GtkListItem points an object that belongs to the list model.</p>
|
||||
<p>GtkListView is a widget to show GListModel items. GtkListItem is used
|
||||
by GtkListView to represent items of a list model. But, GtkListItem
|
||||
itself is not a widget, so a user needs to set a widget, for example
|
||||
GtkLabel, as a child of GtkListItem to display an item of the list
|
||||
model. “item” property of GtkListItem points an object that belongs to
|
||||
the list model.</p>
|
||||
<figure>
|
||||
<img src="image/gtklistitem.png" alt="" /><figcaption>GtkListItem</figcaption>
|
||||
<img src="image/gtklistitem.png" alt="GtkListItem" />
|
||||
<figcaption aria-hidden="true">GtkListItem</figcaption>
|
||||
</figure>
|
||||
<p>In case the number of items is very big, for example more than a thousand, GtkListItem is recycled and connected to another item which is newly displayed. This recycle makes the number of GtkListItem objects fairly small, less than 200. This is very effective to restrain the growth of memory consumption so that GListModel can contain lots of items, for example, more than a million items.</p>
|
||||
<p>In case the number of items is very big, for example more than a
|
||||
thousand, GtkListItem is recycled and connected to another item which is
|
||||
newly displayed. This recycle makes the number of GtkListItem objects
|
||||
fairly small, less than 200. This is very effective to restrain the
|
||||
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 factory, GtkSignalListItemFactory and GtkBuilderListItemFactory.</p>
|
||||
<p>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.</p>
|
||||
<h3 id="gtksignallistitemfactory">GtkSignalListItemFactory</h3>
|
||||
<p>GtkSignalListItemFactory provides signals for users to configure a GtkListItem object. There are four signals.</p>
|
||||
<p>GtkSignalListItemFactory provides signals for users to configure a
|
||||
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 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. For example, a user gets the item from “item” property of the GtkListItem instance. Then gets the string of the item and sets the label property of the GtkLabel instance with the string. This signal is emitted when the GtkListItem is newly created, recycled or some changes has happened to the item of the list.</li>
|
||||
<li>“unbind” is emitted to unbind an item. A user undoes everything done in step 2 in the signal handler. If some object are created in step 2, they must be destroyed.</li>
|
||||
<li>“teardown” is emitted to undo everything done in step 1. So, the widget created in step 1 must be destroyed. After this signal, the list item will be destroyed.</li>
|
||||
<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 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.
|
||||
For example, a user gets the item from “item” property of the
|
||||
GtkListItem instance. Then gets the string of the item and sets the
|
||||
label property of the GtkLabel instance with the string. This signal is
|
||||
emitted when the GtkListItem is newly created, recycled or some changes
|
||||
has happened to the item of the list.</li>
|
||||
<li>“unbind” is emitted to unbind an item. A user undoes everything done
|
||||
in step 2 in the signal handler. If some object are created in step 2,
|
||||
they must be destroyed.</li>
|
||||
<li>“teardown” is emitted to undo everything done in step 1. So, the
|
||||
widget created in step 1 must be destroyed. After this signal, the list
|
||||
item will be destroyed.</li>
|
||||
</ol>
|
||||
<p>The following program <code>list1.c</code> shows the list of strings “one”, “two”, “three” and “four”. GtkNoSelection is used, so user can’t select any item.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<p>The following program <code>list1.c</code> shows the list of strings
|
||||
“one”, “two”, “three” and “four”. GtkNoSelection is used, so user can’t
|
||||
select any item.</p>
|
||||
<div class="sourceCode" id="cb2"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2"></a></span>
|
||||
<span id="cb2-3"><a href="#cb2-3"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-4"><a href="#cb2-4"></a>setup_cb (GtkListItemFactory *factory, GtkListItem *listitem, gpointer user_data) {</span>
|
||||
<span id="cb2-5"><a href="#cb2-5"></a> GtkWidget *lb = gtk_label_new (NULL);</span>
|
||||
<span id="cb2-6"><a href="#cb2-6"></a> gtk_list_item_set_child (listitem, lb);</span>
|
||||
<span id="cb2-7"><a href="#cb2-7"></a>}</span>
|
||||
<span id="cb2-4"><a href="#cb2-4"></a>setup_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<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 (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_data) {</span>
|
||||
<span id="cb2-11"><a href="#cb2-11"></a> GtkWidget *lb = gtk_list_item_get_child (listitem);</span>
|
||||
<span id="cb2-12"><a href="#cb2-12"></a> GtkStringObject *strobj = gtk_list_item_get_item (listitem);</span>
|
||||
<span id="cb2-13"><a href="#cb2-13"></a> <span class="dt">const</span> <span class="dt">char</span> *text = gtk_string_object_get_string (strobj);</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> 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-13"><a href="#cb2-13"></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-14"><a href="#cb2-14"></a></span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></a> gtk_label_set_text (GTK_LABEL (lb), text);</span>
|
||||
<span id="cb2-16"><a href="#cb2-16"></a>}</span>
|
||||
<span id="cb2-15"><a href="#cb2-15"></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-16"><a href="#cb2-16"></a><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 class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-19"><a href="#cb2-19"></a>unbind_cb (GtkSignalListItemFactory *self, GtkListItem *listitem, gpointer user_data) {</span>
|
||||
<span id="cb2-19"><a href="#cb2-19"></a>unbind_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-20"><a href="#cb2-20"></a> <span class="co">/* There's nothing to do here. */</span></span>
|
||||
<span id="cb2-21"><a href="#cb2-21"></a> <span class="co">/* If you does something like setting a signal in bind_cb, */</span></span>
|
||||
<span id="cb2-22"><a href="#cb2-22"></a> <span class="co">/* then disconnecting the signal is necessary in unbind_cb. */</span></span>
|
||||
<span id="cb2-23"><a href="#cb2-23"></a>}</span>
|
||||
<span id="cb2-23"><a href="#cb2-23"></a><span class="op">}</span></span>
|
||||
<span id="cb2-24"><a href="#cb2-24"></a></span>
|
||||
<span id="cb2-25"><a href="#cb2-25"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-26"><a href="#cb2-26"></a>teardown_cb (GtkListItemFactory *factory, GtkListItem *listitem, gpointer user_data) {</span>
|
||||
<span id="cb2-27"><a href="#cb2-27"></a> gtk_list_item_set_child (listitem, NULL);</span>
|
||||
<span id="cb2-26"><a href="#cb2-26"></a>teardown_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<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-27"><a href="#cb2-27"></a> gtk_list_item_set_child <span class="op">(</span>listitem<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb2-28"><a href="#cb2-28"></a><span class="co">/* When the child of listitem is set to NULL, the reference to GtkLabel will be released and lb will be destroyed. */</span></span>
|
||||
<span id="cb2-29"><a href="#cb2-29"></a><span class="co">/* Therefore, g_object_unref () for the GtkLabel object doesn't need in the user code. */</span></span>
|
||||
<span id="cb2-30"><a href="#cb2-30"></a>}</span>
|
||||
<span id="cb2-30"><a href="#cb2-30"></a><span class="op">}</span></span>
|
||||
<span id="cb2-31"><a href="#cb2-31"></a></span>
|
||||
<span id="cb2-32"><a href="#cb2-32"></a><span class="co">/* ----- activate, open, startup handlers ----- */</span></span>
|
||||
<span id="cb2-33"><a href="#cb2-33"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-34"><a href="#cb2-34"></a>app_activate (GApplication *application) {</span>
|
||||
<span id="cb2-35"><a href="#cb2-35"></a> GtkApplication *app = GTK_APPLICATION (application);</span>
|
||||
<span id="cb2-36"><a href="#cb2-36"></a> GtkWidget *win = gtk_application_window_new (app);</span>
|
||||
<span id="cb2-37"><a href="#cb2-37"></a> gtk_window_set_default_size (GTK_WINDOW (win), <span class="dv">600</span>, <span class="dv">400</span>);</span>
|
||||
<span id="cb2-38"><a href="#cb2-38"></a> GtkWidget *scr = gtk_scrolled_window_new ();</span>
|
||||
<span id="cb2-39"><a href="#cb2-39"></a> gtk_window_set_child (GTK_WINDOW (win), scr);</span>
|
||||
<span id="cb2-34"><a href="#cb2-34"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-35"><a href="#cb2-35"></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="cb2-36"><a href="#cb2-36"></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="cb2-37"><a href="#cb2-37"></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="cb2-38"><a href="#cb2-38"></a> GtkWidget <span class="op">*</span>scr <span class="op">=</span> gtk_scrolled_window_new <span class="op">();</span></span>
|
||||
<span id="cb2-39"><a href="#cb2-39"></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="cb2-40"><a href="#cb2-40"></a></span>
|
||||
<span id="cb2-41"><a href="#cb2-41"></a> <span class="dt">char</span> *array[] = {</span>
|
||||
<span id="cb2-42"><a href="#cb2-42"></a> <span class="st">"one"</span>, <span class="st">"two"</span>, <span class="st">"three"</span>, <span class="st">"four"</span>, NULL</span>
|
||||
<span id="cb2-43"><a href="#cb2-43"></a> };</span>
|
||||
<span id="cb2-44"><a href="#cb2-44"></a> GtkStringList *sl = gtk_string_list_new ((<span class="dt">const</span> <span class="dt">char</span> * <span class="dt">const</span> *) array);</span>
|
||||
<span id="cb2-45"><a href="#cb2-45"></a> GtkNoSelection *ns = gtk_no_selection_new (G_LIST_MODEL (sl));</span>
|
||||
<span id="cb2-41"><a href="#cb2-41"></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="cb2-42"><a href="#cb2-42"></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="cb2-43"><a href="#cb2-43"></a> <span class="op">};</span></span>
|
||||
<span id="cb2-44"><a href="#cb2-44"></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="cb2-45"><a href="#cb2-45"></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>sl<span class="op">));</span></span>
|
||||
<span id="cb2-46"><a href="#cb2-46"></a></span>
|
||||
<span id="cb2-47"><a href="#cb2-47"></a> GtkListItemFactory *factory = gtk_signal_list_item_factory_new ();</span>
|
||||
<span id="cb2-48"><a href="#cb2-48"></a> g_signal_connect (factory, <span class="st">"setup"</span>, G_CALLBACK (setup_cb), NULL);</span>
|
||||
<span id="cb2-49"><a href="#cb2-49"></a> g_signal_connect (factory, <span class="st">"bind"</span>, G_CALLBACK (bind_cb), NULL);</span>
|
||||
<span id="cb2-50"><a href="#cb2-50"></a> g_signal_connect (factory, <span class="st">"unbind"</span>, G_CALLBACK (unbind_cb), NULL);</span>
|
||||
<span id="cb2-51"><a href="#cb2-51"></a> g_signal_connect (factory, <span class="st">"teardown"</span>, G_CALLBACK (teardown_cb), NULL);</span>
|
||||
<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 *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ns), factory);</span>
|
||||
<span id="cb2-54"><a href="#cb2-54"></a> gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);</span>
|
||||
<span id="cb2-55"><a href="#cb2-55"></a> gtk_widget_show (win);</span>
|
||||
<span id="cb2-56"><a href="#cb2-56"></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_widget_show <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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-59"><a href="#cb2-59"></a>app_startup (GApplication *application) {</span>
|
||||
<span id="cb2-60"><a href="#cb2-60"></a>}</span>
|
||||
<span id="cb2-59"><a href="#cb2-59"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-60"><a href="#cb2-60"></a><span class="op">}</span></span>
|
||||
<span id="cb2-61"><a href="#cb2-61"></a></span>
|
||||
<span id="cb2-62"><a href="#cb2-62"></a><span class="co">/* ----- main ----- */</span></span>
|
||||
<span id="cb2-63"><a href="#cb2-63"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.list1"</span></span>
|
||||
<span id="cb2-64"><a href="#cb2-64"></a></span>
|
||||
<span id="cb2-65"><a href="#cb2-65"></a><span class="dt">int</span></span>
|
||||
<span id="cb2-66"><a href="#cb2-66"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb2-67"><a href="#cb2-67"></a> GtkApplication *app;</span>
|
||||
<span id="cb2-68"><a href="#cb2-68"></a> <span class="dt">int</span> stat;</span>
|
||||
<span id="cb2-66"><a href="#cb2-66"></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-67"><a href="#cb2-67"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb2-68"><a href="#cb2-68"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb2-69"><a href="#cb2-69"></a></span>
|
||||
<span id="cb2-70"><a href="#cb2-70"></a> app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);</span>
|
||||
<span id="cb2-70"><a href="#cb2-70"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_FLAGS_NONE<span class="op">);</span></span>
|
||||
<span id="cb2-71"><a href="#cb2-71"></a></span>
|
||||
<span id="cb2-72"><a href="#cb2-72"></a> g_signal_connect (app, <span class="st">"startup"</span>, G_CALLBACK (app_startup), NULL);</span>
|
||||
<span id="cb2-73"><a href="#cb2-73"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</span>
|
||||
<span id="cb2-72"><a href="#cb2-72"></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="cb2-73"><a href="#cb2-73"></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-74"><a href="#cb2-74"></a></span>
|
||||
<span id="cb2-75"><a href="#cb2-75"></a> stat =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb2-76"><a href="#cb2-76"></a> g_object_unref (app);</span>
|
||||
<span id="cb2-77"><a href="#cb2-77"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb2-78"><a href="#cb2-78"></a>}</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. (If you’ve installed Gtk4 from the source to $HOME/local, then your bin directory is $Home/local/bin. Otherwise, $Home/bin is your private bin directory.)</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="fu">gcc</span> <span class="kw">`</span><span class="ex">pkg-config</span> --cflags gtk4<span class="kw">`</span> <span class="va">$1</span>.c <span class="kw">`</span><span class="ex">pkg-config</span> --libs gtk4<span class="kw">`</span></span></code></pre></div>
|
||||
<p>Change the current directory to the directory includes <code>list1.c</code> and type as follows.</p>
|
||||
<span id="cb2-75"><a href="#cb2-75"></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-76"><a href="#cb2-76"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb2-77"><a href="#cb2-77"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb2-78"><a href="#cb2-78"></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.
|
||||
(If you’ve installed GTK 4 from the source to $HOME/local, then your bin
|
||||
directory is $Home/local/bin. Otherwise, $Home/bin is your private bin
|
||||
directory.)</p>
|
||||
<div class="sourceCode" id="cb3"><pre
|
||||
class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gcc</span> <span class="kw">`</span><span class="ex">pkg-config</span> <span class="at">--cflags</span> gtk4<span class="kw">`</span> <span class="va">$1</span>.c <span class="kw">`</span><span class="ex">pkg-config</span> <span class="at">--libs</span> gtk4<span class="kw">`</span></span></code></pre></div>
|
||||
<p>Change the current directory to the directory includes
|
||||
<code>list1.c</code> and type as follows.</p>
|
||||
<pre><code>$ chmod 755 $HOME/local/bin/comp # or chmod 755 $Home/bin/comp
|
||||
$ comp list1
|
||||
$ ./a.out</code></pre>
|
||||
<p>Then, <code>list1.c</code> has been compiled and executed.</p>
|
||||
<figure>
|
||||
<img src="image/list1.png" alt="" /><figcaption>list1</figcaption>
|
||||
<img src="image/list1.png" alt="list1" />
|
||||
<figcaption aria-hidden="true">list1</figcaption>
|
||||
</figure>
|
||||
<p>I think the program is not so difficult. If you feel some difficulty, read this section again, especially GtkSignalListItemFactory subsubsection.</p>
|
||||
<p>I think the program is not so difficult. If you feel some difficulty,
|
||||
read this section again, especially GtkSignalListItemFactory
|
||||
subsubsection.</p>
|
||||
<h3 id="gtkbuilderlistitemfactory">GtkBuilderListItemFactory</h3>
|
||||
<p>GtkBuilderListItemFactory is another GtkListItemFactory. Its behavior is defined with ui file.</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="kw"><interface></span></span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a> <span class="kw"><template</span><span class="ot"> class=</span><span class="st">"GtkListItem"</span><span class="kw">></span></span>
|
||||
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"child"</span><span class="kw">></span></span>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="kw">></span></span>
|
||||
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a> <span class="kw"><binding</span><span class="ot"> name=</span><span class="st">"label"</span><span class="kw">></span></span>
|
||||
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a> <span class="kw"><lookup</span><span class="ot"> name=</span><span class="st">"string"</span><span class="ot"> type=</span><span class="st">"GtkStringObject"</span><span class="kw">></span></span>
|
||||
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a> <span class="kw"><lookup</span><span class="ot"> name=</span><span class="st">"item"</span><span class="kw">></span>GtkListItem<span class="kw"></lookup></span></span>
|
||||
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a> <span class="kw"></lookup></span></span>
|
||||
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a> <span class="kw"></binding></span></span>
|
||||
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a> <span class="kw"></template></span></span>
|
||||
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a><span class="kw"></interface></span></span></code></pre></div>
|
||||
<p>Template tag is used to define GtkListItem. 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.</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>
|
||||
<p>GtkBuilderListItemFactory is another GtkListItemFactory. Its behavior
|
||||
is defined with ui file.</p>
|
||||
<div class="sourceCode" id="cb5"><pre
|
||||
class="sourceCode xml"><code class="sourceCode xml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><<span class="kw">interface</span>></span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> <<span class="kw">template</span><span class="ot"> class=</span><span class="st">"GtkListItem"</span>></span>
|
||||
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"child"</span>></span>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
||||
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
||||
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"string"</span><span class="ot"> type=</span><span class="st">"GtkStringObject"</span>></span>
|
||||
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"item"</span>>GtkListItem</<span class="kw">lookup</span>></span>
|
||||
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a> </<span class="kw">lookup</span>></span>
|
||||
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> </<span class="kw">binding</span>></span>
|
||||
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a> </<span class="kw">template</span>></span>
|
||||
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||
<p>Template tag is used to define GtkListItem. 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.</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>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 href="https://blog.gtk.org/2020/09/05/a-primer-on-gtklistview/">GTK Development Blog</a> by Matthias Clasen.</p>
|
||||
<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
|
||||
href="https://blog.gtk.org/2020/09/05/a-primer-on-gtklistview/">GTK
|
||||
Development Blog</a> by Matthias Clasen.</p>
|
||||
<blockquote>
|
||||
<p>Remember that the classname (GtkListItem) in a ui template is used as the “this” pointer referring to the object that is being instantiated.</p>
|
||||
<p>Remember that the classname (GtkListItem) in a ui template is used as
|
||||
the “this” pointer referring to the object that is being
|
||||
instantiated.</p>
|
||||
</blockquote>
|
||||
<p>Therefore, GtkListItem instance is used as the <code>this</code> object of the lookup tag when it is evaluated. <code>this</code> object will be explained in <a href="sec28.html">section 28</a>.</p>
|
||||
<p>The C source code is as follows. Its name is <code>list2.c</code> and 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>
|
||||
<p>Therefore, GtkListItem instance is used as the <code>this</code>
|
||||
object of the lookup tag when it is evaluated. <code>this</code> object
|
||||
will be explained in <a href="sec28.html">section 28</a>.</p>
|
||||
<p>The C source code is as follows. Its name is <code>list2.c</code> and
|
||||
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 (GApplication *application) {</span>
|
||||
<span id="cb7-6"><a href="#cb7-6"></a> GtkApplication *app = GTK_APPLICATION (application);</span>
|
||||
<span id="cb7-7"><a href="#cb7-7"></a> GtkWidget *win = gtk_application_window_new (app);</span>
|
||||
<span id="cb7-8"><a href="#cb7-8"></a> gtk_window_set_default_size (GTK_WINDOW (win), <span class="dv">600</span>, <span class="dv">400</span>);</span>
|
||||
<span id="cb7-9"><a href="#cb7-9"></a> GtkWidget *scr = gtk_scrolled_window_new ();</span>
|
||||
<span id="cb7-10"><a href="#cb7-10"></a> gtk_window_set_child (GTK_WINDOW (win), scr);</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> *array[] = {</span>
|
||||
<span id="cb7-13"><a href="#cb7-13"></a> <span class="st">"one"</span>, <span class="st">"two"</span>, <span class="st">"three"</span>, <span class="st">"four"</span>, NULL</span>
|
||||
<span id="cb7-14"><a href="#cb7-14"></a> };</span>
|
||||
<span id="cb7-15"><a href="#cb7-15"></a> GtkStringList *sl = gtk_string_list_new ((<span class="dt">const</span> <span class="dt">char</span> * <span class="dt">const</span> *) array);</span>
|
||||
<span id="cb7-16"><a href="#cb7-16"></a> GtkSingleSelection *ss = gtk_single_selection_new (G_LIST_MODEL (sl));</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> *ui_string =</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>
|
||||
|
@ -307,42 +403,52 @@ $ ./a.out</code></pre>
|
|||
<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>
|
||||
<span id="cb7-33"><a href="#cb7-33"></a> GBytes *gbytes = g_bytes_new_static (ui_string, strlen (ui_string));</span>
|
||||
<span id="cb7-34"><a href="#cb7-34"></a> GtkListItemFactory *factory = gtk_builder_list_item_factory_new_from_bytes (NULL, gbytes);</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 *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ss), factory);</span>
|
||||
<span id="cb7-37"><a href="#cb7-37"></a> gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);</span>
|
||||
<span id="cb7-38"><a href="#cb7-38"></a> gtk_widget_show (win);</span>
|
||||
<span id="cb7-39"><a href="#cb7-39"></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_widget_show <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-40"><a href="#cb7-40"></a></span>
|
||||
<span id="cb7-41"><a href="#cb7-41"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb7-42"><a href="#cb7-42"></a>app_startup (GApplication *application) {</span>
|
||||
<span id="cb7-43"><a href="#cb7-43"></a>}</span>
|
||||
<span id="cb7-42"><a href="#cb7-42"></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-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="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb7-50"><a href="#cb7-50"></a> GtkApplication *app;</span>
|
||||
<span id="cb7-51"><a href="#cb7-51"></a> <span class="dt">int</span> stat;</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> app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);</span>
|
||||
<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_FLAGS_NONE<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 (app, <span class="st">"startup"</span>, G_CALLBACK (app_startup), NULL);</span>
|
||||
<span id="cb7-56"><a href="#cb7-56"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</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 =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb7-59"><a href="#cb7-59"></a> g_object_unref (app);</span>
|
||||
<span id="cb7-60"><a href="#cb7-60"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb7-61"><a href="#cb7-61"></a>}</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 string.</p>
|
||||
<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
|
||||
string.</p>
|
||||
<h2 id="gtkdirectorylist">GtkDirectoryList</h2>
|
||||
<p>GtkDirectoryList is a list model containing GFileInfo objects which are information of files under a certain directory. It uses <code>g_file_enumerate_children_async()</code> to get the GFileInfo objects. The list model is created by <code>gtk_directory_list_new</code> function.</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"></a>GtkDirectoryList *gtk_directory_list_new (<span class="dt">const</span> <span class="dt">char</span> *attributes, GFile *file);</span></code></pre></div>
|
||||
<p><code>attributes</code> is a comma separated list of file attributes. File attributes are key-value pairs. A key consists of a namespace and a name. For example, “standard::name” key is the name of a file. “standard” means general file information. “name” means filename. The following table shows some example.</p>
|
||||
<p>GtkDirectoryList is a list model containing GFileInfo objects which
|
||||
are information of files under a certain directory. It uses
|
||||
<code>g_file_enumerate_children_async()</code> to get the GFileInfo
|
||||
objects. The list model is created by
|
||||
<code>gtk_directory_list_new</code> function.</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>GtkDirectoryList <span class="op">*</span>gtk_directory_list_new <span class="op">(</span><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>attributes<span class="op">,</span> GFile <span class="op">*</span>file<span class="op">);</span></span></code></pre></div>
|
||||
<p><code>attributes</code> is a comma separated list of file attributes.
|
||||
File attributes are key-value pairs. A key consists of a namespace and a
|
||||
name. For example, “standard::name” key is the name of a file.
|
||||
“standard” means general file information. “name” means filename. The
|
||||
following table shows some example.</p>
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width: 19%" />
|
||||
|
@ -357,7 +463,8 @@ $ ./a.out</code></pre>
|
|||
<tbody>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">standard::type</td>
|
||||
<td style="text-align: left;">file type. for example, regular file, directory, symbolic link, etc.</td>
|
||||
<td style="text-align: left;">file type. for example, regular file,
|
||||
directory, symbolic link, etc.</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">standard::name</td>
|
||||
|
@ -369,74 +476,105 @@ $ ./a.out</code></pre>
|
|||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">access::can-read</td>
|
||||
<td style="text-align: left;">read privilege if the user is able to read the file</td>
|
||||
<td style="text-align: left;">read privilege if the user is able to read
|
||||
the file</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">time::modified</td>
|
||||
<td style="text-align: left;">the time the file was last modified in seconds since the UNIX epoch</td>
|
||||
<td style="text-align: left;">the time the file was last modified in
|
||||
seconds since the UNIX epoch</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The current directory is “.”. The following program makes GtkDirectoryList <code>dl</code> and its contents are GFileInfo objects under the current directory.</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a>GFile *file = g_file_new_for_path (<span class="st">"."</span>);</span>
|
||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a>GtkDirectoryList *dl = gtk_directory_list_new (<span class="st">"standard::name"</span>, file);</span>
|
||||
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a>g_object_unref (file);</span></code></pre></div>
|
||||
<p>It is not so difficult to make file listing program by changing <code>list2.c</code> in the previous subsection. One problem is that GInfoFile doesn’t have properties. Lookup tag look for a property, so it is useless for looking for a filename from a GFileInfo object. Instead, 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"></a><span class="dt">char</span> *</span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a>get_file_name (GtkListItem *item, GFileInfo *info) {</span>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a> <span class="cf">if</span> (! G_IS_FILE_INFO (info))</span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a> <span class="cf">return</span> NULL;</span>
|
||||
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a> <span class="cf">else</span></span>
|
||||
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a> <span class="cf">return</span> g_strdup (g_file_info_get_name (info));</span>
|
||||
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a>}</span>
|
||||
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a></span>
|
||||
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a>... ...</span>
|
||||
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a>... ...</span>
|
||||
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a></span>
|
||||
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a><span class="st">"<interface>"</span></span>
|
||||
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></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"></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"></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"></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"></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"></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"></a> <span class="st">"</closure>"</span></span>
|
||||
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true"></a> <span class="st">"</binding>"</span></span>
|
||||
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true"></a> <span class="st">"</object>"</span></span>
|
||||
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true"></a> <span class="st">"</property>"</span></span>
|
||||
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true"></a> <span class="st">"</template>"</span></span>
|
||||
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true"></a><span class="st">"</interface>"</span></span></code></pre></div>
|
||||
<p>The current directory is “.”. The following program makes
|
||||
GtkDirectoryList <code>dl</code> and its contents are GFileInfo objects
|
||||
under the current directory.</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></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="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></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="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>g_object_unref <span class="op">(</span>file<span class="op">);</span></span></code></pre></div>
|
||||
<p>It is not so difficult to make file listing program by changing
|
||||
<code>list2.c</code> in the previous subsection. One problem is that
|
||||
GInfoFile doesn’t have properties. Lookup tag look for a property, so it
|
||||
is useless for looking for a filename from a GFileInfo object. Instead,
|
||||
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">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>
|
||||
<ul>
|
||||
<li>“gchararray” is the type name of strings. “gchar” is the same as “char” type. 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 attribute specifies the function name and type attribute specifies the type of the return value of the function. The contents of closure tag (it is between <closure…> and</closure>) is parameters of 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 check the <code>info</code> parameter. Because it can be NULL when GListItem <code>item</code> is unbound. If its GFileInfo, then return the filename (copy of the filename).</li>
|
||||
<li>“gchararray” is the type name of strings. “gchar” is the same as
|
||||
“char” type. 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
|
||||
attribute specifies the function name and type attribute specifies the
|
||||
type of the return value of the function. The contents of closure tag
|
||||
(it is between <closure…> and</closure>) is parameters of
|
||||
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 check the
|
||||
<code>info</code> parameter. Because it can be NULL when GListItem
|
||||
<code>item</code> is unbound. If its GFileInfo, then return the filename
|
||||
(copy of the filename).</li>
|
||||
</ul>
|
||||
<p>The whole program (<code>list3.c</code>) is as follows. The program is located in src/misc directory.</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<p>The whole program (<code>list3.c</code>) is as follows. The program
|
||||
is located in src/misc directory.</p>
|
||||
<div class="sourceCode" id="cb11"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<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>
|
||||
<span id="cb11-4"><a href="#cb11-4"></a>get_file_name (GtkListItem *item, GFileInfo *info) {</span>
|
||||
<span id="cb11-5"><a href="#cb11-5"></a> <span class="cf">if</span> (! G_IS_FILE_INFO (info))</span>
|
||||
<span id="cb11-6"><a href="#cb11-6"></a> <span class="cf">return</span> NULL;</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 (g_file_info_get_name (info));</span>
|
||||
<span id="cb11-9"><a href="#cb11-9"></a>}</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 (GApplication *application) {</span>
|
||||
<span id="cb11-14"><a href="#cb11-14"></a> GtkApplication *app = GTK_APPLICATION (application);</span>
|
||||
<span id="cb11-15"><a href="#cb11-15"></a> GtkWidget *win = gtk_application_window_new (app);</span>
|
||||
<span id="cb11-16"><a href="#cb11-16"></a> gtk_window_set_default_size (GTK_WINDOW (win), <span class="dv">600</span>, <span class="dv">400</span>);</span>
|
||||
<span id="cb11-17"><a href="#cb11-17"></a> GtkWidget *scr = gtk_scrolled_window_new ();</span>
|
||||
<span id="cb11-18"><a href="#cb11-18"></a> gtk_window_set_child (GTK_WINDOW (win), scr);</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 *file = g_file_new_for_path (<span class="st">"."</span>);</span>
|
||||
<span id="cb11-21"><a href="#cb11-21"></a> GtkDirectoryList *dl = gtk_directory_list_new (<span class="st">"standard::name"</span>, file);</span>
|
||||
<span id="cb11-22"><a href="#cb11-22"></a> g_object_unref (file);</span>
|
||||
<span id="cb11-23"><a href="#cb11-23"></a> GtkNoSelection *ns = gtk_no_selection_new (G_LIST_MODEL (dl));</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> *ui_string =</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>
|
||||
|
@ -450,55 +588,70 @@ $ ./a.out</code></pre>
|
|||
<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>
|
||||
<span id="cb11-40"><a href="#cb11-40"></a> GBytes *gbytes = g_bytes_new_static (ui_string, strlen (ui_string));</span>
|
||||
<span id="cb11-41"><a href="#cb11-41"></a> GtkListItemFactory *factory = gtk_builder_list_item_factory_new_from_bytes (NULL, gbytes);</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 *lv = gtk_list_view_new (GTK_SELECTION_MODEL (ns), factory);</span>
|
||||
<span id="cb11-44"><a href="#cb11-44"></a> gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), lv);</span>
|
||||
<span id="cb11-45"><a href="#cb11-45"></a> gtk_widget_show (win);</span>
|
||||
<span id="cb11-46"><a href="#cb11-46"></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_widget_show <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 (GApplication *application) {</span>
|
||||
<span id="cb11-50"><a href="#cb11-50"></a>}</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-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="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb11-57"><a href="#cb11-57"></a> GtkApplication *app;</span>
|
||||
<span id="cb11-58"><a href="#cb11-58"></a> <span class="dt">int</span> stat;</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 = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);</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_FLAGS_NONE<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 (app, <span class="st">"startup"</span>, G_CALLBACK (app_startup), NULL);</span>
|
||||
<span id="cb11-63"><a href="#cb11-63"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</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 =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb11-66"><a href="#cb11-66"></a> g_object_unref (app);</span>
|
||||
<span id="cb11-67"><a href="#cb11-67"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb11-68"><a href="#cb11-68"></a>}</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>
|
||||
<p>Generally, a symbol table is used by a linker to link objects to an executable file. It includes function names and their location. A linker usually doesn’t put a symbol table into the created executable file. But if <code>--export-dynamic</code> option is given, the linker adds the symbol table to the executable file.</p>
|
||||
<p>To accomplish it, an option <code>-Wl,--export-dynamic</code> is given to the C compiler.</p>
|
||||
<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>
|
||||
<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>
|
||||
<p>Generally, a symbol table is used by a linker to link objects to an
|
||||
executable file. It includes function names and their location. A linker
|
||||
usually doesn’t put a symbol table into the created executable file. But
|
||||
if <code>--export-dynamic</code> option is given, the linker adds the
|
||||
symbol table to the executable file.</p>
|
||||
<p>To accomplish it, an option <code>-Wl,--export-dynamic</code> is
|
||||
given to the C compiler.</p>
|
||||
<ul>
|
||||
<li><code>-Wl</code> is a C compiler option that passes the following option to the linker.</li>
|
||||
<li><code>--export-dynamic</code> is a linker option. The following is cited from the linker document. “When creating a dynamically linked executable, add all symbols to the dynamic symbol table. The dynamic symbol table is the set of symbols which are visible from dynamic objects at run time.”</li>
|
||||
<li><code>-Wl</code> is a C compiler option that passes the following
|
||||
option to the linker.</li>
|
||||
<li><code>--export-dynamic</code> is a linker option. The following is
|
||||
cited from the linker document. “When creating a dynamically linked
|
||||
executable, add all symbols to the dynamic symbol table. The dynamic
|
||||
symbol table is the set of symbols which are visible from dynamic
|
||||
objects at run time.”</li>
|
||||
</ul>
|
||||
<p>Compile and execute it.</p>
|
||||
<pre><code>$ gcc -Wl,--export-dynamic `pkg-config --cflags gtk4` list3.c `pkg-config --libs gtk4`</code></pre>
|
||||
<p>You can also make a shell script to compile <code>list3.c</code></p>
|
||||
<div class="sourceCode" id="cb13"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a><span class="fu">gcc</span> -Wl,--export-dynamic <span class="kw">`</span><span class="ex">pkg-config</span> --cflags gtk4<span class="kw">`</span> <span class="va">$1</span>.c <span class="kw">`</span><span class="ex">pkg-config</span> --libs gtk4<span class="kw">`</span></span></code></pre></div>
|
||||
<p>Save this one liner to a file <code>comp</code>. Then, copy it to <code>$HOME/bin</code> and give it executable permission.</p>
|
||||
<div class="sourceCode" id="cb13"><pre
|
||||
class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gcc</span> <span class="at">-Wl,--export-dynamic</span> <span class="kw">`</span><span class="ex">pkg-config</span> <span class="at">--cflags</span> gtk4<span class="kw">`</span> <span class="va">$1</span>.c <span class="kw">`</span><span class="ex">pkg-config</span> <span class="at">--libs</span> gtk4<span class="kw">`</span></span></code></pre></div>
|
||||
<p>Save this one liner to a file <code>comp</code>. Then, copy it to
|
||||
<code>$HOME/bin</code> and give it executable permission.</p>
|
||||
<pre><code>$ cp comp $HOME/bin/comp
|
||||
$ chmod +x $HOME/bin/comp</code></pre>
|
||||
<p>You can compile <code>list3.c</code> and execute it, like this:</p>
|
||||
<pre><code>$ comp list3
|
||||
$ ./a.out</code></pre>
|
||||
<figure>
|
||||
<img src="image/list3.png" alt="" /><figcaption>screenshot list3</figcaption>
|
||||
<img src="image/list3.png" alt="screenshot list3" />
|
||||
<figcaption aria-hidden="true">screenshot list3</figcaption>
|
||||
</figure>
|
||||
</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>
|
||||
|
|
818
docs/sec27.html
818
docs/sec27.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;}
|
||||
|
@ -111,197 +111,265 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 id="gtkgridview-and-activate-signal">GtkGridView and activate signal</h1>
|
||||
<p>GtkGridView is similar to GtkListView. It displays a GListModel as a grid, which is like a square tessellation.</p>
|
||||
<h1 id="gtkgridview-and-activate-signal">GtkGridView and activate
|
||||
signal</h1>
|
||||
<p>GtkGridView is similar to GtkListView. It displays a GListModel as a
|
||||
grid, which is like a square tessellation.</p>
|
||||
<figure>
|
||||
<img src="image/list4.png" alt="" /><figcaption>Grid</figcaption>
|
||||
<img src="image/list4.png" alt="Grid" />
|
||||
<figcaption aria-hidden="true">Grid</figcaption>
|
||||
</figure>
|
||||
<p>This is often seen when you use a file browser like nautilus.</p>
|
||||
<p>In this section, let’s make a very simple file browser <code>list4</code>. It just shows the files in the current directory. And a user can choose list or grid by clicking on buttons in the tool bar. Each item in the list or grid has an icon and a filename. In addition, <code>list4</code> provides the way to open the <code>tfe</code> text editor to show a text file. A user can do that by double clicking on an item or pressing enter key when an item is selected.</p>
|
||||
<p>In this section, let’s make a very simple file browser
|
||||
<code>list4</code>. It just shows the files in the current directory.
|
||||
And a user can choose list or grid by clicking on buttons in the tool
|
||||
bar. Each item in the list or grid has an icon and a filename. In
|
||||
addition, <code>list4</code> provides the way to open the
|
||||
<code>tfe</code> text editor to show a text file. A user can do that by
|
||||
double clicking on an item or pressing enter key when an item is
|
||||
selected.</p>
|
||||
<h2 id="gtkdirectorylist">GtkDirectoryList</h2>
|
||||
<p>GtkDirectoryList implements GListModel and it contains information of files in a certain directory. The items of the list are GFileInfo objects.</p>
|
||||
<p>In the <code>list4</code> source files, GtkDirectoryList is described in a ui file and built by GtkBuilder. The GtkDirectoryList instance is assigned to the “model” property of a GtkSingleSelection instance. And the GtkSingleSelection instance is assigned to the “model” property of a GListView or GGridView instance.</p>
|
||||
<p>GtkDirectoryList implements GListModel and it contains information of
|
||||
files in a certain directory. The items of the list are GFileInfo
|
||||
objects.</p>
|
||||
<p>In the <code>list4</code> source files, GtkDirectoryList is described
|
||||
in a ui file and built by GtkBuilder. The GtkDirectoryList instance is
|
||||
assigned to the “model” property of a GtkSingleSelection instance. And
|
||||
the GtkSingleSelection instance is assigned to the “model” property of a
|
||||
GListView or GGridView instance.</p>
|
||||
<pre><code>GtkListView (model property) => GtkSingleSelection (model property) => GtkDirectoryList
|
||||
GtkGridView (model property) => GtkSingleSelection (model property) => GtkDirectoryList</code></pre>
|
||||
<figure>
|
||||
<img src="image/directorylist.png" alt="" /><figcaption>DirectoryList</figcaption>
|
||||
<img src="image/directorylist.png" alt="DirectoryList" />
|
||||
<figcaption aria-hidden="true">DirectoryList</figcaption>
|
||||
</figure>
|
||||
<p>The following is the part of the ui file <code>list4.ui</code>. It defines GtkListView, GtkSingleSelection and GtkDirectoryList. It also defines GtkGridView and GtkSingleSelection.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkListView"</span><span class="ot"> id=</span><span class="st">"list"</span><span class="kw">></span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"model"</span><span class="kw">></span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkSingleSelection"</span><span class="ot"> id=</span><span class="st">"singleselection"</span><span class="kw">></span></span>
|
||||
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"model"</span><span class="kw">></span></span>
|
||||
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkDirectoryList"</span><span class="ot"> id=</span><span class="st">"directorylist"</span><span class="kw">></span></span>
|
||||
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"attributes"</span><span class="kw">></span>standard::name,standard::icon,standard::content-type<span class="kw"></property></span></span>
|
||||
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a><span class="kw"></object></span></span>
|
||||
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a><span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkGridView"</span><span class="ot"> id=</span><span class="st">"grid"</span><span class="kw">></span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"model"</span><span class="kw">></span>singleselection<span class="kw"></property></span></span>
|
||||
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true"></a><span class="kw"></object></span></span></code></pre></div>
|
||||
<p>GtkDirectoryList has an “attributes” property. It is attributes of GFileInfo such as “standard::name”, “standard::icon” and “standard::content-type”.</p>
|
||||
<p>The following is the part of the ui file <code>list4.ui</code>. It
|
||||
defines GtkListView, GtkSingleSelection and GtkDirectoryList. It also
|
||||
defines GtkGridView and GtkSingleSelection.</p>
|
||||
<div class="sourceCode" id="cb2"><pre
|
||||
class="sourceCode xml"><code class="sourceCode xml"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkListView"</span><span class="ot"> id=</span><span class="st">"list"</span>></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"model"</span>></span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkSingleSelection"</span><span class="ot"> id=</span><span class="st">"singleselection"</span>></span>
|
||||
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"model"</span>></span>
|
||||
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkDirectoryList"</span><span class="ot"> id=</span><span class="st">"directorylist"</span>></span>
|
||||
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"attributes"</span>>standard::name,standard::icon,standard::content-type</<span class="kw">property</span>></span>
|
||||
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a></<span class="kw">object</span>></span>
|
||||
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkGridView"</span><span class="ot"> id=</span><span class="st">"grid"</span>></span>
|
||||
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"model"</span>>singleselection</<span class="kw">property</span>></span>
|
||||
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a></<span class="kw">object</span>></span></code></pre></div>
|
||||
<p>GtkDirectoryList has an “attributes” property. It is attributes of
|
||||
GFileInfo such as “standard::name”, “standard::icon” and
|
||||
“standard::content-type”.</p>
|
||||
<ul>
|
||||
<li>standard::name is a filename.</li>
|
||||
<li>standard::icon is an icon of the file. It is a GIcon object.</li>
|
||||
<li>standard::content-type is a content-type. Content-type is the same as mime type for the internet technology. For example, “text/plain” is a text file, “text/x-csrc” is a C source code and so on. (“text/x-csrc”is not registered to IANA media types. Such “x-” subtype is not a standard mime type.) Content type is also used by the desktop system.</li>
|
||||
<li>standard::content-type is a content-type. Content-type is the same
|
||||
as mime type for the internet technology. For example, “text/plain” is a
|
||||
text file, “text/x-csrc” is a C source code and so on. (“text/x-csrc”is
|
||||
not registered to IANA media types. Such “x-” subtype is not a standard
|
||||
mime type.) Content type is also used by the desktop system.</li>
|
||||
</ul>
|
||||
<p>GtkGridView has the same structure as GtkListView. But it is enough to specify its model property to <code>singleselection</code> which is the identification of the GtkSingleSelection. Therefore the description for GtkGridView is very short.</p>
|
||||
<p>GtkGridView has the same structure as GtkListView. But it is enough
|
||||
to specify its model property to <code>singleselection</code> which is
|
||||
the identification of the GtkSingleSelection. Therefore the description
|
||||
for GtkGridView is very short.</p>
|
||||
<h2 id="ui-file-of-the-window">Ui file of the window</h2>
|
||||
<p>Look at the screenshot of <code>list4</code> at the top of this section. The widgets are built with the following ui file.</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw"><?xml</span> version="1.0" encoding="UTF-8"<span class="kw">?></span></span>
|
||||
<span id="cb3-2"><a href="#cb3-2"></a><span class="kw"><interface></span></span>
|
||||
<span id="cb3-3"><a href="#cb3-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="cb3-4"><a href="#cb3-4"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"title"</span><span class="kw">></span>file list<span class="kw"></property></span></span>
|
||||
<span id="cb3-5"><a href="#cb3-5"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"default-width"</span><span class="kw">></span>600<span class="kw"></property></span></span>
|
||||
<span id="cb3-6"><a href="#cb3-6"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"default-height"</span><span class="kw">></span>400<span class="kw"></property></span></span>
|
||||
<span id="cb3-7"><a href="#cb3-7"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-8"><a href="#cb3-8"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxv"</span><span class="kw">></span></span>
|
||||
<span id="cb3-9"><a href="#cb3-9"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"orientation"</span><span class="kw">></span>GTK_ORIENTATION_VERTICAL<span class="kw"></property></span></span>
|
||||
<span id="cb3-10"><a href="#cb3-10"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-11"><a href="#cb3-11"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxh"</span><span class="kw">></span></span>
|
||||
<span id="cb3-12"><a href="#cb3-12"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"orientation"</span><span class="kw">></span>GTK_ORIENTATION_HORIZONTAL<span class="kw"></property></span></span>
|
||||
<span id="cb3-13"><a href="#cb3-13"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-14"><a href="#cb3-14"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy1"</span><span class="kw">></span></span>
|
||||
<span id="cb3-15"><a href="#cb3-15"></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="cb3-16"><a href="#cb3-16"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-17"><a href="#cb3-17"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-18"><a href="#cb3-18"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-19"><a href="#cb3-19"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btnlist"</span><span class="kw">></span></span>
|
||||
<span id="cb3-20"><a href="#cb3-20"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"name"</span><span class="kw">></span>btnlist<span class="kw"></property></span></span>
|
||||
<span id="cb3-21"><a href="#cb3-21"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"action-name"</span><span class="kw">></span>win.view<span class="kw"></property></span></span>
|
||||
<span id="cb3-22"><a href="#cb3-22"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"action-target"</span><span class="kw">></span><span class="dv">&apos;</span>list<span class="dv">&apos;</span><span class="kw"></property></span></span>
|
||||
<span id="cb3-23"><a href="#cb3-23"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-24"><a href="#cb3-24"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkImage"</span><span class="kw">></span></span>
|
||||
<span id="cb3-25"><a href="#cb3-25"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"resource"</span><span class="kw">></span>/com/github/ToshioCP/list4/list.png<span class="kw"></property></span></span>
|
||||
<span id="cb3-26"><a href="#cb3-26"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-27"><a href="#cb3-27"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-28"><a href="#cb3-28"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-29"><a href="#cb3-29"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-30"><a href="#cb3-30"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-31"><a href="#cb3-31"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btngrid"</span><span class="kw">></span></span>
|
||||
<span id="cb3-32"><a href="#cb3-32"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"name"</span><span class="kw">></span>btngrid<span class="kw"></property></span></span>
|
||||
<span id="cb3-33"><a href="#cb3-33"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"action-name"</span><span class="kw">></span>win.view<span class="kw"></property></span></span>
|
||||
<span id="cb3-34"><a href="#cb3-34"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"action-target"</span><span class="kw">></span><span class="dv">&apos;</span>grid<span class="dv">&apos;</span><span class="kw"></property></span></span>
|
||||
<span id="cb3-35"><a href="#cb3-35"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-36"><a href="#cb3-36"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkImage"</span><span class="kw">></span></span>
|
||||
<span id="cb3-37"><a href="#cb3-37"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"resource"</span><span class="kw">></span>/com/github/ToshioCP/list4/grid.png<span class="kw"></property></span></span>
|
||||
<span id="cb3-38"><a href="#cb3-38"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-39"><a href="#cb3-39"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-40"><a href="#cb3-40"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-41"><a href="#cb3-41"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-42"><a href="#cb3-42"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-43"><a href="#cb3-43"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy2"</span><span class="kw">></span></span>
|
||||
<span id="cb3-44"><a href="#cb3-44"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"width-chars"</span><span class="kw">></span>10<span class="kw"></property></span></span>
|
||||
<span id="cb3-45"><a href="#cb3-45"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-46"><a href="#cb3-46"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-47"><a href="#cb3-47"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-48"><a href="#cb3-48"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-49"><a href="#cb3-49"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb3-50"><a href="#cb3-50"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkScrolledWindow"</span><span class="ot"> id=</span><span class="st">"scr"</span><span class="kw">></span></span>
|
||||
<span id="cb3-51"><a href="#cb3-51"></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="cb3-52"><a href="#cb3-52"></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="cb3-53"><a href="#cb3-53"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-54"><a href="#cb3-54"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-55"><a href="#cb3-55"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-56"><a href="#cb3-56"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb3-57"><a href="#cb3-57"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-58"><a href="#cb3-58"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkListView"</span><span class="ot"> id=</span><span class="st">"list"</span><span class="kw">></span></span>
|
||||
<span id="cb3-59"><a href="#cb3-59"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"model"</span><span class="kw">></span></span>
|
||||
<span id="cb3-60"><a href="#cb3-60"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkSingleSelection"</span><span class="ot"> id=</span><span class="st">"singleselection"</span><span class="kw">></span></span>
|
||||
<span id="cb3-61"><a href="#cb3-61"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"model"</span><span class="kw">></span></span>
|
||||
<span id="cb3-62"><a href="#cb3-62"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkDirectoryList"</span><span class="ot"> id=</span><span class="st">"directorylist"</span><span class="kw">></span></span>
|
||||
<span id="cb3-63"><a href="#cb3-63"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"attributes"</span><span class="kw">></span>standard::name,standard::icon,standard::content-type<span class="kw"></property></span></span>
|
||||
<span id="cb3-64"><a href="#cb3-64"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-65"><a href="#cb3-65"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb3-66"><a href="#cb3-66"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-67"><a href="#cb3-67"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb3-68"><a href="#cb3-68"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-69"><a href="#cb3-69"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkGridView"</span><span class="ot"> id=</span><span class="st">"grid"</span><span class="kw">></span></span>
|
||||
<span id="cb3-70"><a href="#cb3-70"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"model"</span><span class="kw">></span>singleselection<span class="kw"></property></span></span>
|
||||
<span id="cb3-71"><a href="#cb3-71"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb3-72"><a href="#cb3-72"></a><span class="kw"></interface></span></span></code></pre></div>
|
||||
<p>The file consists of two parts. The first part begins at the third line and ends at the 57th line. This part is the widgets from the top level window to the scrolled window. It also includes two buttons. The second part begins at the 58th line and ends at the 71st line. This is the part of GtkListView and GtkGridView. They are described in the previous section.</p>
|
||||
<p>Look at the screenshot of <code>list4</code> at the top of this
|
||||
section. The widgets are built with the following ui file.</p>
|
||||
<div class="sourceCode" id="cb3"><pre
|
||||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb3-1"><a href="#cb3-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="cb3-2"><a href="#cb3-2"></a><<span class="kw">interface</span>></span>
|
||||
<span id="cb3-3"><a href="#cb3-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="cb3-4"><a href="#cb3-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"title"</span>>file list</<span class="kw">property</span>></span>
|
||||
<span id="cb3-5"><a href="#cb3-5"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-width"</span>>600</<span class="kw">property</span>></span>
|
||||
<span id="cb3-6"><a href="#cb3-6"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"default-height"</span>>400</<span class="kw">property</span>></span>
|
||||
<span id="cb3-7"><a href="#cb3-7"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-8"><a href="#cb3-8"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxv"</span>></span>
|
||||
<span id="cb3-9"><a href="#cb3-9"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_VERTICAL</<span class="kw">property</span>></span>
|
||||
<span id="cb3-10"><a href="#cb3-10"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-11"><a href="#cb3-11"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="ot"> id=</span><span class="st">"boxh"</span>></span>
|
||||
<span id="cb3-12"><a href="#cb3-12"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_HORIZONTAL</<span class="kw">property</span>></span>
|
||||
<span id="cb3-13"><a href="#cb3-13"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-14"><a href="#cb3-14"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy1"</span>></span>
|
||||
<span id="cb3-15"><a href="#cb3-15"></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="cb3-16"><a href="#cb3-16"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-17"><a href="#cb3-17"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-18"><a href="#cb3-18"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-19"><a href="#cb3-19"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btnlist"</span>></span>
|
||||
<span id="cb3-20"><a href="#cb3-20"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"name"</span>>btnlist</<span class="kw">property</span>></span>
|
||||
<span id="cb3-21"><a href="#cb3-21"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"action-name"</span>>win.view</<span class="kw">property</span>></span>
|
||||
<span id="cb3-22"><a href="#cb3-22"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"action-target"</span>><span class="dv">&apos;</span>list<span class="dv">&apos;</span></<span class="kw">property</span>></span>
|
||||
<span id="cb3-23"><a href="#cb3-23"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-24"><a href="#cb3-24"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkImage"</span>></span>
|
||||
<span id="cb3-25"><a href="#cb3-25"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"resource"</span>>/com/github/ToshioCP/list4/list.png</<span class="kw">property</span>></span>
|
||||
<span id="cb3-26"><a href="#cb3-26"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-27"><a href="#cb3-27"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-28"><a href="#cb3-28"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-29"><a href="#cb3-29"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-30"><a href="#cb3-30"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-31"><a href="#cb3-31"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkButton"</span><span class="ot"> id=</span><span class="st">"btngrid"</span>></span>
|
||||
<span id="cb3-32"><a href="#cb3-32"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"name"</span>>btngrid</<span class="kw">property</span>></span>
|
||||
<span id="cb3-33"><a href="#cb3-33"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"action-name"</span>>win.view</<span class="kw">property</span>></span>
|
||||
<span id="cb3-34"><a href="#cb3-34"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"action-target"</span>><span class="dv">&apos;</span>grid<span class="dv">&apos;</span></<span class="kw">property</span>></span>
|
||||
<span id="cb3-35"><a href="#cb3-35"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-36"><a href="#cb3-36"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkImage"</span>></span>
|
||||
<span id="cb3-37"><a href="#cb3-37"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"resource"</span>>/com/github/ToshioCP/list4/grid.png</<span class="kw">property</span>></span>
|
||||
<span id="cb3-38"><a href="#cb3-38"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-39"><a href="#cb3-39"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-40"><a href="#cb3-40"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-41"><a href="#cb3-41"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-42"><a href="#cb3-42"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-43"><a href="#cb3-43"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="ot"> id=</span><span class="st">"dmy2"</span>></span>
|
||||
<span id="cb3-44"><a href="#cb3-44"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"width-chars"</span>>10</<span class="kw">property</span>></span>
|
||||
<span id="cb3-45"><a href="#cb3-45"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-46"><a href="#cb3-46"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-47"><a href="#cb3-47"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-48"><a href="#cb3-48"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-49"><a href="#cb3-49"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb3-50"><a href="#cb3-50"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkScrolledWindow"</span><span class="ot"> id=</span><span class="st">"scr"</span>></span>
|
||||
<span id="cb3-51"><a href="#cb3-51"></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="cb3-52"><a href="#cb3-52"></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="cb3-53"><a href="#cb3-53"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-54"><a href="#cb3-54"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-55"><a href="#cb3-55"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-56"><a href="#cb3-56"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb3-57"><a href="#cb3-57"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-58"><a href="#cb3-58"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkListView"</span><span class="ot"> id=</span><span class="st">"list"</span>></span>
|
||||
<span id="cb3-59"><a href="#cb3-59"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"model"</span>></span>
|
||||
<span id="cb3-60"><a href="#cb3-60"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkSingleSelection"</span><span class="ot"> id=</span><span class="st">"singleselection"</span>></span>
|
||||
<span id="cb3-61"><a href="#cb3-61"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"model"</span>></span>
|
||||
<span id="cb3-62"><a href="#cb3-62"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkDirectoryList"</span><span class="ot"> id=</span><span class="st">"directorylist"</span>></span>
|
||||
<span id="cb3-63"><a href="#cb3-63"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"attributes"</span>>standard::name,standard::icon,standard::content-type</<span class="kw">property</span>></span>
|
||||
<span id="cb3-64"><a href="#cb3-64"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-65"><a href="#cb3-65"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb3-66"><a href="#cb3-66"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-67"><a href="#cb3-67"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb3-68"><a href="#cb3-68"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-69"><a href="#cb3-69"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkGridView"</span><span class="ot"> id=</span><span class="st">"grid"</span>></span>
|
||||
<span id="cb3-70"><a href="#cb3-70"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"model"</span>>singleselection</<span class="kw">property</span>></span>
|
||||
<span id="cb3-71"><a href="#cb3-71"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb3-72"><a href="#cb3-72"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||
<p>The file consists of two parts. The first part begins at the third
|
||||
line and ends at the 57th line. This part is the widgets from the top
|
||||
level window to the scrolled window. It also includes two buttons. The
|
||||
second part begins at the 58th line and ends at the 71st line. This is
|
||||
the part of GtkListView and GtkGridView. They are described in the
|
||||
previous section.</p>
|
||||
<ul>
|
||||
<li>13-17, 42-46: Two labels are dummy labels. They just work as a space to put the two buttons at the appropriate position.</li>
|
||||
<li>19-41: GtkButton <code>btnlist</code> and <code>btngrid</code>. These two buttons work as selection buttons to switch from list to grid and vice versa. These two buttons are connected to a stateful action <code>win.view</code>. This action is stateful and has a parameter. Such action consists of prefix, action name and parameter. The prefix of the action is <code>win</code>, which means the action belongs to the top level window. So, a prefix gives the scope of the action. The action name is <code>view</code>. The parameters are <code>list</code> or <code>grid</code>, which show the state of the action. A parameter is also called a target, because it is a target to which the buttons are clicked on to change the action state. We often write the detailed action like “win.view::list” or “win.view::grid”.</li>
|
||||
<li>21-22: The properties “action-name” and “action-target” belong to GtkActionable interface. GtkButton implements GtkActionable. The action name is “win.view” and the target is “list”. Generally, a target is GVariant, which can be string, integer, float and so on. You need to use GVariant text format to write GVariant value in ui files. If the type of the GVariant value is string, then the value with GVariant text format is bounded by single quotes or double quotes. Because ui file is xml format text, single quote cannot be written without escape. Its escape sequence is &apos;. Therefore, the target ‘list’ is written as &apos;list&apos;. Because the button is connected to the action, “clicked” signal handler isn’t needed.</li>
|
||||
<li>23-27: The child widget of the button is GtkImage. GtkImage has a “resource” property. It is a GResource and GtkImage reads an image data from the resource and sets the image. This resource is built from 24x24-sized png image data, which is an original icon.</li>
|
||||
<li>50-53: GtkScrolledWindow. Its child widget will be GtkListView or GtkGridView.</li>
|
||||
<li>13-17, 42-46: Two labels are dummy labels. They just work as a space
|
||||
to put the two buttons at the appropriate position.</li>
|
||||
<li>19-41: GtkButton <code>btnlist</code> and <code>btngrid</code>.
|
||||
These two buttons work as selection buttons to switch from list to grid
|
||||
and vice versa. These two buttons are connected to a stateful action
|
||||
<code>win.view</code>. This action is stateful and has a parameter. Such
|
||||
action consists of prefix, action name and parameter. The prefix of the
|
||||
action is <code>win</code>, which means the action belongs to the top
|
||||
level window. So, a prefix gives the scope of the action. The action
|
||||
name is <code>view</code>. The parameters are <code>list</code> or
|
||||
<code>grid</code>, which show the state of the action. A parameter is
|
||||
also called a target, because it is a target to which the buttons are
|
||||
clicked on to change the action state. We often write the detailed
|
||||
action like “win.view::list” or “win.view::grid”.</li>
|
||||
<li>21-22: The properties “action-name” and “action-target” belong to
|
||||
GtkActionable interface. GtkButton implements GtkActionable. The action
|
||||
name is “win.view” and the target is “list”. Generally, a target is
|
||||
GVariant, which can be string, integer, float and so on. You need to use
|
||||
GVariant text format to write GVariant value in ui files. If the type of
|
||||
the GVariant value is string, then the value with GVariant text format
|
||||
is bounded by single quotes or double quotes. Because ui file is xml
|
||||
format text, single quote cannot be written without escape. Its escape
|
||||
sequence is &apos;. Therefore, the target ‘list’ is written as
|
||||
&apos;list&apos;. Because the button is connected to the action,
|
||||
“clicked” signal handler isn’t needed.</li>
|
||||
<li>23-27: The child widget of the button is GtkImage. GtkImage has a
|
||||
“resource” property. It is a GResource and GtkImage reads an image data
|
||||
from the resource and sets the image. This resource is built from
|
||||
24x24-sized png image data, which is an original icon.</li>
|
||||
<li>50-53: GtkScrolledWindow. Its child widget will be GtkListView or
|
||||
GtkGridView.</li>
|
||||
</ul>
|
||||
<p>The action <code>view</code> is created, connected to the “activate” signal handler and inserted to the window (action map) as follows.</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"></a> act_view = g_simple_action_new_stateful (<span class="st">"view"</span>, g_variant_type_new(<span class="st">"s"</span>), g_variant_new_string (<span class="st">"list"</span>));</span>
|
||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a> g_signal_connect (act_view, <span class="st">"activate"</span>, G_CALLBACK (view_activated), scr); <span class="co">/* scr is the GtkScrolledWindow object */</span></span>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a> g_action_map_add_action (G_ACTION_MAP (win), G_ACTION (act_view));</span></code></pre></div>
|
||||
<p>The signal handler <code>view_activated</code> will be explained later.</p>
|
||||
<p>The action <code>view</code> is created, connected to the “activate”
|
||||
signal handler and inserted to the window (action map) as follows.</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> act_view <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">"view"</span><span class="op">,</span> g_variant_type_new<span class="op">(</span><span class="st">"s"</span><span class="op">),</span> g_variant_new_string <span class="op">(</span><span class="st">"list"</span><span class="op">));</span></span>
|
||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> g_signal_connect <span class="op">(</span>act_view<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>view_activated<span class="op">),</span> scr<span class="op">);</span> <span class="co">/* scr is the GtkScrolledWindow object */</span></span>
|
||||
<span id="cb4-3"><a href="#cb4-3" 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_view<span class="op">));</span></span></code></pre></div>
|
||||
<p>The signal handler <code>view_activated</code> will be explained
|
||||
later.</p>
|
||||
<h2 id="factories">Factories</h2>
|
||||
<p>Each view (GtkListView and GtkGridView) has its own factory because its items have different structure of widgets. The factories are GtkBuilderListItemFactory objects. Their ui files are as follows.</p>
|
||||
<p>Each view (GtkListView and GtkGridView) has its own factory because
|
||||
its items have different structure of widgets. The factories are
|
||||
GtkBuilderListItemFactory objects. Their ui files are as follows.</p>
|
||||
<p>factory_list.ui</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"><template</span><span class="ot"> class=</span><span class="st">"GtkListItem"</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">"child"</span><span class="kw">></span></span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="kw">></span></span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"orientation"</span><span class="kw">></span>GTK_ORIENTATION_HORIZONTAL<span class="kw"></property></span></span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"spacing"</span><span class="kw">></span>20<span class="kw"></property></span></span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkImage"</span><span class="kw">></span></span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a> <span class="kw"><binding</span><span class="ot"> name=</span><span class="st">"gicon"</span><span class="kw">></span></span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> <span class="kw"><closure</span><span class="ot"> type=</span><span class="st">"GIcon"</span><span class="ot"> function=</span><span class="st">"get_icon"</span><span class="kw">></span></span>
|
||||
<span id="cb5-12"><a href="#cb5-12"></a> <span class="kw"><lookup</span><span class="ot"> name=</span><span class="st">"item"</span><span class="kw">></span>GtkListItem<span class="kw"></lookup></span></span>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a> <span class="kw"></closure></span></span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a> <span class="kw"></binding></span></span>
|
||||
<span id="cb5-15"><a href="#cb5-15"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb5-16"><a href="#cb5-16"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb5-17"><a href="#cb5-17"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb5-18"><a href="#cb5-18"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="kw">></span></span>
|
||||
<span id="cb5-19"><a href="#cb5-19"></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-20"><a href="#cb5-20"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"xalign"</span><span class="kw">></span>0<span class="kw"></property></span></span>
|
||||
<span id="cb5-21"><a href="#cb5-21"></a> <span class="kw"><binding</span><span class="ot"> name=</span><span class="st">"label"</span><span class="kw">></span></span>
|
||||
<span id="cb5-22"><a href="#cb5-22"></a> <span class="kw"><closure</span><span class="ot"> type=</span><span class="st">"gchararray"</span><span class="ot"> function=</span><span class="st">"get_file_name"</span><span class="kw">></span></span>
|
||||
<span id="cb5-23"><a href="#cb5-23"></a> <span class="kw"><lookup</span><span class="ot"> name=</span><span class="st">"item"</span><span class="kw">></span>GtkListItem<span class="kw"></lookup></span></span>
|
||||
<span id="cb5-24"><a href="#cb5-24"></a> <span class="kw"></closure></span></span>
|
||||
<span id="cb5-25"><a href="#cb5-25"></a> <span class="kw"></binding></span></span>
|
||||
<span id="cb5-26"><a href="#cb5-26"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb5-27"><a href="#cb5-27"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb5-28"><a href="#cb5-28"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb5-29"><a href="#cb5-29"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb5-30"><a href="#cb5-30"></a> <span class="kw"></template></span></span>
|
||||
<span id="cb5-31"><a href="#cb5-31"></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">template</span><span class="ot"> class=</span><span class="st">"GtkListItem"</span>></span>
|
||||
<span id="cb5-4"><a href="#cb5-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"child"</span>></span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span>></span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_HORIZONTAL</<span class="kw">property</span>></span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"spacing"</span>>20</<span class="kw">property</span>></span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkImage"</span>></span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"gicon"</span>></span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> <<span class="kw">closure</span><span class="ot"> type=</span><span class="st">"GIcon"</span><span class="ot"> function=</span><span class="st">"get_icon"</span>></span>
|
||||
<span id="cb5-12"><a href="#cb5-12"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"item"</span>>GtkListItem</<span class="kw">lookup</span>></span>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a> </<span class="kw">closure</span>></span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a> </<span class="kw">binding</span>></span>
|
||||
<span id="cb5-15"><a href="#cb5-15"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb5-16"><a href="#cb5-16"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb5-17"><a href="#cb5-17"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb5-18"><a href="#cb5-18"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
||||
<span id="cb5-19"><a href="#cb5-19"></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-20"><a href="#cb5-20"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"xalign"</span>>0</<span class="kw">property</span>></span>
|
||||
<span id="cb5-21"><a href="#cb5-21"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
||||
<span id="cb5-22"><a href="#cb5-22"></a> <<span class="kw">closure</span><span class="ot"> type=</span><span class="st">"gchararray"</span><span class="ot"> function=</span><span class="st">"get_file_name"</span>></span>
|
||||
<span id="cb5-23"><a href="#cb5-23"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"item"</span>>GtkListItem</<span class="kw">lookup</span>></span>
|
||||
<span id="cb5-24"><a href="#cb5-24"></a> </<span class="kw">closure</span>></span>
|
||||
<span id="cb5-25"><a href="#cb5-25"></a> </<span class="kw">binding</span>></span>
|
||||
<span id="cb5-26"><a href="#cb5-26"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb5-27"><a href="#cb5-27"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb5-28"><a href="#cb5-28"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb5-29"><a href="#cb5-29"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb5-30"><a href="#cb5-30"></a> </<span class="kw">template</span>></span>
|
||||
<span id="cb5-31"><a href="#cb5-31"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||
<p>factory_grid.ui</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"><interface></span></span>
|
||||
<span id="cb6-3"><a href="#cb6-3"></a> <span class="kw"><template</span><span class="ot"> class=</span><span class="st">"GtkListItem"</span><span class="kw">></span></span>
|
||||
<span id="cb6-4"><a href="#cb6-4"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"child"</span><span class="kw">></span></span>
|
||||
<span id="cb6-5"><a href="#cb6-5"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span><span class="kw">></span></span>
|
||||
<span id="cb6-6"><a href="#cb6-6"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"orientation"</span><span class="kw">></span>GTK_ORIENTATION_VERTICAL<span class="kw"></property></span></span>
|
||||
<span id="cb6-7"><a href="#cb6-7"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"spacing"</span><span class="kw">></span>20<span class="kw"></property></span></span>
|
||||
<span id="cb6-8"><a href="#cb6-8"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb6-9"><a href="#cb6-9"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkImage"</span><span class="kw">></span></span>
|
||||
<span id="cb6-10"><a href="#cb6-10"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"icon-size"</span><span class="kw">></span>GTK_ICON_SIZE_LARGE<span class="kw"></property></span></span>
|
||||
<span id="cb6-11"><a href="#cb6-11"></a> <span class="kw"><binding</span><span class="ot"> name=</span><span class="st">"gicon"</span><span class="kw">></span></span>
|
||||
<span id="cb6-12"><a href="#cb6-12"></a> <span class="kw"><closure</span><span class="ot"> type=</span><span class="st">"GIcon"</span><span class="ot"> function=</span><span class="st">"get_icon"</span><span class="kw">></span></span>
|
||||
<span id="cb6-13"><a href="#cb6-13"></a> <span class="kw"><lookup</span><span class="ot"> name=</span><span class="st">"item"</span><span class="kw">></span>GtkListItem<span class="kw"></lookup></span></span>
|
||||
<span id="cb6-14"><a href="#cb6-14"></a> <span class="kw"></closure></span></span>
|
||||
<span id="cb6-15"><a href="#cb6-15"></a> <span class="kw"></binding></span></span>
|
||||
<span id="cb6-16"><a href="#cb6-16"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb6-17"><a href="#cb6-17"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb6-18"><a href="#cb6-18"></a> <span class="kw"><child></span></span>
|
||||
<span id="cb6-19"><a href="#cb6-19"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span><span class="kw">></span></span>
|
||||
<span id="cb6-20"><a href="#cb6-20"></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="cb6-21"><a href="#cb6-21"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"xalign"</span><span class="kw">></span>0.5<span class="kw"></property></span></span>
|
||||
<span id="cb6-22"><a href="#cb6-22"></a> <span class="kw"><binding</span><span class="ot"> name=</span><span class="st">"label"</span><span class="kw">></span></span>
|
||||
<span id="cb6-23"><a href="#cb6-23"></a> <span class="kw"><closure</span><span class="ot"> type=</span><span class="st">"gchararray"</span><span class="ot"> function=</span><span class="st">"get_file_name"</span><span class="kw">></span></span>
|
||||
<span id="cb6-24"><a href="#cb6-24"></a> <span class="kw"><lookup</span><span class="ot"> name=</span><span class="st">"item"</span><span class="kw">></span>GtkListItem<span class="kw"></lookup></span></span>
|
||||
<span id="cb6-25"><a href="#cb6-25"></a> <span class="kw"></closure></span></span>
|
||||
<span id="cb6-26"><a href="#cb6-26"></a> <span class="kw"></binding></span></span>
|
||||
<span id="cb6-27"><a href="#cb6-27"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb6-28"><a href="#cb6-28"></a> <span class="kw"></child></span></span>
|
||||
<span id="cb6-29"><a href="#cb6-29"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb6-30"><a href="#cb6-30"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb6-31"><a href="#cb6-31"></a> <span class="kw"></template></span></span>
|
||||
<span id="cb6-32"><a href="#cb6-32"></a><span class="kw"></interface></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">interface</span>></span>
|
||||
<span id="cb6-3"><a href="#cb6-3"></a> <<span class="kw">template</span><span class="ot"> class=</span><span class="st">"GtkListItem"</span>></span>
|
||||
<span id="cb6-4"><a href="#cb6-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"child"</span>></span>
|
||||
<span id="cb6-5"><a href="#cb6-5"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span>></span>
|
||||
<span id="cb6-6"><a href="#cb6-6"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_VERTICAL</<span class="kw">property</span>></span>
|
||||
<span id="cb6-7"><a href="#cb6-7"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"spacing"</span>>20</<span class="kw">property</span>></span>
|
||||
<span id="cb6-8"><a href="#cb6-8"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb6-9"><a href="#cb6-9"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkImage"</span>></span>
|
||||
<span id="cb6-10"><a href="#cb6-10"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"icon-size"</span>>GTK_ICON_SIZE_LARGE</<span class="kw">property</span>></span>
|
||||
<span id="cb6-11"><a href="#cb6-11"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"gicon"</span>></span>
|
||||
<span id="cb6-12"><a href="#cb6-12"></a> <<span class="kw">closure</span><span class="ot"> type=</span><span class="st">"GIcon"</span><span class="ot"> function=</span><span class="st">"get_icon"</span>></span>
|
||||
<span id="cb6-13"><a href="#cb6-13"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"item"</span>>GtkListItem</<span class="kw">lookup</span>></span>
|
||||
<span id="cb6-14"><a href="#cb6-14"></a> </<span class="kw">closure</span>></span>
|
||||
<span id="cb6-15"><a href="#cb6-15"></a> </<span class="kw">binding</span>></span>
|
||||
<span id="cb6-16"><a href="#cb6-16"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb6-17"><a href="#cb6-17"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb6-18"><a href="#cb6-18"></a> <<span class="kw">child</span>></span>
|
||||
<span id="cb6-19"><a href="#cb6-19"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
||||
<span id="cb6-20"><a href="#cb6-20"></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="cb6-21"><a href="#cb6-21"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"xalign"</span>>0.5</<span class="kw">property</span>></span>
|
||||
<span id="cb6-22"><a href="#cb6-22"></a> <<span class="kw">binding</span><span class="ot"> name=</span><span class="st">"label"</span>></span>
|
||||
<span id="cb6-23"><a href="#cb6-23"></a> <<span class="kw">closure</span><span class="ot"> type=</span><span class="st">"gchararray"</span><span class="ot"> function=</span><span class="st">"get_file_name"</span>></span>
|
||||
<span id="cb6-24"><a href="#cb6-24"></a> <<span class="kw">lookup</span><span class="ot"> name=</span><span class="st">"item"</span>>GtkListItem</<span class="kw">lookup</span>></span>
|
||||
<span id="cb6-25"><a href="#cb6-25"></a> </<span class="kw">closure</span>></span>
|
||||
<span id="cb6-26"><a href="#cb6-26"></a> </<span class="kw">binding</span>></span>
|
||||
<span id="cb6-27"><a href="#cb6-27"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb6-28"><a href="#cb6-28"></a> </<span class="kw">child</span>></span>
|
||||
<span id="cb6-29"><a href="#cb6-29"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb6-30"><a href="#cb6-30"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb6-31"><a href="#cb6-31"></a> </<span class="kw">template</span>></span>
|
||||
<span id="cb6-32"><a href="#cb6-32"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||||
<p>The two files above are almost same. The difference is:</p>
|
||||
<ul>
|
||||
<li>The orientation of the box</li>
|
||||
|
@ -319,196 +387,266 @@ GtkGridView (model property) => GtkSingleSelection (model property) => Gtk
|
|||
< <property name="xalign">0</property>
|
||||
---
|
||||
> <property name="xalign">0.5</property></code></pre>
|
||||
<p>Each view item has two properties, “gicon” property of GtkImage and “label” property of GtkLabel. Because GFileInfo doesn’t have properties correspond to icon or filename, the factory uses closure tag to bind “gicon” and “label” properties to GFileInfo information. A function <code>get_icon</code> gets GIcon the GFileInfo object has. And a function <code>get_file_name</code> gets a filename the GFileInfo object has.</p>
|
||||
<div class="sourceCode" id="cb8"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a>GIcon *</span>
|
||||
<span id="cb8-2"><a href="#cb8-2"></a>get_icon (GtkListItem *item, GFileInfo *info) {</span>
|
||||
<span id="cb8-3"><a href="#cb8-3"></a> GIcon *icon;</span>
|
||||
<p>Each view item has two properties, “gicon” property of GtkImage and
|
||||
“label” property of GtkLabel. Because GFileInfo doesn’t have properties
|
||||
correspond to icon or filename, the factory uses closure tag to bind
|
||||
“gicon” and “label” properties to GFileInfo information. A function
|
||||
<code>get_icon</code> gets GIcon the GFileInfo object has. And a
|
||||
function <code>get_file_name</code> gets a filename the GFileInfo object
|
||||
has.</p>
|
||||
<div class="sourceCode" id="cb8"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a>GIcon <span class="op">*</span></span>
|
||||
<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> (! G_IS_FILE_INFO (info))</span>
|
||||
<span id="cb8-6"><a href="#cb8-6"></a> <span class="cf">return</span> NULL;</span>
|
||||
<span id="cb8-7"><a href="#cb8-7"></a> <span class="cf">else</span> {</span>
|
||||
<span id="cb8-8"><a href="#cb8-8"></a> icon = g_file_info_get_icon (info);</span>
|
||||
<span id="cb8-9"><a href="#cb8-9"></a> g_object_ref (icon);</span>
|
||||
<span id="cb8-10"><a href="#cb8-10"></a> <span class="cf">return</span> icon;</span>
|
||||
<span id="cb8-11"><a href="#cb8-11"></a> }</span>
|
||||
<span id="cb8-12"><a href="#cb8-12"></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>
|
||||
<span id="cb8-15"><a href="#cb8-15"></a>get_file_name (GtkListItem *item, GFileInfo *info) {</span>
|
||||
<span id="cb8-16"><a href="#cb8-16"></a> <span class="cf">if</span> (! G_IS_FILE_INFO (info))</span>
|
||||
<span id="cb8-17"><a href="#cb8-17"></a> <span class="cf">return</span> NULL;</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 (g_file_info_get_name (info));</span>
|
||||
<span id="cb8-20"><a href="#cb8-20"></a>}</span></code></pre></div>
|
||||
<p>One important thing is view items own the instance or string. It is achieved by <code>g_object_ref</code> to increase the reference count by one, or <code>strdup</code> to create a copy of the string. The object or string will be automatically freed in unbinding process when the view item is recycled.</p>
|
||||
<h2 id="an-activate-signal-handler-of-the-action">An activate signal handler of the action</h2>
|
||||
<p>An activate signal handler <code>view_activate</code> switches the view. It does two things.</p>
|
||||
<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 view items own the instance or string. It is
|
||||
achieved by <code>g_object_ref</code> to increase the reference count by
|
||||
one, or <code>strdup</code> to create a copy of the string. The object
|
||||
or string will be automatically freed in unbinding process when the view
|
||||
item is recycled.</p>
|
||||
<h2 id="an-activate-signal-handler-of-the-action">An activate signal
|
||||
handler of the action</h2>
|
||||
<p>An activate signal handler <code>view_activate</code> switches the
|
||||
view. It does two things.</p>
|
||||
<ul>
|
||||
<li>Changes the child widget of GtkScrolledWindow.</li>
|
||||
<li>Changes the CSS of buttons to show the current state.</li>
|
||||
</ul>
|
||||
<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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb9-2"><a href="#cb9-2"></a>view_activated(GSimpleAction *action, GVariant *parameter, gpointer user_data) {</span>
|
||||
<span id="cb9-3"><a href="#cb9-3"></a> GtkScrolledWindow *scr = GTK_SCROLLED_WINDOW (user_data);</span>
|
||||
<span id="cb9-4"><a href="#cb9-4"></a> <span class="dt">const</span> <span class="dt">char</span> *view = g_variant_get_string (parameter, NULL);</span>
|
||||
<span id="cb9-5"><a href="#cb9-5"></a> <span class="dt">const</span> <span class="dt">char</span> *other;</span>
|
||||
<span id="cb9-6"><a href="#cb9-6"></a> <span class="dt">char</span> *css;</span>
|
||||
<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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb9-2"><a href="#cb9-2"></a>view_activated<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb9-3"><a href="#cb9-3"></a> GtkScrolledWindow <span class="op">*</span>scr <span class="op">=</span> GTK_SCROLLED_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
|
||||
<span id="cb9-4"><a href="#cb9-4"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>view <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="cb9-5"><a href="#cb9-5"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>other<span class="op">;</span></span>
|
||||
<span id="cb9-6"><a href="#cb9-6"></a> <span class="dt">char</span> <span class="op">*</span>css<span class="op">;</span></span>
|
||||
<span id="cb9-7"><a href="#cb9-7"></a></span>
|
||||
<span id="cb9-8"><a href="#cb9-8"></a> <span class="cf">if</span> (strcmp (view, <span class="st">"list"</span>) == <span class="dv">0</span>) {</span>
|
||||
<span id="cb9-9"><a href="#cb9-9"></a> other = <span class="st">"grid"</span>;</span>
|
||||
<span id="cb9-10"><a href="#cb9-10"></a> gtk_scrolled_window_set_child (scr, list);</span>
|
||||
<span id="cb9-11"><a href="#cb9-11"></a> }<span class="cf">else</span> {</span>
|
||||
<span id="cb9-12"><a href="#cb9-12"></a> other = <span class="st">"list"</span>;</span>
|
||||
<span id="cb9-13"><a href="#cb9-13"></a> gtk_scrolled_window_set_child (scr, grid);</span>
|
||||
<span id="cb9-14"><a href="#cb9-14"></a> }</span>
|
||||
<span id="cb9-15"><a href="#cb9-15"></a> css = g_strdup_printf (<span class="st">"button#btn%s {background: silver;} button#btn%s {background: white;}"</span>, view, other);</span>
|
||||
<span id="cb9-16"><a href="#cb9-16"></a> gtk_css_provider_load_from_data (provider, css, -<span class="dv">1</span>);</span>
|
||||
<span id="cb9-17"><a href="#cb9-17"></a> g_free (css);</span>
|
||||
<span id="cb9-18"><a href="#cb9-18"></a> g_action_change_state (G_ACTION (action), parameter);</span>
|
||||
<span id="cb9-19"><a href="#cb9-19"></a>}</span></code></pre></div>
|
||||
<p>The second parameter of this handler is the target of the clicked button. Its type is GVariant.</p>
|
||||
<span id="cb9-8"><a href="#cb9-8"></a> <span class="cf">if</span> <span class="op">(</span>strcmp <span class="op">(</span>view<span class="op">,</span> <span class="st">"list"</span><span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb9-9"><a href="#cb9-9"></a> other <span class="op">=</span> <span class="st">"grid"</span><span class="op">;</span></span>
|
||||
<span id="cb9-10"><a href="#cb9-10"></a> gtk_scrolled_window_set_child <span class="op">(</span>scr<span class="op">,</span> list<span class="op">);</span></span>
|
||||
<span id="cb9-11"><a href="#cb9-11"></a> <span class="op">}</span><span class="cf">else</span> <span class="op">{</span></span>
|
||||
<span id="cb9-12"><a href="#cb9-12"></a> other <span class="op">=</span> <span class="st">"list"</span><span class="op">;</span></span>
|
||||
<span id="cb9-13"><a href="#cb9-13"></a> gtk_scrolled_window_set_child <span class="op">(</span>scr<span class="op">,</span> grid<span class="op">);</span></span>
|
||||
<span id="cb9-14"><a href="#cb9-14"></a> <span class="op">}</span></span>
|
||||
<span id="cb9-15"><a href="#cb9-15"></a> css <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">"button#btn%s {background: silver;} button#btn%s {background: white;}"</span><span class="op">,</span> view<span class="op">,</span> other<span class="op">);</span></span>
|
||||
<span id="cb9-16"><a href="#cb9-16"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> css<span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
||||
<span id="cb9-17"><a href="#cb9-17"></a> g_free <span class="op">(</span>css<span class="op">);</span></span>
|
||||
<span id="cb9-18"><a href="#cb9-18"></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="cb9-19"><a href="#cb9-19"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>The second parameter of this handler is the target of the clicked
|
||||
button. Its type is GVariant.</p>
|
||||
<ul>
|
||||
<li>If <code>btnlist</code> has been clicked, then <code>parameter</code> is a GVariant of the string “list”.</li>
|
||||
<li>If <code>btngrid</code> has been clicked, then <code>parameter</code> is a GVariant of the string “grid”.</li>
|
||||
<li>If <code>btnlist</code> has been clicked, then
|
||||
<code>parameter</code> is a GVariant of the string “list”.</li>
|
||||
<li>If <code>btngrid</code> has been clicked, then
|
||||
<code>parameter</code> is a GVariant of the string “grid”.</li>
|
||||
</ul>
|
||||
<p>The third parameter <code>user_data</code> points GtkScrolledWindow, which is set in the <code>g_signal_connect</code> function.</p>
|
||||
<p>The third parameter <code>user_data</code> points GtkScrolledWindow,
|
||||
which is set in the <code>g_signal_connect</code> function.</p>
|
||||
<ul>
|
||||
<li>4: <code>g_variant_get_string</code> gets the string from the GVariant variable.</li>
|
||||
<li>8-14: Sets the child of <code>scr</code>. The function <code>gtk_scrolled_window_set_child</code> decreases the reference count of the old child by one. And it increases the reference count of the new child by one.</li>
|
||||
<li>15-17: Sets the CSS of the buttons. The background of the clicked button will be silver color and the other button will be white.</li>
|
||||
<li>4: <code>g_variant_get_string</code> gets the string from the
|
||||
GVariant variable.</li>
|
||||
<li>8-14: Sets the child of <code>scr</code>. The function
|
||||
<code>gtk_scrolled_window_set_child</code> decreases the reference count
|
||||
of the old child by one. And it increases the reference count of the new
|
||||
child by one.</li>
|
||||
<li>15-17: Sets the CSS of the buttons. The background of the clicked
|
||||
button will be silver color and the other button will be white.</li>
|
||||
<li>18: Changes the state of the action.</li>
|
||||
</ul>
|
||||
<h2 id="activate-signal-of-gtklistview-and-gtkgridview">Activate signal of GtkListView and GtkGridView</h2>
|
||||
<p>Views (GtkListView and GtkGridView) have an “activate” signal. It is emitted when an item in the view is double clicked or the enter key is pressed. You can do anything you like by connecting the “activate” signal to the handler.</p>
|
||||
<p>The example <code>list4</code> launches <code>tfe</code> text file editor if the item of the list is a text file.</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"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a>list_activate (GtkListView *list, <span class="dt">int</span> position, gpointer user_data) {</span>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a> GFileInfo *info = G_FILE_INFO (g_list_model_get_item (G_LIST_MODEL (gtk_list_view_get_model (list)), position));</span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a> launch_tfe_with_file (info);</span>
|
||||
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a>}</span>
|
||||
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a></span>
|
||||
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a>grid_activate (GtkGridView *grid, <span class="dt">int</span> position, gpointer user_data) {</span>
|
||||
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a> GFileInfo *info = G_FILE_INFO (g_list_model_get_item (G_LIST_MODEL (gtk_grid_view_get_model (grid)), position));</span>
|
||||
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a> launch_tfe_with_file (info);</span>
|
||||
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a>}</span>
|
||||
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a></span>
|
||||
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></a>... ...</span>
|
||||
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true"></a>... ...</span>
|
||||
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true"></a></span>
|
||||
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true"></a> g_signal_connect (GTK_LIST_VIEW (list), <span class="st">"activate"</span>, G_CALLBACK (list_activate), NULL);</span>
|
||||
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true"></a> g_signal_connect (GTK_GRID_VIEW (grid), <span class="st">"activate"</span>, G_CALLBACK (grid_activate), NULL);</span></code></pre></div>
|
||||
<p>The second parameter of the handlers is the position of the item (GFileInfo) of the GListModel. So you can get the item with <code>g_list_model_get_item</code> function.</p>
|
||||
<h2 id="content-type-and-launching-an-application">Content type and launching an application</h2>
|
||||
<p>The function <code>launch_tfe_with_file</code> gets a file from the GFileInfo instance. If the file is a text file, it launches <code>tfe</code> with the file.</p>
|
||||
<p>GFileInfo has information about file type. The file type is like “text/plain”, “text/x-csrc” and so on. It is called content type. Content type can be got with <code>g_file_info_get_content_type</code> function.</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb11-2"><a href="#cb11-2"></a>launch_tfe_with_file (GFileInfo *info) {</span>
|
||||
<span id="cb11-3"><a href="#cb11-3"></a> GError *err = NULL;</span>
|
||||
<span id="cb11-4"><a href="#cb11-4"></a> GFile *file;</span>
|
||||
<span id="cb11-5"><a href="#cb11-5"></a> GList *files = NULL;</span>
|
||||
<span id="cb11-6"><a href="#cb11-6"></a> <span class="dt">const</span> <span class="dt">char</span> *content_type;</span>
|
||||
<span id="cb11-7"><a href="#cb11-7"></a> <span class="dt">const</span> <span class="dt">char</span> *text_type = <span class="st">"text/"</span>;</span>
|
||||
<span id="cb11-8"><a href="#cb11-8"></a> GAppInfo *appinfo;</span>
|
||||
<span id="cb11-9"><a href="#cb11-9"></a> <span class="dt">int</span> i;</span>
|
||||
<h2 id="activate-signal-of-gtklistview-and-gtkgridview">Activate signal
|
||||
of GtkListView and GtkGridView</h2>
|
||||
<p>Views (GtkListView and GtkGridView) have an “activate” signal. It is
|
||||
emitted when an item in the view is double clicked or the enter key is
|
||||
pressed. You can do anything you like by connecting the “activate”
|
||||
signal to the handler.</p>
|
||||
<p>The example <code>list4</code> launches <code>tfe</code> text file
|
||||
editor if the item of the list is a text file.</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">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>list_activate <span class="op">(</span>GtkListView <span class="op">*</span>list<span class="op">,</span> <span class="dt">int</span> position<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> GFileInfo <span class="op">*</span>info <span class="op">=</span> G_FILE_INFO <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>gtk_list_view_get_model <span class="op">(</span>list<span class="op">)),</span> position<span class="op">));</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> launch_tfe_with_file <span class="op">(</span>info<span class="op">);</span></span>
|
||||
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>grid_activate <span class="op">(</span>GtkGridView <span class="op">*</span>grid<span class="op">,</span> <span class="dt">int</span> position<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a> GFileInfo <span class="op">*</span>info <span class="op">=</span> G_FILE_INFO <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>gtk_grid_view_get_model <span class="op">(</span>grid<span class="op">)),</span> position<span class="op">));</span></span>
|
||||
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a> launch_tfe_with_file <span class="op">(</span>info<span class="op">);</span></span>
|
||||
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span></span>
|
||||
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a> g_signal_connect <span class="op">(</span>GTK_LIST_VIEW <span class="op">(</span>list<span class="op">),</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>list_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a> g_signal_connect <span class="op">(</span>GTK_GRID_VIEW <span class="op">(</span>grid<span class="op">),</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>grid_activate<span class="op">),</span> NULL<span class="op">);</span></span></code></pre></div>
|
||||
<p>The second parameter of the handlers is the position of the item
|
||||
(GFileInfo) of the GListModel. So you can get the item with
|
||||
<code>g_list_model_get_item</code> function.</p>
|
||||
<h2 id="content-type-and-launching-an-application">Content type and
|
||||
launching an application</h2>
|
||||
<p>The function <code>launch_tfe_with_file</code> gets a file from the
|
||||
GFileInfo instance. If the file is a text file, it launches
|
||||
<code>tfe</code> with the file.</p>
|
||||
<p>GFileInfo has information about file type. The file type is like
|
||||
“text/plain”, “text/x-csrc” and so on. It is called content type.
|
||||
Content type can be got with <code>g_file_info_get_content_type</code>
|
||||
function.</p>
|
||||
<div class="sourceCode" id="cb11"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb11-2"><a href="#cb11-2"></a>launch_tfe_with_file <span class="op">(</span>GFileInfo <span class="op">*</span>info<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-3"><a href="#cb11-3"></a> GError <span class="op">*</span>err <span class="op">=</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb11-4"><a href="#cb11-4"></a> GFile <span class="op">*</span>file<span class="op">;</span></span>
|
||||
<span id="cb11-5"><a href="#cb11-5"></a> GList <span class="op">*</span>files <span class="op">=</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb11-6"><a href="#cb11-6"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>content_type<span class="op">;</span></span>
|
||||
<span id="cb11-7"><a href="#cb11-7"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>text_type <span class="op">=</span> <span class="st">"text/"</span><span class="op">;</span></span>
|
||||
<span id="cb11-8"><a href="#cb11-8"></a> GAppInfo <span class="op">*</span>appinfo<span class="op">;</span></span>
|
||||
<span id="cb11-9"><a href="#cb11-9"></a> <span class="dt">int</span> i<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="cf">if</span> (! info)</span>
|
||||
<span id="cb11-12"><a href="#cb11-12"></a> <span class="cf">return</span>;</span>
|
||||
<span id="cb11-13"><a href="#cb11-13"></a> content_type = g_file_info_get_content_type (info);</span>
|
||||
<span id="cb11-14"><a href="#cb11-14"></a>g_print (<span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span>, content_type); <span class="co">/* This line can be commented out if unnecessary */</span></span>
|
||||
<span id="cb11-15"><a href="#cb11-15"></a> <span class="cf">if</span> (! content_type)</span>
|
||||
<span id="cb11-16"><a href="#cb11-16"></a> <span class="cf">return</span>;</span>
|
||||
<span id="cb11-17"><a href="#cb11-17"></a> <span class="cf">for</span> (i=<span class="dv">0</span>;i<<span class="dv">5</span>;++i) {</span>
|
||||
<span id="cb11-18"><a href="#cb11-18"></a> <span class="cf">if</span> (content_type[i] != text_type[i])</span>
|
||||
<span id="cb11-19"><a href="#cb11-19"></a> <span class="cf">return</span>;</span>
|
||||
<span id="cb11-20"><a href="#cb11-20"></a> }</span>
|
||||
<span id="cb11-21"><a href="#cb11-21"></a> appinfo = g_app_info_create_from_commandline (<span class="st">"tfe"</span>, <span class="st">"tfe"</span>, G_APP_INFO_CREATE_NONE, &err);</span>
|
||||
<span id="cb11-22"><a href="#cb11-22"></a> <span class="cf">if</span> (err) {</span>
|
||||
<span id="cb11-23"><a href="#cb11-23"></a> g_printerr (<span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span>, err->message);</span>
|
||||
<span id="cb11-24"><a href="#cb11-24"></a> g_error_free (err);</span>
|
||||
<span id="cb11-25"><a href="#cb11-25"></a> <span class="cf">return</span>;</span>
|
||||
<span id="cb11-26"><a href="#cb11-26"></a> }</span>
|
||||
<span id="cb11-27"><a href="#cb11-27"></a> err = NULL;</span>
|
||||
<span id="cb11-28"><a href="#cb11-28"></a> file = g_file_new_for_path (g_file_info_get_name (info));</span>
|
||||
<span id="cb11-29"><a href="#cb11-29"></a> files = g_list_append (files, file);</span>
|
||||
<span id="cb11-30"><a href="#cb11-30"></a> <span class="cf">if</span> (! (g_app_info_launch (appinfo, files, NULL, &err))) {</span>
|
||||
<span id="cb11-31"><a href="#cb11-31"></a> g_printerr (<span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span>, err->message);</span>
|
||||
<span id="cb11-32"><a href="#cb11-32"></a> g_error_free (err);</span>
|
||||
<span id="cb11-33"><a href="#cb11-33"></a> }</span>
|
||||
<span id="cb11-34"><a href="#cb11-34"></a> g_list_free_full (files, g_object_unref);</span>
|
||||
<span id="cb11-35"><a href="#cb11-35"></a> g_object_unref (appinfo);</span>
|
||||
<span id="cb11-36"><a href="#cb11-36"></a>}</span></code></pre></div>
|
||||
<span id="cb11-11"><a href="#cb11-11"></a> <span class="cf">if</span> <span class="op">(!</span> info<span class="op">)</span></span>
|
||||
<span id="cb11-12"><a href="#cb11-12"></a> <span class="cf">return</span><span class="op">;</span></span>
|
||||
<span id="cb11-13"><a href="#cb11-13"></a> content_type <span class="op">=</span> g_file_info_get_content_type <span class="op">(</span>info<span class="op">);</span></span>
|
||||
<span id="cb11-14"><a href="#cb11-14"></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> content_type<span class="op">);</span> <span class="co">/* This line can be commented out if unnecessary */</span></span>
|
||||
<span id="cb11-15"><a href="#cb11-15"></a> <span class="cf">if</span> <span class="op">(!</span> content_type<span class="op">)</span></span>
|
||||
<span id="cb11-16"><a href="#cb11-16"></a> <span class="cf">return</span><span class="op">;</span></span>
|
||||
<span id="cb11-17"><a href="#cb11-17"></a> <span class="cf">for</span> <span class="op">(</span>i<span class="op">=</span><span class="dv">0</span><span class="op">;</span>i<span class="op"><</span><span class="dv">5</span><span class="op">;++</span>i<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-18"><a href="#cb11-18"></a> <span class="cf">if</span> <span class="op">(</span>content_type<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> text_type<span class="op">[</span>i<span class="op">])</span></span>
|
||||
<span id="cb11-19"><a href="#cb11-19"></a> <span class="cf">return</span><span class="op">;</span></span>
|
||||
<span id="cb11-20"><a href="#cb11-20"></a> <span class="op">}</span></span>
|
||||
<span id="cb11-21"><a href="#cb11-21"></a> appinfo <span class="op">=</span> g_app_info_create_from_commandline <span class="op">(</span><span class="st">"tfe"</span><span class="op">,</span> <span class="st">"tfe"</span><span class="op">,</span> G_APP_INFO_CREATE_NONE<span class="op">,</span> <span class="op">&</span>err<span class="op">);</span></span>
|
||||
<span id="cb11-22"><a href="#cb11-22"></a> <span class="cf">if</span> <span class="op">(</span>err<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb11-23"><a href="#cb11-23"></a> g_printerr <span class="op">(</span><span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> err<span class="op">-></span>message<span class="op">);</span></span>
|
||||
<span id="cb11-24"><a href="#cb11-24"></a> g_error_free <span class="op">(</span>err<span class="op">);</span></span>
|
||||
<span id="cb11-25"><a href="#cb11-25"></a> <span class="cf">return</span><span class="op">;</span></span>
|
||||
<span id="cb11-26"><a href="#cb11-26"></a> <span class="op">}</span></span>
|
||||
<span id="cb11-27"><a href="#cb11-27"></a> err <span class="op">=</span> NULL<span class="op">;</span></span>
|
||||
<span id="cb11-28"><a href="#cb11-28"></a> file <span class="op">=</span> g_file_new_for_path <span class="op">(</span>g_file_info_get_name <span class="op">(</span>info<span class="op">));</span></span>
|
||||
<span id="cb11-29"><a href="#cb11-29"></a> files <span class="op">=</span> g_list_append <span class="op">(</span>files<span class="op">,</span> file<span class="op">);</span></span>
|
||||
<span id="cb11-30"><a href="#cb11-30"></a> <span class="cf">if</span> <span class="op">(!</span> <span class="op">(</span>g_app_info_launch <span class="op">(</span>appinfo<span class="op">,</span> files<span class="op">,</span> NULL<span class="op">,</span> <span class="op">&</span>err<span class="op">)))</span> <span class="op">{</span></span>
|
||||
<span id="cb11-31"><a href="#cb11-31"></a> g_printerr <span class="op">(</span><span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> err<span class="op">-></span>message<span class="op">);</span></span>
|
||||
<span id="cb11-32"><a href="#cb11-32"></a> g_error_free <span class="op">(</span>err<span class="op">);</span></span>
|
||||
<span id="cb11-33"><a href="#cb11-33"></a> <span class="op">}</span></span>
|
||||
<span id="cb11-34"><a href="#cb11-34"></a> g_list_free_full <span class="op">(</span>files<span class="op">,</span> g_object_unref<span class="op">);</span></span>
|
||||
<span id="cb11-35"><a href="#cb11-35"></a> g_object_unref <span class="op">(</span>appinfo<span class="op">);</span></span>
|
||||
<span id="cb11-36"><a href="#cb11-36"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>13: Gets the content type of the file from GFileInfo.</li>
|
||||
<li>14: Prints the content type. This is only useful to know a content type of a file. You can delete it if unnecessary.</li>
|
||||
<li>17-20: If the content type doesn’t begin with “text/”, then it returns.</li>
|
||||
<li>21: Creates GAppInfo object of <code>tfe</code> application. GAppInfo is an interface and the variable <code>appinfo</code> points a GDesktopAppInfo instance. GAppInfo is a collection of information of an application.</li>
|
||||
<li>30: Launches the application (<code>tfe</code>) with an argument <code>file</code>. <code>g_app_info_launch</code> has four parameters. The first parameter is GAppInfo object. The second parameter is a list of GFile objects. In this function, only one GFile instance is given to <code>tfe</code>, but you can give more arguments. The third parameter is GAppLaunchContext, but this program gives NULL instead. The last parameter is the pointer to the pointer to a GError.</li>
|
||||
<li>34: <code>g_list_free_full</code> frees the memories used by the list and items.</li>
|
||||
<li>14: Prints the content type. This is only useful to know a content
|
||||
type of a file. You can delete it if unnecessary.</li>
|
||||
<li>17-20: If the content type doesn’t begin with “text/”, then it
|
||||
returns.</li>
|
||||
<li>21: Creates GAppInfo object of <code>tfe</code> application.
|
||||
GAppInfo is an interface and the variable <code>appinfo</code> points a
|
||||
GDesktopAppInfo instance. GAppInfo is a collection of information of an
|
||||
application.</li>
|
||||
<li>30: Launches the application (<code>tfe</code>) with an argument
|
||||
<code>file</code>. <code>g_app_info_launch</code> has four parameters.
|
||||
The first parameter is GAppInfo object. The second parameter is a list
|
||||
of GFile objects. In this function, only one GFile instance is given to
|
||||
<code>tfe</code>, but you can give more arguments. The third parameter
|
||||
is GAppLaunchContext, but this program gives NULL instead. The last
|
||||
parameter is the pointer to the pointer to a GError.</li>
|
||||
<li>34: <code>g_list_free_full</code> frees the memories used by the
|
||||
list and items.</li>
|
||||
</ul>
|
||||
<p>If your distribution supports Gtk4, using <code>g_app_info_launch_default_for_uri</code> is convenient. The function automatically determines the default application from the file and launches it. For example, if the file is text, then it launches gedit with the file. Such functionality comes from desktop.</p>
|
||||
<p>If your distribution supports GTK 4, using
|
||||
<code>g_app_info_launch_default_for_uri</code> is convenient. The
|
||||
function automatically determines the default application from the file
|
||||
and launches it. For example, if the file is text, then it launches
|
||||
gedit with the file. Such functionality comes from desktop.</p>
|
||||
<h2 id="compilation-and-execution">Compilation and execution</h2>
|
||||
<p>The source files are located in src/list4 directory. To compile and execute list4, type as follows.</p>
|
||||
<p>The source files are located in src/list4 directory. To compile and
|
||||
execute list4, type as follows.</p>
|
||||
<pre><code>$ cd list4 # or cd src/list4. It depends your current directory.
|
||||
$ meson _build
|
||||
$ ninja -C _build
|
||||
$ _build/list4</code></pre>
|
||||
<p>Then a file list appears as a list style. Click on a button on the tool bar so that you can change the style to grid or back to list. Double click “list4.c” item, then <code>tfe</code> text editor runs with the argument “list4.c”. The following is the screenshot.</p>
|
||||
<p>Then a file list appears as a list style. Click on a button on the
|
||||
tool bar so that you can change the style to grid or back to list.
|
||||
Double click “list4.c” item, then <code>tfe</code> text editor runs with
|
||||
the argument “list4.c”. The following is the screenshot.</p>
|
||||
<figure>
|
||||
<img src="image/screenshot_list4.png" alt="" /><figcaption>Screenshot</figcaption>
|
||||
<img src="image/screenshot_list4.png" alt="Screenshot" />
|
||||
<figcaption aria-hidden="true">Screenshot</figcaption>
|
||||
</figure>
|
||||
<h2 id="gbytes-property-of-gtkbuilderlistitemfactory">“gbytes” property of GtkBuilderListItemFactory</h2>
|
||||
<p>GtkBuilderListItemFactory has “gbytes” property. The property contains a byte sequence of ui data. If you use this property, you can put the contents of <code>factory_list.ui</code> and <code>factory_grid.ui</code>into <code>list4.ui</code>. The following shows a part of the new ui file (<code>list5.ui</code>).</p>
|
||||
<div class="sourceCode" id="cb13"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkListView"</span><span class="ot"> id=</span><span class="st">"list"</span><span class="kw">></span></span>
|
||||
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"model"</span><span class="kw">></span></span>
|
||||
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkSingleSelection"</span><span class="ot"> id=</span><span class="st">"singleselection"</span><span class="kw">></span></span>
|
||||
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"model"</span><span class="kw">></span></span>
|
||||
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkDirectoryList"</span><span class="ot"> id=</span><span class="st">"directorylist"</span><span class="kw">></span></span>
|
||||
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"attributes"</span><span class="kw">></span>standard::name,standard::icon,standard::content-type<span class="kw"></property></span></span>
|
||||
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"factory"</span><span class="kw">></span></span>
|
||||
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true"></a> <span class="kw"><object</span><span class="ot"> class=</span><span class="st">"GtkBuilderListItemFactory"</span><span class="kw">></span></span>
|
||||
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true"></a> <span class="kw"><property</span><span class="ot"> name=</span><span class="st">"bytes"</span><span class="kw">></span><span class="bn"><![CDATA[</span></span>
|
||||
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true"></a><?xml version="1.0" encoding="UTF-8"?></span>
|
||||
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true"></a><interface></span>
|
||||
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true"></a> <template class="GtkListItem"></span>
|
||||
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true"></a> <property name="child"></span>
|
||||
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true"></a> <object class="GtkBox"></span>
|
||||
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true"></a> <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property></span>
|
||||
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true"></a> <property name="spacing">20</property></span>
|
||||
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true"></a> <child></span>
|
||||
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true"></a> <object class="GtkImage"></span>
|
||||
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true"></a> <binding name="gicon"></span>
|
||||
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true"></a> <closure type="GIcon" function="get_icon"></span>
|
||||
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true"></a> <lookup name="item">GtkListItem</lookup></span>
|
||||
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true"></a> </closure></span>
|
||||
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true"></a> </binding></span>
|
||||
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true"></a> </object></span>
|
||||
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true"></a> </child></span>
|
||||
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true"></a> <child></span>
|
||||
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true"></a> <object class="GtkLabel"></span>
|
||||
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true"></a> <property name="hexpand">TRUE</property></span>
|
||||
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true"></a> <property name="xalign">0</property></span>
|
||||
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true"></a> <binding name="label"></span>
|
||||
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true"></a> <closure type="gchararray" function="get_file_name"></span>
|
||||
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true"></a> <lookup name="item">GtkListItem</lookup></span>
|
||||
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true"></a> </closure></span>
|
||||
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true"></a> </binding></span>
|
||||
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true"></a> </object></span>
|
||||
<span id="cb13-40"><a href="#cb13-40" aria-hidden="true"></a> </child></span>
|
||||
<span id="cb13-41"><a href="#cb13-41" aria-hidden="true"></a> </object></span>
|
||||
<span id="cb13-42"><a href="#cb13-42" aria-hidden="true"></a> </property></span>
|
||||
<span id="cb13-43"><a href="#cb13-43" aria-hidden="true"></a> </template></span>
|
||||
<span id="cb13-44"><a href="#cb13-44" aria-hidden="true"></a></interface></span>
|
||||
<span id="cb13-45"><a href="#cb13-45" aria-hidden="true"></a> <span class="bn">]]></span><span class="kw"></property></span></span>
|
||||
<span id="cb13-46"><a href="#cb13-46" aria-hidden="true"></a> <span class="kw"></object></span></span>
|
||||
<span id="cb13-47"><a href="#cb13-47" aria-hidden="true"></a> <span class="kw"></property></span></span>
|
||||
<span id="cb13-48"><a href="#cb13-48" aria-hidden="true"></a> <span class="kw"></object></span></span></code></pre></div>
|
||||
<p>CDATA section begins with “<[CDATA[" and ends with "]]>”. The contents of CDATA section is recognized as a string. Any character, even if it is a key syntax marker such as ‘<’ or ‘>’, is recognized literally. Therefore, the text between “<[CDATA[" and "]]>” is inserted to “bytes” property as it is.</p>
|
||||
<p>This method decreases the number of ui files. But, the new ui file is a bit complicated especially for the beginners. If you feel some difficulty, it is better for you to separate the ui file.</p>
|
||||
<h2 id="gbytes-property-of-gtkbuilderlistitemfactory">“gbytes” property
|
||||
of GtkBuilderListItemFactory</h2>
|
||||
<p>GtkBuilderListItemFactory has “gbytes” property. The property
|
||||
contains a byte sequence of ui data. If you use this property, you can
|
||||
put the contents of <code>factory_list.ui</code> and
|
||||
<code>factory_grid.ui</code>into <code>list4.ui</code>. The following
|
||||
shows a part of the new ui file (<code>list5.ui</code>).</p>
|
||||
<div class="sourceCode" id="cb13"><pre
|
||||
class="sourceCode xml"><code class="sourceCode xml"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkListView"</span><span class="ot"> id=</span><span class="st">"list"</span>></span>
|
||||
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"model"</span>></span>
|
||||
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkSingleSelection"</span><span class="ot"> id=</span><span class="st">"singleselection"</span>></span>
|
||||
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"model"</span>></span>
|
||||
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkDirectoryList"</span><span class="ot"> id=</span><span class="st">"directorylist"</span>></span>
|
||||
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"attributes"</span>>standard::name,standard::icon,standard::content-type</<span class="kw">property</span>></span>
|
||||
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"factory"</span>></span>
|
||||
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBuilderListItemFactory"</span>></span>
|
||||
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"bytes"</span>><span class="bn"><![CDATA[</span></span>
|
||||
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a><?xml version="1.0" encoding="UTF-8"?></span>
|
||||
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a><interface></span>
|
||||
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a> <template class="GtkListItem"></span>
|
||||
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a> <property name="child"></span>
|
||||
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a> <object class="GtkBox"></span>
|
||||
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a> <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property></span>
|
||||
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a> <property name="spacing">20</property></span>
|
||||
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a> <child></span>
|
||||
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a> <object class="GtkImage"></span>
|
||||
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a> <binding name="gicon"></span>
|
||||
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a> <closure type="GIcon" function="get_icon"></span>
|
||||
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a> <lookup name="item">GtkListItem</lookup></span>
|
||||
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a> </closure></span>
|
||||
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a> </binding></span>
|
||||
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a> </object></span>
|
||||
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a> </child></span>
|
||||
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a> <child></span>
|
||||
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a> <object class="GtkLabel"></span>
|
||||
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a> <property name="hexpand">TRUE</property></span>
|
||||
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a> <property name="xalign">0</property></span>
|
||||
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a> <binding name="label"></span>
|
||||
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a> <closure type="gchararray" function="get_file_name"></span>
|
||||
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a> <lookup name="item">GtkListItem</lookup></span>
|
||||
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a> </closure></span>
|
||||
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a> </binding></span>
|
||||
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a> </object></span>
|
||||
<span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a> </child></span>
|
||||
<span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a> </object></span>
|
||||
<span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a> </property></span>
|
||||
<span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a> </template></span>
|
||||
<span id="cb13-44"><a href="#cb13-44" aria-hidden="true" tabindex="-1"></a></interface></span>
|
||||
<span id="cb13-45"><a href="#cb13-45" aria-hidden="true" tabindex="-1"></a> <span class="bn">]]></span></<span class="kw">property</span>></span>
|
||||
<span id="cb13-46"><a href="#cb13-46" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span>
|
||||
<span id="cb13-47"><a href="#cb13-47" aria-hidden="true" tabindex="-1"></a> </<span class="kw">property</span>></span>
|
||||
<span id="cb13-48"><a href="#cb13-48" aria-hidden="true" tabindex="-1"></a> </<span class="kw">object</span>></span></code></pre></div>
|
||||
<p>CDATA section begins with “<[CDATA[” and ends with ”]]>”. The
|
||||
contents of CDATA section is recognized as a string. Any character, even
|
||||
if it is a key syntax marker such as ‘<’ or ‘>’, is recognized
|
||||
literally. Therefore, the text between “<[CDATA[” and ”]]>” is
|
||||
inserted to “bytes” property as it is.</p>
|
||||
<p>This method decreases the number of ui files. But, the new ui file is
|
||||
a bit complicated especially for the beginners. If you feel some
|
||||
difficulty, it is better for you to separate the ui file.</p>
|
||||
<p>A directory src/list5 includes the ui file above.</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>
|
||||
|
|
276
docs/sec3.html
276
docs/sec3.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;}
|
||||
|
@ -111,108 +111,173 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 id="gtkapplication-and-gtkapplicationwindow">GtkApplication and GtkApplicationWindow</h1>
|
||||
<h1 id="gtkapplication-and-gtkapplicationwindow">GtkApplication and
|
||||
GtkApplicationWindow</h1>
|
||||
<h2 id="gtkapplication">GtkApplication</h2>
|
||||
<h3 id="gtkapplication-and-g_application_run">GtkApplication and g_application_run</h3>
|
||||
<p>Usually people write programming code to make an application. What are applications? Applications are software that runs using libraries, which includes the OS, frameworks and so on. In Gtk4 programming, the GtkApplication is a program (or executable) that runs using Gtk libraries.</p>
|
||||
<h3 id="gtkapplication-and-g_application_run">GtkApplication and
|
||||
g_application_run</h3>
|
||||
<p>Usually people write programming code to make an application. What
|
||||
are applications? Applications are software that runs using libraries,
|
||||
which includes the OS, frameworks and so on. In GTK 4 programming, the
|
||||
GtkApplication is a program (or executable) that runs using Gtk
|
||||
libraries.</p>
|
||||
<p>The basic way to write a GtkApplication is as follows.</p>
|
||||
<ul>
|
||||
<li>Create a GtkApplication instance.</li>
|
||||
<li>Run the application.</li>
|
||||
</ul>
|
||||
<p>That’s all. Very simple. The following is the C code representing the scenario above.</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<p>That’s all. Very simple. The following is the C code representing the
|
||||
scenario above.</p>
|
||||
<div class="sourceCode" id="cb1"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2"></a></span>
|
||||
<span id="cb1-3"><a href="#cb1-3"></a><span class="dt">int</span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb1-5"><a href="#cb1-5"></a> GtkApplication *app;</span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a> <span class="dt">int</span> stat;</span>
|
||||
<span id="cb1-4"><a href="#cb1-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="cb1-5"><a href="#cb1-5"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7"></a></span>
|
||||
<span id="cb1-8"><a href="#cb1-8"></a> app = gtk_application_new (<span class="st">"com.github.ToshioCP.pr1"</span>, G_APPLICATION_FLAGS_NONE);</span>
|
||||
<span id="cb1-9"><a href="#cb1-9"></a> stat =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb1-10"><a href="#cb1-10"></a> g_object_unref (app);</span>
|
||||
<span id="cb1-11"><a href="#cb1-11"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb1-12"><a href="#cb1-12"></a>}</span></code></pre></div>
|
||||
<p>The first line says that this program includes the header files of the Gtk libraries. The function <code>main</code> above is a startup function in C language. The variable <code>app</code> is defined as a pointer to a GtkApplication instance. The function <code>gtk_application_new</code> creates a GtkApplication instance and returns a pointer to the instance. The GtkApplication instance is a C structure data in which the information about the application is stored. The meaning of the arguments will be explained later. The function <code>g_application_run</code> runs an application that the instance defined. (We often say that the function runs <code>app</code>. Actually, <code>app</code> is not an application but a pointer to the instance of the application. However, it is simple and short, and probably no confusion occurs.)</p>
|
||||
<p>To compile this, the following command needs to be run. The string <code>pr1.c</code> is the filename of the C source code above.</p>
|
||||
<span id="cb1-8"><a href="#cb1-8"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span><span class="st">"com.github.ToshioCP.pr1"</span><span class="op">,</span> G_APPLICATION_FLAGS_NONE<span class="op">);</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9"></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="cb1-10"><a href="#cb1-10"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb1-11"><a href="#cb1-11"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb1-12"><a href="#cb1-12"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>The first line says that this program includes the header files of
|
||||
the Gtk libraries. The function <code>main</code> above is a startup
|
||||
function in C language. The variable <code>app</code> is defined as a
|
||||
pointer to a GtkApplication instance. The function
|
||||
<code>gtk_application_new</code> creates a GtkApplication instance and
|
||||
returns a pointer to the instance. The GtkApplication instance is a C
|
||||
structure data in which the information about the application is stored.
|
||||
The meaning of the arguments will be explained later. The function
|
||||
<code>g_application_run</code> runs an application that the instance
|
||||
defined. (We often say that the function runs <code>app</code>.
|
||||
Actually, <code>app</code> is not an application but a pointer to the
|
||||
instance of the application. However, it is simple and short, and
|
||||
probably no confusion occurs.)</p>
|
||||
<p>To compile this, the following command needs to be run. The string
|
||||
<code>pr1.c</code> is the filename of the C source code above.</p>
|
||||
<pre><code>$ gcc `pkg-config --cflags gtk4` pr1.c `pkg-config --libs gtk4`</code></pre>
|
||||
<p>The C compiler gcc generates an executable file, <code>a.out</code>. Let’s run it.</p>
|
||||
<p>The C compiler gcc generates an executable file, <code>a.out</code>.
|
||||
Let’s run it.</p>
|
||||
<pre><code>$ ./a.out
|
||||
|
||||
(a.out:13533): GLib-GIO-WARNING **: 15:30:17.449: Your application does not implement
|
||||
g_application_activate() and has no handlers connected to the "activate" signal.
|
||||
It should do one of these.
|
||||
$</code></pre>
|
||||
<p>Oh, it just produces an error message. This error message means that the GtkApplication object ran, without a doubt. Now, let’s think about what this message means.</p>
|
||||
<p>Oh, it just produces an error message. This error message means that
|
||||
the GtkApplication object ran, without a doubt. Now, let’s think about
|
||||
what this message means.</p>
|
||||
<h3 id="signal">signal</h3>
|
||||
<p>The message tells us that:</p>
|
||||
<ol type="1">
|
||||
<li>The application GtkApplication doesn’t implement <code>g_application_activate()</code>,</li>
|
||||
<li>The application GtkApplication doesn’t implement
|
||||
<code>g_application_activate()</code>,</li>
|
||||
<li>It has no handlers connected to the “activate” signal, and</li>
|
||||
<li>You will need to solve at least one of these.</li>
|
||||
</ol>
|
||||
<p>These two causes of the error are related to signals. So, I will explain that to you first.</p>
|
||||
<p>A signal is emitted when something happens. For example, a window is created, a window is destroyed and so on. The signal “activate” is emitted when the application is activated, or started. If the signal is connected to a function, which is called a signal handler or simply handler, then the function is invoked when the signal emits.</p>
|
||||
<p>These two causes of the error are related to signals. So, I will
|
||||
explain that to you first.</p>
|
||||
<p>A signal is emitted when something happens. For example, a window is
|
||||
created, a window is destroyed and so on. The signal “activate” is
|
||||
emitted when the application is activated, or started. If the signal is
|
||||
connected to a function, which is called a signal handler or simply
|
||||
handler, then the function is invoked when the signal emits.</p>
|
||||
<p>The flow is like this:</p>
|
||||
<ol type="1">
|
||||
<li>Something happens.</li>
|
||||
<li>If it’s related to a certain signal, then the signal is emitted.</li>
|
||||
<li>If the signal as been connected to a handler, then the handler is invoked.</li>
|
||||
<li>If it’s related to a certain signal, then the signal is
|
||||
emitted.</li>
|
||||
<li>If the signal as been connected to a handler, then the handler is
|
||||
invoked.</li>
|
||||
</ol>
|
||||
<p>Signals are defined in objects. For example, the “activate” signal belongs to the GApplication object, which is a parent object of GtkApplication object.</p>
|
||||
<p>The GApplication object is a child object of the GObject object. GObject is the top object in the hierarchy of all the objects.</p>
|
||||
<p>Signals are defined in objects. For example, the “activate” signal
|
||||
belongs to the GApplication object, which is a parent object of
|
||||
GtkApplication object.</p>
|
||||
<p>The GApplication object is a child object of the GObject object.
|
||||
GObject is the top object in the hierarchy of all the objects.</p>
|
||||
<pre><code>GObject -- GApplication -- GtkApplication
|
||||
<---parent --->child</code></pre>
|
||||
<p>A child object inherits signals, functions, properties and so on from its parent object. So, GtkApplication also has the “activate” signal.</p>
|
||||
<p>Now we can solve the problem in <code>pr1.c</code>. We need to connect the “activate” signal to a handler. We use a function <code>g_signal_connect</code> which connects a signal to a handler.</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<p>A child object inherits signals, functions, properties and so on from
|
||||
its parent object. So, GtkApplication also has the “activate”
|
||||
signal.</p>
|
||||
<p>Now we can solve the problem in <code>pr1.c</code>. We need to
|
||||
connect the “activate” signal to a handler. We use a function
|
||||
<code>g_signal_connect</code> which connects a signal to a handler.</p>
|
||||
<div class="sourceCode" id="cb5"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb5-2"><a href="#cb5-2"></a></span>
|
||||
<span id="cb5-3"><a href="#cb5-3"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb5-4"><a href="#cb5-4"></a>app_activate (GApplication *app, gpointer *user_data) {</span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a> g_print (<span class="st">"GtkApplication is activated.</span><span class="sc">\n</span><span class="st">"</span>);</span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a>}</span>
|
||||
<span id="cb5-4"><a href="#cb5-4"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">,</span> gpointer <span class="op">*</span>user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a> g_print <span class="op">(</span><span class="st">"GtkApplication is activated.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a><span class="op">}</span></span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a></span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a><span class="dt">int</span></span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a> GtkApplication *app;</span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> <span class="dt">int</span> stat;</span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></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="cb5-10"><a href="#cb5-10"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb5-12"><a href="#cb5-12"></a></span>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a> app = gtk_application_new (<span class="st">"com.github.ToshioCP.pr2"</span>, G_APPLICATION_FLAGS_NONE);</span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</span>
|
||||
<span id="cb5-15"><a href="#cb5-15"></a> stat =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb5-16"><a href="#cb5-16"></a> g_object_unref (app);</span>
|
||||
<span id="cb5-17"><a href="#cb5-17"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb5-18"><a href="#cb5-18"></a>}</span></code></pre></div>
|
||||
<p>First, we define the handler <code>app_activate</code> which simply displays a message. In the function <code>main</code>, we add <code>g_signal_connect</code> before <code>g_application_run</code>. The function <code>g_signal_connect</code> has four arguments.</p>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span><span class="st">"com.github.ToshioCP.pr2"</span><span class="op">,</span> G_APPLICATION_FLAGS_NONE<span class="op">);</span></span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></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="cb5-15"><a href="#cb5-15"></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="cb5-16"><a href="#cb5-16"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb5-17"><a href="#cb5-17"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb5-18"><a href="#cb5-18"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>First, we define the handler <code>app_activate</code> which simply
|
||||
displays a message. In the function <code>main</code>, we add
|
||||
<code>g_signal_connect</code> before <code>g_application_run</code>. The
|
||||
function <code>g_signal_connect</code> has four arguments.</p>
|
||||
<ol type="1">
|
||||
<li>An instance to which the signal belongs.</li>
|
||||
<li>The name of the signal.</li>
|
||||
<li>A handler function (also called callback), which needs to be casted by <code>G_CALLBACK</code>.</li>
|
||||
<li>Data to pass to the handler. If no data is necessary, NULL should be given.</li>
|
||||
<li>A handler function (also called callback), which needs to be casted
|
||||
by <code>G_CALLBACK</code>.</li>
|
||||
<li>Data to pass to the handler. If no data is necessary, NULL should be
|
||||
given.</li>
|
||||
</ol>
|
||||
<p>You can find the description of each signal in the API reference manual. For example, “activate” signal is in GApplication section in <a href="https://docs.gtk.org/gio/signal.Application.activate.html">GIO API Reference</a>. The handler function is described in it.</p>
|
||||
<p>In addition, <code>g_signal_connect</code> is described in <a href="https://docs.gtk.org/gobject/func.signal_connect.html">GObject API Reference</a>. API reference manual is very important. You should see and understand it to write Gtk applications. They are located in <a href="https://docs.gtk.org/">‘GTK Documentation’</a>.</p>
|
||||
<p>Let’s compile the source file above (<code>pr2.c</code>) and run it.</p>
|
||||
<p>You can find the description of each signal in the API reference
|
||||
manual. For example, “activate” signal is in GApplication section in <a
|
||||
href="https://docs.gtk.org/gio/signal.Application.activate.html">GIO API
|
||||
Reference</a>. The handler function is described in it.</p>
|
||||
<p>In addition, <code>g_signal_connect</code> is described in <a
|
||||
href="https://docs.gtk.org/gobject/func.signal_connect.html">GObject API
|
||||
Reference</a>. API reference manual is very important. You should see
|
||||
and understand it to write Gtk applications. They are located in <a
|
||||
href="https://docs.gtk.org/">‘GTK Documentation’</a>.</p>
|
||||
<p>Let’s compile the source file above (<code>pr2.c</code>) and run
|
||||
it.</p>
|
||||
<pre><code>$ gcc `pkg-config --cflags gtk4` pr2.c `pkg-config --libs gtk4`
|
||||
$ ./a.out
|
||||
GtkApplication is activated.
|
||||
$</code></pre>
|
||||
<p>OK, well done. However, you may have noticed that it’s painful to type such a long line to compile. It is a good idea to use shell script to solve this problem. Make a text file which contains the following line.</p>
|
||||
<p>OK, well done. However, you may have noticed that it’s painful to
|
||||
type such a long line to compile. It is a good idea to use shell script
|
||||
to solve this problem. Make a text file which contains the following
|
||||
line.</p>
|
||||
<pre><code>gcc `pkg-config --cflags gtk4` $1.c `pkg-config --libs gtk4`</code></pre>
|
||||
<p>Then, save it under the directory $HOME/bin, which is usually /home/(username)/bin. (If your user name is James, then the directory is /home/james/bin). And turn on the execute bit of the file. If the filename is <code>comp</code>, do like this:</p>
|
||||
<p>Then, save it under the directory $HOME/bin, which is usually
|
||||
/home/(username)/bin. (If your user name is James, then the directory is
|
||||
/home/james/bin). And turn on the execute bit of the file. If the
|
||||
filename is <code>comp</code>, do like this:</p>
|
||||
<pre><code>$ chmod 755 $HOME/bin/comp
|
||||
$ ls -log $HOME/bin
|
||||
... ... ...
|
||||
-rwxr-xr-x 1 62 May 23 08:21 comp
|
||||
... ... ...</code></pre>
|
||||
<p>If this is the first time that you make a $HOME/bin directory and save a file in it, then you need to logout and login again.</p>
|
||||
<p>If this is the first time that you make a $HOME/bin directory and
|
||||
save a file in it, then you need to logout and login again.</p>
|
||||
<pre><code>$ comp pr2
|
||||
$ ./a.out
|
||||
GtkApplication is activated.
|
||||
$</code></pre>
|
||||
<h2 id="gtkwindow-and-gtkapplicationwindow">GtkWindow and GtkApplicationWindow</h2>
|
||||
<h2 id="gtkwindow-and-gtkapplicationwindow">GtkWindow and
|
||||
GtkApplicationWindow</h2>
|
||||
<h3 id="gtkwindow">GtkWindow</h3>
|
||||
<p>A message “GtkApplication is activated.” was printed out in the previous subsection. It was good in terms of a test of GtkApplication. However, it is insufficient because Gtk is a framework for graphical user interface (GUI). Now we go ahead with adding a window into this program. What we need to do is:</p>
|
||||
<p>A message “GtkApplication is activated.” was printed out in the
|
||||
previous subsection. It was good in terms of a test of GtkApplication.
|
||||
However, it is insufficient because Gtk is a framework for graphical
|
||||
user interface (GUI). Now we go ahead with adding a window into this
|
||||
program. What we need to do is:</p>
|
||||
<ol type="1">
|
||||
<li>Create a GtkWindow.</li>
|
||||
<li>Connect it to GtkApplication.</li>
|
||||
|
@ -220,62 +285,97 @@ $</code></pre>
|
|||
</ol>
|
||||
<p>Now rewrite the function <code>app_activate</code>.</p>
|
||||
<h4 id="create-a-gtkwindow">Create a GtkWindow</h4>
|
||||
<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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-2"><a href="#cb10-2"></a>app_activate (GApplication *app, gpointer user_data) {</span>
|
||||
<span id="cb10-3"><a href="#cb10-3"></a> GtkWidget *win;</span>
|
||||
<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="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb10-2"><a href="#cb10-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="cb10-3"><a href="#cb10-3"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
||||
<span id="cb10-4"><a href="#cb10-4"></a></span>
|
||||
<span id="cb10-5"><a href="#cb10-5"></a> win = gtk_window_new ();</span>
|
||||
<span id="cb10-6"><a href="#cb10-6"></a> gtk_window_set_application (GTK_WINDOW (win), GTK_APPLICATION (app));</span>
|
||||
<span id="cb10-7"><a href="#cb10-7"></a> gtk_widget_show (win);</span>
|
||||
<span id="cb10-8"><a href="#cb10-8"></a>}</span></code></pre></div>
|
||||
<p>Widget is an abstract concept that includes all the GUI interfaces such as windows, dialogs, buttons, multi-line text, containers and so on. And GtkWidget is a base object from which all the GUI objects derive.</p>
|
||||
<span id="cb10-5"><a href="#cb10-5"></a> win <span class="op">=</span> gtk_window_new <span class="op">();</span></span>
|
||||
<span id="cb10-6"><a href="#cb10-6"></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="cb10-7"><a href="#cb10-7"></a> gtk_widget_show <span class="op">(</span>win<span class="op">);</span></span>
|
||||
<span id="cb10-8"><a href="#cb10-8"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>Widget is an abstract concept that includes all the GUI interfaces
|
||||
such as windows, dialogs, buttons, multi-line text, containers and so
|
||||
on. And GtkWidget is a base object from which all the GUI objects
|
||||
derive.</p>
|
||||
<pre><code>parent <-----> child
|
||||
GtkWidget -- GtkWindow</code></pre>
|
||||
<p>GtkWindow includes GtkWidget at the top of its object.</p>
|
||||
<figure>
|
||||
<img src="image/window_widget.png" alt="" /><figcaption>GtkWindow and GtkWidget</figcaption>
|
||||
<img src="image/window_widget.png" alt="GtkWindow and GtkWidget" />
|
||||
<figcaption aria-hidden="true">GtkWindow and GtkWidget</figcaption>
|
||||
</figure>
|
||||
<p>The function <code>gtk_window_new</code> is defined as follows.</p>
|
||||
<div class="sourceCode" id="cb12"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a>GtkWidget *</span>
|
||||
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a>gtk_window_new (<span class="dt">void</span>);</span></code></pre></div>
|
||||
<p>By this definition, it returns a pointer to GtkWidget, not GtkWindow. It actually creates a new GtkWindow instance (not GtkWidget) but returns a pointer to GtkWidget. However,the pointer points the GtkWidget and at the same time it also points GtkWindow that contains GtkWidget in it.</p>
|
||||
<p>If you want to use <code>win</code> as a pointer to the GtkWindow, you need to cast it.</p>
|
||||
<div class="sourceCode" id="cb13"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a>(GtkWindow *) win</span></code></pre></div>
|
||||
<p>Or you can use <code>GTK_WINDOW</code> macro that performs a similar function.</p>
|
||||
<div class="sourceCode" id="cb14"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true"></a>GTK_WINDOW (win)</span></code></pre></div>
|
||||
<div class="sourceCode" id="cb12"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>GtkWidget <span class="op">*</span></span>
|
||||
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>gtk_window_new <span class="op">(</span><span class="dt">void</span><span class="op">);</span></span></code></pre></div>
|
||||
<p>By this definition, it returns a pointer to GtkWidget, not GtkWindow.
|
||||
It actually creates a new GtkWindow instance (not GtkWidget) but returns
|
||||
a pointer to GtkWidget. However,the pointer points the GtkWidget and at
|
||||
the same time it also points GtkWindow that contains GtkWidget in
|
||||
it.</p>
|
||||
<p>If you want to use <code>win</code> as a pointer to the GtkWindow,
|
||||
you need to cast it.</p>
|
||||
<div class="sourceCode" id="cb13"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span>GtkWindow <span class="op">*)</span> win</span></code></pre></div>
|
||||
<p>Or you can use <code>GTK_WINDOW</code> macro that performs a similar
|
||||
function.</p>
|
||||
<div class="sourceCode" id="cb14"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>GTK_WINDOW <span class="op">(</span>win<span class="op">)</span></span></code></pre></div>
|
||||
<p>This is a recommended way.</p>
|
||||
<h4 id="connect-it-to-gtkapplication.">Connect it to GtkApplication.</h4>
|
||||
<p>The function <code>gtk_window_set_application</code> is used to connect GtkWindow to GtkApplication.</p>
|
||||
<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true"></a>gtk_window_set_application (GTK_WINDOW (win), GTK_APPLICATION (app));</span></code></pre></div>
|
||||
<p>You need to cast <code>win</code> to GtkWindow and <code>app</code> to GtkApplication. <code>GTK_WINDOW</code> and <code>GTK_APPLICATION</code> macro is appropriate for that.</p>
|
||||
<p>GtkApplication continues to run until the related window is destroyed. If you didn’t connect GtkWindow and GtkApplication, GtkApplication destroys itself immediately. Because no window is connected to GtkApplication, GtkApplication doesn’t need to wait anything. As it destroys itself, the GtkWindow is also destroyed.</p>
|
||||
<h4 id="connect-it-to-gtkapplication.">Connect it to
|
||||
GtkApplication.</h4>
|
||||
<p>The function <code>gtk_window_set_application</code> is used to
|
||||
connect GtkWindow to GtkApplication.</p>
|
||||
<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></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></code></pre></div>
|
||||
<p>You need to cast <code>win</code> to GtkWindow and <code>app</code>
|
||||
to GtkApplication. <code>GTK_WINDOW</code> and
|
||||
<code>GTK_APPLICATION</code> macro is appropriate for that.</p>
|
||||
<p>GtkApplication continues to run until the related window is
|
||||
destroyed. If you didn’t connect GtkWindow and GtkApplication,
|
||||
GtkApplication destroys itself immediately. Because no window is
|
||||
connected to GtkApplication, GtkApplication doesn’t need to wait
|
||||
anything. As it destroys itself, the GtkWindow is also destroyed.</p>
|
||||
<h4 id="show-the-window.">Show the window.</h4>
|
||||
<p>The function <code>gtk_widget_show</code> is used to show the window.</p>
|
||||
<p>Gtk4 changes the default widget visibility to on, so every widget doesn’t need this function to show itself. But, there’s an exception. Top window (this term will be explained later) isn’t visible when it is created. So you need to use the function above to show the window.</p>
|
||||
<p>The function <code>gtk_widget_show</code> is used to show the
|
||||
window.</p>
|
||||
<p>GTK 4 changes the default widget visibility to on, so every widget
|
||||
doesn’t need this function to show itself. But, there’s an exception.
|
||||
Top window (this term will be explained later) isn’t visible when it is
|
||||
created. So you need to use the function above to show the window.</p>
|
||||
<p>Save the program as <code>pr3.c</code> and compile and run it.</p>
|
||||
<pre><code>$ comp pr3
|
||||
$ ./a.out</code></pre>
|
||||
<p>A small window appears.</p>
|
||||
<figure>
|
||||
<img src="image/screenshot_pr3.png" alt="" /><figcaption>Screenshot of the window</figcaption>
|
||||
<img src="image/screenshot_pr3.png" alt="Screenshot of the window" />
|
||||
<figcaption aria-hidden="true">Screenshot of the window</figcaption>
|
||||
</figure>
|
||||
<p>Click on the close button then the window disappears and the program finishes.</p>
|
||||
<p>Click on the close button then the window disappears and the program
|
||||
finishes.</p>
|
||||
<h3 id="gtkapplicationwindow">GtkApplicationWindow</h3>
|
||||
<p>GtkApplicationWindow is a child object of GtkWindow. It has some extra functionality for better integration with GtkApplication. It is recommended to use it instead of GtkWindow when you use GtkApplication.</p>
|
||||
<p>GtkApplicationWindow is a child object of GtkWindow. It has some
|
||||
extra functionality for better integration with GtkApplication. It is
|
||||
recommended to use it instead of GtkWindow when you use
|
||||
GtkApplication.</p>
|
||||
<p>Now rewrite the program and use GtkApplicationWindow.</p>
|
||||
<div class="sourceCode" id="cb17"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb17-2"><a href="#cb17-2"></a>app_activate (GApplication *app, gpointer user_data) {</span>
|
||||
<span id="cb17-3"><a href="#cb17-3"></a> GtkWidget *win;</span>
|
||||
<div class="sourceCode" id="cb17"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb17-2"><a href="#cb17-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="cb17-3"><a href="#cb17-3"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
||||
<span id="cb17-4"><a href="#cb17-4"></a></span>
|
||||
<span id="cb17-5"><a href="#cb17-5"></a> win = gtk_application_window_new (GTK_APPLICATION (app));</span>
|
||||
<span id="cb17-6"><a href="#cb17-6"></a> gtk_window_set_title (GTK_WINDOW (win), <span class="st">"pr4"</span>);</span>
|
||||
<span id="cb17-7"><a href="#cb17-7"></a> gtk_window_set_default_size (GTK_WINDOW (win), <span class="dv">400</span>, <span class="dv">300</span>);</span>
|
||||
<span id="cb17-8"><a href="#cb17-8"></a> gtk_widget_show (win);</span>
|
||||
<span id="cb17-9"><a href="#cb17-9"></a>}</span></code></pre></div>
|
||||
<p>When you create GtkApplicationWindow, you need to give GtkApplication instance as an argument. Then it automatically connect these two instances. So you don’t need to call <code>gtk_window_set_application</code> any more.</p>
|
||||
<p>The program sets the title and the default size of the window. Compile it and run <code>a.out</code>, then you will see a bigger window with its title “pr4”.</p>
|
||||
<span id="cb17-5"><a href="#cb17-5"></a> win <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="cb17-6"><a href="#cb17-6"></a> gtk_window_set_title <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> <span class="st">"pr4"</span><span class="op">);</span></span>
|
||||
<span id="cb17-7"><a href="#cb17-7"></a> gtk_window_set_default_size <span class="op">(</span>GTK_WINDOW <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="cb17-8"><a href="#cb17-8"></a> gtk_widget_show <span class="op">(</span>win<span class="op">);</span></span>
|
||||
<span id="cb17-9"><a href="#cb17-9"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>When you create GtkApplicationWindow, you need to give GtkApplication
|
||||
instance as an argument. Then it automatically connect these two
|
||||
instances. So you don’t need to call
|
||||
<code>gtk_window_set_application</code> any more.</p>
|
||||
<p>The program sets the title and the default size of the window.
|
||||
Compile it and run <code>a.out</code>, then you will see a bigger window
|
||||
with its title “pr4”.</p>
|
||||
<figure>
|
||||
<img src="image/screenshot_pr4.png" alt="" /><figcaption>Screenshot of the window</figcaption>
|
||||
<img src="image/screenshot_pr4.png" alt="Screenshot of the window" />
|
||||
<figcaption aria-hidden="true">Screenshot of the window</figcaption>
|
||||
</figure>
|
||||
</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>
|
||||
|
|
246
docs/sec6.html
246
docs/sec6.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,26 +112,51 @@
|
|||
</div>
|
||||
</nav>
|
||||
<h1 id="string-and-memory-management">String and memory management</h1>
|
||||
<p>GtkTextView and GtkTextBuffer have functions that use string parameters or return a string. The knowledge of strings and memory management is useful to understand how to use these functions.</p>
|
||||
<p>GtkTextView and GtkTextBuffer have functions that use string
|
||||
parameters or return a string. The knowledge of strings and memory
|
||||
management is useful to understand how to use these functions.</p>
|
||||
<h2 id="string-and-memory">String and memory</h2>
|
||||
<p>A String is an array of characters that is terminated with ‘\0’. Strings are not a C type such as char, int, float or double, but exist as a pointer to a character array. They behaves like a string type which you may be familiar from other languages. So, this pointer is often called ‘a string’.</p>
|
||||
<p>In the following, <code>a</code> and <code>b</code> defined as character arrays, and are strings.</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"></a><span class="dt">char</span> a[<span class="dv">10</span>], *b;</span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a>a[<span class="dv">0</span>] = <span class="ch">'H'</span>;</span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a>a[<span class="dv">1</span>] = <span class="ch">'e'</span>;</span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a>a[<span class="dv">2</span>] = <span class="ch">'l'</span>;</span>
|
||||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a>a[<span class="dv">3</span>] = <span class="ch">'l'</span>;</span>
|
||||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a>a[<span class="dv">4</span>] = <span class="ch">'o'</span>;</span>
|
||||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a>a[<span class="dv">5</span>] = <span class="ch">'\0'</span>;</span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a></span>
|
||||
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a>b = a;</span>
|
||||
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a><span class="co">/* *b is 'H' */</span></span>
|
||||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a><span class="co">/* *(++b) is 'e' */</span></span></code></pre></div>
|
||||
<p>The array <code>a</code> has <code>char</code> elements and the size of ten. The first six elements are ‘H’, ‘e’, ‘l’, ‘l’, ‘o’ and ‘\0’. This array represents the string “Hello”. The first five elements are character codes that correspond to the characters. The sixth element is ‘\0’, which is the same as zero, and indicates that the string ends there. The size of the array is 10, so 4 bytes aren’t used, but that’s OK, they are just ignored.</p>
|
||||
<p>The variable ‘b’ is a pointer to a character. Because <code>b</code> is assigned to be <code>a</code>, <code>a</code> and <code>b</code> point the same character (‘H’). The variable <code>a</code> is defined as an array and it can’t be changed. It always point the top address of the array. On the other hand, ‘b’ is a pointer, which is mutable, so <code>b</code> can be change. It is then possible to write statements like <code>++b</code>, which means take the value in b (n address), increase it by one, and store that back in <code>b</code>.</p>
|
||||
<p>If a pointer is NULL, it points to nothing. So, the pointer is not a string. A NULL string on the other hand will be a pointer which points to a location that contains <code>\0</code>, which is a string of length 0 (or ""). Programs that use strings will include bugs if you aren’t careful when using NULL pointers.</p>
|
||||
<p>Another annoying problem is the memory that a string is allocated. There are four cases:</p>
|
||||
<p>A String is an array of characters that is terminated with ‘\0’.
|
||||
Strings are not a C type such as char, int, float or double, but exist
|
||||
as a pointer to a character array. They behaves like a string type which
|
||||
you may be familiar from other languages. So, this pointer is often
|
||||
called ‘a string’.</p>
|
||||
<p>In the following, <code>a</code> and <code>b</code> defined as
|
||||
character arrays, and are strings.</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><span class="dt">char</span> a<span class="op">[</span><span class="dv">10</span><span class="op">],</span> <span class="op">*</span>b<span class="op">;</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>a<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">=</span> <span class="ch">'H'</span><span class="op">;</span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>a<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">=</span> <span class="ch">'e'</span><span class="op">;</span></span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>a<span class="op">[</span><span class="dv">2</span><span class="op">]</span> <span class="op">=</span> <span class="ch">'l'</span><span class="op">;</span></span>
|
||||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>a<span class="op">[</span><span class="dv">3</span><span class="op">]</span> <span class="op">=</span> <span class="ch">'l'</span><span class="op">;</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>a<span class="op">[</span><span class="dv">4</span><span class="op">]</span> <span class="op">=</span> <span class="ch">'o'</span><span class="op">;</span></span>
|
||||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>a<span class="op">[</span><span class="dv">5</span><span class="op">]</span> <span class="op">=</span> <span class="ch">'\0'</span><span class="op">;</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>b <span class="op">=</span> a<span class="op">;</span></span>
|
||||
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="co">/* *b is 'H' */</span></span>
|
||||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="co">/* *(++b) is 'e' */</span></span></code></pre></div>
|
||||
<p>The array <code>a</code> has <code>char</code> elements and the size
|
||||
of ten. The first six elements are ‘H’, ‘e’, ‘l’, ‘l’, ‘o’ and ‘\0’.
|
||||
This array represents the string “Hello”. The first five elements are
|
||||
character codes that correspond to the characters. The sixth element is
|
||||
‘\0’, which is the same as zero, and indicates that the string ends
|
||||
there. The size of the array is 10, so 4 bytes aren’t used, but that’s
|
||||
OK, they are just ignored.</p>
|
||||
<p>The variable ‘b’ is a pointer to a character. Because <code>b</code>
|
||||
is assigned to be <code>a</code>, <code>a</code> and <code>b</code>
|
||||
point the same character (‘H’). The variable <code>a</code> is defined
|
||||
as an array and it can’t be changed. It always point the top address of
|
||||
the array. On the other hand, ‘b’ is a pointer, which is mutable, so
|
||||
<code>b</code> can be change. It is then possible to write statements
|
||||
like <code>++b</code>, which means take the value in b (n address),
|
||||
increase it by one, and store that back in <code>b</code>.</p>
|
||||
<p>If a pointer is NULL, it points to nothing. So, the pointer is not a
|
||||
string. A NULL string on the other hand will be a pointer which points
|
||||
to a location that contains <code>\0</code>, which is a string of length
|
||||
0 (or ““). Programs that use strings will include bugs if you aren’t
|
||||
careful when using NULL pointers.</p>
|
||||
<p>Another annoying problem is the memory that a string is allocated.
|
||||
There are four cases:</p>
|
||||
<ul>
|
||||
<li>The string is read only;</li>
|
||||
<li>The string is in static memory area;</li>
|
||||
|
@ -139,80 +164,137 @@
|
|||
<li>The string is in memory allocated from the heap area.</li>
|
||||
</ul>
|
||||
<h2 id="read-only-string">Read only string</h2>
|
||||
<p>A string literal in a C program is surrounded by double quotes and written as the following:</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="dt">char</span> *s;</span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>s = <span class="st">"Hello"</span></span></code></pre></div>
|
||||
<p>“Hello” is a string literal, and is stored in program memory. A string literal is read only. In the program above, <code>s</code> points the string literal.</p>
|
||||
<p>A string literal in a C program is surrounded by double quotes and
|
||||
written as the following:</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> <span class="op">*</span>s<span class="op">;</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>s <span class="op">=</span> <span class="st">"Hello"</span></span></code></pre></div>
|
||||
<p>“Hello” is a string literal, and is stored in program memory. A
|
||||
string literal is read only. In the program above, <code>s</code> points
|
||||
the string literal.</p>
|
||||
<p>So, the following program is illegal.</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"></a>*(s+<span class="dv">1</span>) = <span class="ch">'a'</span>;</span></code></pre></div>
|
||||
<p>The result is undefined. Probably a bad thing will happen, for example, a segmentation fault.</p>
|
||||
<p>NOTE: The memory of the literal string is allocated when the program is compiled. It is possible to view all the literal strings defined in your program by using the <code>string</code> command.</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><span class="op">*(</span>s<span class="op">+</span><span class="dv">1</span><span class="op">)</span> <span class="op">=</span> <span class="ch">'a'</span><span class="op">;</span></span></code></pre></div>
|
||||
<p>The result is undefined. Probably a bad thing will happen, for
|
||||
example, a segmentation fault.</p>
|
||||
<p>NOTE: The memory of the literal string is allocated when the program
|
||||
is compiled. It is possible to view all the literal strings defined in
|
||||
your program by using the <code>string</code> command.</p>
|
||||
<h2 id="strings-defined-as-arrays">Strings defined as arrays</h2>
|
||||
<p>If a string is defined as an array, it’s in either stored in the static memory area or stack. This depends on the class of the array. If the array’s class is <code>static</code>, then it’s placed in static memory area. This allocation and memory address is fixed for the life of the program. This area can be changed and is writable.</p>
|
||||
<p>If the array’s class is <code>auto</code>, then it’s placed in stack. If the array is defined inside a function, its default class is <code>auto</code>. The stack area will disappear when the function exits and returns to the caller. Arrays defined on the stack are writable.</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"></a></span>
|
||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="dt">static</span> <span class="dt">char</span> a[] = {<span class="ch">'H'</span>, <span class="ch">'e'</span>, <span class="ch">'l'</span>, <span class="ch">'l'</span>, <span class="ch">'o'</span>, <span class="ch">'\0'</span>};</span>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a></span>
|
||||
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a><span class="dt">void</span></span>
|
||||
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a>print_strings (<span class="dt">void</span>) {</span>
|
||||
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a> <span class="dt">char</span> b[] = <span class="st">"Hello"</span>;</span>
|
||||
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a></span>
|
||||
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a> a[<span class="dv">1</span>] = <span class="ch">'a'</span>; <span class="co">/* Because the array is static, it's writable. */</span></span>
|
||||
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a> b[<span class="dv">1</span>] = <span class="ch">'a'</span>; <span class="co">/* Because the array is auto, it's writable. */</span></span>
|
||||
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a></span>
|
||||
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a> printf (<span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span>, a); <span class="co">/* Hallo */</span></span>
|
||||
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a> printf (<span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span>, b); <span class="co">/* Hallo */</span></span>
|
||||
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a>}</span></code></pre></div>
|
||||
<p>The array <code>a</code> is defined externally to a function and is global in its scope. Such variables are placed in static memory area even if the <code>static</code> class is left out. The compiler calculates the number of the elements in the right hand side (six), and then creates code that allocates six bytes in the static memory area and copies the data to this memory.</p>
|
||||
<p>The array <code>b</code> is defined inside the function so its class is <code>auto</code>. The compiler calculates the number of the elements in the string literal. It has six elements as the zero termination character is also included. The compiler creates code which allocates six bytes memory in the stack and copies the data to the memory.</p>
|
||||
<p>If a string is defined as an array, it’s in either stored in the
|
||||
static memory area or stack. This depends on the class of the array. If
|
||||
the array’s class is <code>static</code>, then it’s placed in static
|
||||
memory area. This allocation and memory address is fixed for the life of
|
||||
the program. This area can be changed and is writable.</p>
|
||||
<p>If the array’s class is <code>auto</code>, then it’s placed in stack.
|
||||
If the array is defined inside a function, its default class is
|
||||
<code>auto</code>. The stack area will disappear when the function exits
|
||||
and returns to the caller. Arrays defined on the stack are writable.</p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">char</span> a<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="ch">'H'</span><span class="op">,</span> <span class="ch">'e'</span><span class="op">,</span> <span class="ch">'l'</span><span class="op">,</span> <span class="ch">'l'</span><span class="op">,</span> <span class="ch">'o'</span><span class="op">,</span> <span class="ch">'\0'</span><span class="op">};</span></span>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span></span>
|
||||
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>print_strings <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">char</span> b<span class="op">[]</span> <span class="op">=</span> <span class="st">"Hello"</span><span class="op">;</span></span>
|
||||
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a> a<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">=</span> <span class="ch">'a'</span><span class="op">;</span> <span class="co">/* Because the array is static, it's writable. */</span></span>
|
||||
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a> b<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">=</span> <span class="ch">'a'</span><span class="op">;</span> <span class="co">/* Because the array is auto, it's writable. */</span></span>
|
||||
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a> printf <span class="op">(</span><span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> a<span class="op">);</span> <span class="co">/* Hallo */</span></span>
|
||||
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a> printf <span class="op">(</span><span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> b<span class="op">);</span> <span class="co">/* Hallo */</span></span>
|
||||
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>The array <code>a</code> is defined externally to a function and is
|
||||
global in its scope. Such variables are placed in static memory area
|
||||
even if the <code>static</code> class is left out. The compiler
|
||||
calculates the number of the elements in the right hand side (six), and
|
||||
then creates code that allocates six bytes in the static memory area and
|
||||
copies the data to this memory.</p>
|
||||
<p>The array <code>b</code> is defined inside the function so its class
|
||||
is <code>auto</code>. The compiler calculates the number of the elements
|
||||
in the string literal. It has six elements as the zero termination
|
||||
character is also included. The compiler creates code which allocates
|
||||
six bytes memory in the stack and copies the data to the memory.</p>
|
||||
<p>Both <code>a</code> and <code>b</code> are writable.</p>
|
||||
<p>The memory is managed by the executable program. You don’t need your program to allocate or free the memory for <code>a</code> and <code>b</code>. The array <code>a</code> is created then the program is first run and remains for the life of the program. The array <code>b</code> is created on the stack then the function is called, disappears when the function returns.</p>
|
||||
<p>The memory is managed by the executable program. You don’t need your
|
||||
program to allocate or free the memory for <code>a</code> and
|
||||
<code>b</code>. The array <code>a</code> is created then the program is
|
||||
first run and remains for the life of the program. The array
|
||||
<code>b</code> is created on the stack then the function is called,
|
||||
disappears when the function returns.</p>
|
||||
<h2 id="strings-in-the-heap-area">Strings in the heap area</h2>
|
||||
<p>You can also get, use and release memory from the heap area. The standard C library provides <code>malloc</code> to get memory and <code>free</code> to put back memory. GLib provides the functions <code>g_new</code> and <code>g_free</code> to do the same thing, with support for some additional Glib functionality.</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"></a>g_new (struct_type, n_struct)</span></code></pre></div>
|
||||
<p>You can also get, use and release memory from the heap area. The
|
||||
standard C library provides <code>malloc</code> to get memory and
|
||||
<code>free</code> to put back memory. GLib provides the functions
|
||||
<code>g_new</code> and <code>g_free</code> to do the same thing, with
|
||||
support for some additional GLib functionality.</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>g_new <span class="op">(</span>struct_type<span class="op">,</span> n_struct<span class="op">)</span></span></code></pre></div>
|
||||
<p><code>g_new</code> is a macro to allocate memory for an array.</p>
|
||||
<ul>
|
||||
<li><code>struct_type</code> is the type of the element of the array.</li>
|
||||
<li><code>struct_type</code> is the type of the element of the
|
||||
array.</li>
|
||||
<li><code>n_struct</code> is the size of the array.</li>
|
||||
<li>The return value is a pointer to the array. Its type is a pointer to <code>struct_type</code>.</li>
|
||||
<li>The return value is a pointer to the array. Its type is a pointer to
|
||||
<code>struct_type</code>.</li>
|
||||
</ul>
|
||||
<p>For example,</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"></a><span class="dt">char</span> *s;</span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a>s = g_new (<span class="dt">char</span>, <span class="dv">10</span>);</span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a><span class="co">/* s points an array of char. The size of the array is 10. */</span></span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a></span>
|
||||
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="kw">struct</span> tuple {<span class="dt">int</span> x, y;} *t;</span>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a>t = g_new (<span class="kw">struct</span> tuple, <span class="dv">5</span>);</span>
|
||||
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="co">/* t points an array of struct tuple. */</span></span>
|
||||
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a><span class="co">/* The size of the array is 5. */</span></span></code></pre></div>
|
||||
<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">char</span> <span class="op">*</span>s<span class="op">;</span></span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>s <span class="op">=</span> g_new <span class="op">(</span><span class="dt">char</span><span class="op">,</span> <span class="dv">10</span><span class="op">);</span></span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="co">/* s points an array of char. The size of the array is 10. */</span></span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> tuple <span class="op">{</span><span class="dt">int</span> x<span class="op">,</span> y<span class="op">;}</span> <span class="op">*</span>t<span class="op">;</span></span>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>t <span class="op">=</span> g_new <span class="op">(</span><span class="kw">struct</span> tuple<span class="op">,</span> <span class="dv">5</span><span class="op">);</span></span>
|
||||
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="co">/* t points an array of struct tuple. */</span></span>
|
||||
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="co">/* The size of the array is 5. */</span></span></code></pre></div>
|
||||
<p><code>g_free</code> frees memory.</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"></a><span class="dt">void</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a>g_free (gpointer mem);</span></code></pre></div>
|
||||
<p>If <code>mem</code> is NULL, <code>g_free</code> does nothing. <code>gpointer</code> is a type of general pointer. It is the same as <code>void *</code>. This pointer can be casted to any pointer type. Conversely, any pointer type can be casted to <code>gpointer</code>.</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"></a>g_free (s);</span>
|
||||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="co">/* Frees the memory allocated to s. */</span></span>
|
||||
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a></span>
|
||||
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a>g_free (t);</span>
|
||||
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a><span class="co">/* Frees the memory allocated to t. */</span></span></code></pre></div>
|
||||
<p>If the argument doesn’t point allocated memory it will cause an error, specifically, a segmentation fault.</p>
|
||||
<p>Some Glib functions allocate memory. For example, <code>g_strdup</code> allocates memory and copies a string given as an argument.</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="dt">char</span> *s;</span>
|
||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a>s = g_strdup (<span class="st">"Hello"</span>);</span>
|
||||
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a>g_free (s);</span></code></pre></div>
|
||||
<p>The string literal “Hello” has 6 bytes because the string has ‘\0’ at the end it. <code>g_strdup</code> gets 6 bytes from the heap area and copies the string to the memory. <code>s</code> is assigned the top address of the memory. <code>g_free</code> returns the memory to the heap area.</p>
|
||||
<p><code>g_strdup</code> is described in <a href="https://docs.gtk.org/glib/func.strdup.html">GLib API Reference</a>. The following is extracted from the reference.</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="dt">void</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>g_free <span class="op">(</span>gpointer mem<span class="op">);</span></span></code></pre></div>
|
||||
<p>If <code>mem</code> is NULL, <code>g_free</code> does nothing.
|
||||
<code>gpointer</code> is a type of general pointer. It is the same as
|
||||
<code>void *</code>. This pointer can be casted to any pointer type.
|
||||
Conversely, any pointer type can be casted to <code>gpointer</code>.</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>g_free <span class="op">(</span>s<span class="op">);</span></span>
|
||||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="co">/* Frees the memory allocated to s. */</span></span>
|
||||
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>g_free <span class="op">(</span>t<span class="op">);</span></span>
|
||||
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="co">/* Frees the memory allocated to t. */</span></span></code></pre></div>
|
||||
<p>If the argument doesn’t point allocated memory it will cause an
|
||||
error, specifically, a segmentation fault.</p>
|
||||
<p>Some GLib functions allocate memory. For example,
|
||||
<code>g_strdup</code> allocates memory and copies a string given as an
|
||||
argument.</p>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> <span class="op">*</span>s<span class="op">;</span></span>
|
||||
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>s <span class="op">=</span> g_strdup <span class="op">(</span><span class="st">"Hello"</span><span class="op">);</span></span>
|
||||
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>g_free <span class="op">(</span>s<span class="op">);</span></span></code></pre></div>
|
||||
<p>The string literal “Hello” has 6 bytes because the string has ‘\0’ at
|
||||
the end it. <code>g_strdup</code> gets 6 bytes from the heap area and
|
||||
copies the string to the memory. <code>s</code> is assigned the top
|
||||
address of the memory. <code>g_free</code> returns the memory to the
|
||||
heap area.</p>
|
||||
<p><code>g_strdup</code> is described in <a
|
||||
href="https://docs.gtk.org/glib/func.strdup.html">GLib API
|
||||
Reference</a>. The following is extracted from the reference.</p>
|
||||
<blockquote>
|
||||
<p>The returned string should be freed with <code>g_free()</code> when no longer needed.</p>
|
||||
<p>The returned string should be freed with <code>g_free()</code> when
|
||||
no longer needed.</p>
|
||||
</blockquote>
|
||||
<p>The function reference will describe if the returned value needs to be freed. If you forget to free the allocated memory it will remain allocated. Repeated use will cause more memory to be allocated to the program, which will grow over time. This is called a memory leak, and the only way to address this bug is to close the program (and restart it), which will automatically release all of the programs memory back to the system.</p>
|
||||
<p>Some GLib functions return a string which mustn’t be freed by the caller.</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"></a><span class="dt">const</span> <span class="dt">char</span> *</span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a>g_quark_to_string (GQuark quark);</span></code></pre></div>
|
||||
<p>This function returns <code>const char*</code> type. The qualifier <code>const</code> means that the returned value is immutable. The characters pointed by the returned value aren’t be allowed to be changed or freed.</p>
|
||||
<p>If a variable is qualified with <code>const</code>, the variable can’t be assigned except during initialization.</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="dt">const</span> <span class="dt">int</span> x = <span class="dv">10</span>; <span class="co">/* initialization is OK. */</span></span>
|
||||
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a></span>
|
||||
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a>x = <span class="dv">20</span>; <span class="co">/* This is illegal because x is qualified with const */</span></span></code></pre></div>
|
||||
<p>The function reference will describe if the returned value needs to
|
||||
be freed. If you forget to free the allocated memory it will remain
|
||||
allocated. Repeated use will cause more memory to be allocated to the
|
||||
program, which will grow over time. This is called a memory leak, and
|
||||
the only way to address this bug is to close the program (and restart
|
||||
it), which will automatically release all of the programs memory back to
|
||||
the system.</p>
|
||||
<p>Some GLib functions return a string which mustn’t be freed by the
|
||||
caller.</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>g_quark_to_string <span class="op">(</span>GQuark quark<span class="op">);</span></span></code></pre></div>
|
||||
<p>This function returns <code>const char*</code> type. The qualifier
|
||||
<code>const</code> means that the returned value is immutable. The
|
||||
characters pointed by the returned value aren’t be allowed to be changed
|
||||
or freed.</p>
|
||||
<p>If a variable is qualified with <code>const</code>, the variable
|
||||
can’t be assigned except during initialization.</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="dt">int</span> x <span class="op">=</span> <span class="dv">10</span><span class="op">;</span> <span class="co">/* initialization is OK. */</span></span>
|
||||
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> <span class="dv">20</span><span class="op">;</span> <span class="co">/* This is illegal because x is qualified with const */</span></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>
|
||||
</body>
|
||||
|
|
524
docs/sec8.html
524
docs/sec8.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;}
|
||||
|
@ -111,10 +111,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 id="defining-a-child-object">Defining a Child object</h1>
|
||||
<h2 id="a-very-simple-editor">A Very Simple Editor</h2>
|
||||
<p>In the previous section we made a very simple file viewer. Now we go on to rewrite it and turn it into very simple editor. Its source file is in tfe1.c (text file editor 1).</p>
|
||||
<p>GtkTextView has a feature for editing multiple lines. Therefore, we don’t need to write the program from scratch, we just add two things to the file viewer:</p>
|
||||
<h1 id="defining-a-child-object">Defining a child object</h1>
|
||||
<h2 id="a-very-simple-editor">A very simple editor</h2>
|
||||
<p>In the previous section we made a very simple file viewer. Now we go
|
||||
on to rewrite it and turn it into very simple editor. Its source file is
|
||||
in tfe1.c (text file editor 1).</p>
|
||||
<p>GtkTextView has a feature for editing multiple lines. Therefore, we
|
||||
don’t need to write the program from scratch, we just add two things to
|
||||
the file viewer:</p>
|
||||
<ul>
|
||||
<li>Memory to store a pointer to the GFile instance.</li>
|
||||
<li>A function to write the file.</li>
|
||||
|
@ -122,259 +126,357 @@
|
|||
<p>There are a couple of ways to store the details of GFile.</p>
|
||||
<ul>
|
||||
<li>Use global variables; or</li>
|
||||
<li>Make a child object, which can extend the instance memory for the GFile object.</li>
|
||||
<li>Make a child object, which can extend the instance memory for the
|
||||
GFile object.</li>
|
||||
</ul>
|
||||
<p>Using global variables is easy to implement. Define a sufficient size array of pointers to GFile. For example,</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"></a>GFile *f[<span class="dv">20</span>];</span></code></pre></div>
|
||||
<p>The variable <code>f[i]</code> corresponds to the file associated to the i-th GtkNotebookPage. There are however two problems with this. The first concerns the size of the array. If a user gives too many arguments (more than 20 in the example above), it is impossible to store the additional pointers to the GFile instances. The second is the increasing difficulty for maintenance of the program. We have a small program so far, but however, if you continue developing it, the size of the program will grow. Generally speaking, the bigger the program size, the more difficult it is to keep track of and maintain global variables. Global variables can be used and changed anywhere throughout the entire program.</p>
|
||||
<p>Making a child object is a good idea in terms of maintenance. One thing you need to be careful of is the difference between “child object” and “child widget”. Here we are describing a “child object”. A child object includes, and expands on its parent object, as a child object derives everything from the parent object.</p>
|
||||
<p>Using global variables is easy to implement. Define a sufficient size
|
||||
array of pointers to GFile. For example,</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>GFile <span class="op">*</span>f<span class="op">[</span><span class="dv">20</span><span class="op">];</span></span></code></pre></div>
|
||||
<p>The variable <code>f[i]</code> corresponds to the file associated to
|
||||
the i-th GtkNotebookPage. There are however two problems with this. The
|
||||
first concerns the size of the array. If a user gives too many arguments
|
||||
(more than 20 in the example above), it is impossible to store the
|
||||
additional pointers to the GFile instances. The second is the increasing
|
||||
difficulty for maintenance of the program. We have a small program so
|
||||
far, but however, if you continue developing it, the size of the program
|
||||
will grow. Generally speaking, the bigger the program size, the more
|
||||
difficult it is to keep track of and maintain global variables. Global
|
||||
variables can be used and changed anywhere throughout the entire
|
||||
program.</p>
|
||||
<p>Making a child object is a good idea in terms of maintenance. One
|
||||
thing you need to be careful of is the difference between “child object”
|
||||
and “child widget”. Here we are describing a “child object”. A child
|
||||
object includes, and expands on its parent object, as a child object
|
||||
derives everything from the parent object.</p>
|
||||
<figure>
|
||||
<img src="image/child.png" alt="" /><figcaption>Child object of GtkTextView</figcaption>
|
||||
<img src="image/child.png" alt="Child object of GtkTextView" />
|
||||
<figcaption aria-hidden="true">Child object of GtkTextView</figcaption>
|
||||
</figure>
|
||||
<p>We will define TfeTextView as a child object of GtkTextView. It has everything that GtkTextView has. Specifically, TfeTextView has a GtkTextbuffer which corresponds to the GtkTextView inside TfeTextView. The additional important thing is that TfeTextView can also keep an additional pointer to GFile.</p>
|
||||
<p>In general, this is how GObjects work. Understanding the general theory about Gobject’s is difficult, particularly for beginners. So, I will just show you the way how to write the code and avoid the theoretical side. If you want to know about GObject system, refer to another <a href="https://github.com/ToshioCP/Gobject-tutorial">tutorial</a>.</p>
|
||||
<h2 id="how-to-define-a-child-object-of-gtktextview">How to Define a Child Object of GtkTextView</h2>
|
||||
<p>Let’s define the TfeTextView object, which is a child object of GtkTextView. First, look at the program below.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="pp">#define TFE_TYPE_TEXT_VIEW tfe_text_view_get_type ()</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>G_DECLARE_FINAL_TYPE (TfeTextView, tfe_text_view, TFE, TEXT_VIEW, GtkTextView)</span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a></span>
|
||||
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a><span class="kw">struct</span> _TfeTextView</span>
|
||||
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a>{</span>
|
||||
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a> GtkTextView parent;</span>
|
||||
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a> GFile *file;</span>
|
||||
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a>};</span>
|
||||
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a></span>
|
||||
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a>G_DEFINE_TYPE (TfeTextView, tfe_text_view, GTK_TYPE_TEXT_VIEW);</span>
|
||||
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a></span>
|
||||
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a>tfe_text_view_init (TfeTextView *tv) {</span>
|
||||
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true"></a>}</span>
|
||||
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true"></a></span>
|
||||
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true"></a>tfe_text_view_class_init (TfeTextViewClass *class) {</span>
|
||||
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true"></a>}</span>
|
||||
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true"></a></span>
|
||||
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true"></a><span class="dt">void</span></span>
|
||||
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true"></a>tfe_text_view_set_file (TfeTextView *tv, GFile *f) {</span>
|
||||
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true"></a> tv -> file = f;</span>
|
||||
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true"></a>}</span>
|
||||
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true"></a></span>
|
||||
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true"></a>GFile *</span>
|
||||
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true"></a>tfe_text_view_get_file (TfeTextView *tv) {</span>
|
||||
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true"></a> <span class="cf">return</span> tv -> file;</span>
|
||||
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true"></a>}</span>
|
||||
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true"></a></span>
|
||||
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true"></a>GtkWidget *</span>
|
||||
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true"></a>tfe_text_view_new (<span class="dt">void</span>) {</span>
|
||||
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true"></a> <span class="cf">return</span> GTK_WIDGET (g_object_new (TFE_TYPE_TEXT_VIEW, NULL));</span>
|
||||
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true"></a>}</span></code></pre></div>
|
||||
<p>If you are curious about the background theory of this program, that’s good, because knowing the theory is very important if you want to program GTK applications. Look at <a href="https://docs.gtk.org/gobject/">GObject API Reference</a>. All you need is described there, or refer to <a href="https://github.com/ToshioCP/Gobject-tutorial">GObject tutorial</a>. It’s a tough journey especially for beginners so for now, you don’t need to know about this difficult theory. It is enough to just remember the instructions below.</p>
|
||||
<p>We will define TfeTextView as a child object of GtkTextView. It has
|
||||
everything that GtkTextView has. Specifically, TfeTextView has a
|
||||
GtkTextbuffer which corresponds to the GtkTextView inside TfeTextView.
|
||||
The additional important thing is that TfeTextView can also keep an
|
||||
additional pointer to GFile.</p>
|
||||
<p>In general, this is how GObjects work. Understanding the general
|
||||
theory about Gobject’s is difficult, particularly for beginners. So, I
|
||||
will just show you the way how to write the code and avoid the
|
||||
theoretical side. If you want to know about GObject system, refer to
|
||||
another <a
|
||||
href="https://github.com/ToshioCP/Gobject-tutorial">tutorial</a>.</p>
|
||||
<h2 id="how-to-define-a-child-object-of-gtktextview">How to define a
|
||||
child object of GtkTextView</h2>
|
||||
<p>Let’s define the TfeTextView object, which is a child object of
|
||||
GtkTextView. First, look at the program below.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TFE_TYPE_TEXT_VIEW tfe_text_view_get_type ()</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfeTextView<span class="op">,</span> tfe_text_view<span class="op">,</span> TFE<span class="op">,</span> TEXT_VIEW<span class="op">,</span> GtkTextView<span class="op">)</span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> _TfeTextView</span>
|
||||
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
|
||||
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> GtkTextView parent<span class="op">;</span></span>
|
||||
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> GFile <span class="op">*</span>file<span class="op">;</span></span>
|
||||
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
|
||||
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>G_DEFINE_TYPE <span class="op">(</span>TfeTextView<span class="op">,</span> tfe_text_view<span class="op">,</span> GTK_TYPE_TEXT_VIEW<span class="op">);</span></span>
|
||||
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>tfe_text_view_init <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>tfe_text_view_class_init <span class="op">(</span>TfeTextViewClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span></span>
|
||||
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>tfe_text_view_set_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">,</span> GFile <span class="op">*</span>f<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> tv <span class="op">-></span> file <span class="op">=</span> f<span class="op">;</span></span>
|
||||
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>GFile <span class="op">*</span></span>
|
||||
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>tfe_text_view_get_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> tv <span class="op">-></span> file<span class="op">;</span></span>
|
||||
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||||
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>GtkWidget <span class="op">*</span></span>
|
||||
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>tfe_text_view_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_TEXT_VIEW<span class="op">,</span> NULL<span class="op">));</span></span>
|
||||
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>If you are curious about the background theory of this program,
|
||||
that’s good, because knowing the theory is very important if you want to
|
||||
program GTK applications. Look at <a
|
||||
href="https://docs.gtk.org/gobject/">GObject API Reference</a>. All you
|
||||
need is described there, or refer to <a
|
||||
href="https://github.com/ToshioCP/Gobject-tutorial">GObject
|
||||
tutorial</a>. It’s a tough journey especially for beginners so for now,
|
||||
you don’t need to know about this difficult theory. It is enough to just
|
||||
remember the instructions below.</p>
|
||||
<ul>
|
||||
<li>TfeTextView is divided into two parts. Tfe and TextView. Tfe is called the prefix, namespace or module. TextView is called the object.</li>
|
||||
<li>There are three differnet identifier patterns. TfeTextView (camel case), tfe_text_view (this is used to write functions) and TFE_TEXT_VIEW (This is used to cast a pointer to point TfeTextView type).</li>
|
||||
<li>First, define TFE_TYPE_TEXT_VIEW macro as tfe_text_view_get_type (). The name is always (prefix)_TYPE_(object) and the letters are upper case. And the replacement text is always (prefix)_(object)_get_type () and the letters are lower case.</li>
|
||||
<li>Next, use G_DECLARE_FINAL_TYPE macro. The arguments are the child object name in camel case, lower case with underscore, prefix (upper case), object (upper case with underscore) and parent object name (camel case).</li>
|
||||
<li>Declare the structure _TfeTextView. The underscore is necessary. The first member is the parent object. Notice this is not a pointer but the object itself. The second member and after are members of the child object. TfeTextView structure has a pointer to a GFile instance as a member.</li>
|
||||
<li>Use G_DEFINE_TYPE macro. The arguments are the child object name in camel case, lower case with underscore and parent object type (prefix)_TYPE_(module).</li>
|
||||
<li>Define instance init function (tfe_text_view_init). Usually you don’t need to do anything.</li>
|
||||
<li>Define class init function (tfe_text_view_class_init). You don’t need to do anything in this object.</li>
|
||||
<li>Write function codes you want to add (tfe_text_view_set_file and tfe_text_view_get_file). <code>tv</code> is a pointer to the TfeTextView object instance which is a C-structure declared with the tag _TfeTextView. So, the structure has a member <code>file</code> as a pointer to a GFile instance. <code>tv->file = f</code> is an assignment of <code>f</code> to a member <code>file</code> of the structure pointed by <code>tv</code>. This is an example how to use the extended memory in a child widget.</li>
|
||||
<li>Write a function to create an instance. Its name is (prefix)_(object)_new. If the parent object function needs parameters, this function also need them. You sometimes might want to add some parameters. It’s your choice. Use g_object_new function to create the instance. The arguments are (prefix)_TYPE_(object), a list to initialize properties and NULL. In this code no property needs to be initialized. And the return value is casted to GtkWidget.</li>
|
||||
<li>TfeTextView is divided into two parts. Tfe and TextView. Tfe is
|
||||
called the prefix, namespace or module. TextView is called the
|
||||
object.</li>
|
||||
<li>There are three differnet identifier patterns. TfeTextView (camel
|
||||
case), tfe_text_view (this is used to write functions) and TFE_TEXT_VIEW
|
||||
(This is used to cast a pointer to point TfeTextView type).</li>
|
||||
<li>First, define TFE_TYPE_TEXT_VIEW macro as tfe_text_view_get_type ().
|
||||
The name is always (prefix)_TYPE_(object) and the letters are upper
|
||||
case. And the replacement text is always (prefix)_(object)_get_type ()
|
||||
and the letters are lower case.</li>
|
||||
<li>Next, use G_DECLARE_FINAL_TYPE macro. The arguments are the child
|
||||
object name in camel case, lower case with underscore, prefix (upper
|
||||
case), object (upper case with underscore) and parent object name (camel
|
||||
case).</li>
|
||||
<li>Declare the structure _TfeTextView. The underscore is necessary. The
|
||||
first member is the parent object. Notice this is not a pointer but the
|
||||
object itself. The second member and after are members of the child
|
||||
object. TfeTextView structure has a pointer to a GFile instance as a
|
||||
member.</li>
|
||||
<li>Use G_DEFINE_TYPE macro. The arguments are the child object name in
|
||||
camel case, lower case with underscore and parent object type
|
||||
(prefix)_TYPE_(module).</li>
|
||||
<li>Define instance init function (tfe_text_view_init). Usually you
|
||||
don’t need to do anything.</li>
|
||||
<li>Define class init function (tfe_text_view_class_init). You don’t
|
||||
need to do anything in this object.</li>
|
||||
<li>Write function codes you want to add (tfe_text_view_set_file and
|
||||
tfe_text_view_get_file). <code>tv</code> is a pointer to the TfeTextView
|
||||
object instance which is a C-structure declared with the tag
|
||||
_TfeTextView. So, the structure has a member <code>file</code> as a
|
||||
pointer to a GFile instance. <code>tv->file = f</code> is an
|
||||
assignment of <code>f</code> to a member <code>file</code> of the
|
||||
structure pointed by <code>tv</code>. This is an example how to use the
|
||||
extended memory in a child widget.</li>
|
||||
<li>Write a function to create an instance. Its name is
|
||||
(prefix)_(object)_new. If the parent object function needs parameters,
|
||||
this function also need them. You sometimes might want to add some
|
||||
parameters. It’s your choice. Use g_object_new function to create the
|
||||
instance. The arguments are (prefix)_TYPE_(object), a list to initialize
|
||||
properties and NULL. In this code no property needs to be initialized.
|
||||
And the return value is casted to GtkWidget.</li>
|
||||
</ul>
|
||||
<p>This program is not perfect. It has some problems. It will be modified later.</p>
|
||||
<p>This program is not perfect. It has some problems. It will be
|
||||
modified later.</p>
|
||||
<h2 id="close-request-signal">Close-request signal</h2>
|
||||
<p>Imagine that you are using this editor. First, you run the editor with arguments. The arguments are filenames. The editor reads the files and shows the window with the text of files in it. Then you edit the text. After you finish editing, you exit the editor. The editor updates files just before the window closes.</p>
|
||||
<p>GtkWindow emits the “close-request” signal before it closes. We connect the signal and the handler <code>before_close</code>. A handler is a C function. When a function is connected to a certain signal, we call it a handler. The function <code>before_close</code> is invoked when the signal “close-request” is emitted.</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"></a>g_signal_connect (win, <span class="st">"close-request"</span>, G_CALLBACK (before_close), NULL);</span></code></pre></div>
|
||||
<p>The argument <code>win</code> is a GtkApplicationWindow, in which the signal “close-request” is defined, and <code>before_close</code> is the handler. <code>G_CALLBACK</code> cast is necessary for the handler. The program of <code>before_close</code> is as follows.</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="dt">static</span> gboolean</span>
|
||||
<span id="cb4-2"><a href="#cb4-2"></a>before_close (GtkWindow *win, gpointer user_data) {</span>
|
||||
<span id="cb4-3"><a href="#cb4-3"></a> GtkWidget *nb = GTK_WIDGET (user_data);</span>
|
||||
<span id="cb4-4"><a href="#cb4-4"></a> GtkWidget *scr;</span>
|
||||
<span id="cb4-5"><a href="#cb4-5"></a> GtkWidget *tv;</span>
|
||||
<span id="cb4-6"><a href="#cb4-6"></a> GFile *file;</span>
|
||||
<span id="cb4-7"><a href="#cb4-7"></a> <span class="dt">char</span> *pathname;</span>
|
||||
<span id="cb4-8"><a href="#cb4-8"></a> GtkTextBuffer *tb;</span>
|
||||
<span id="cb4-9"><a href="#cb4-9"></a> GtkTextIter start_iter;</span>
|
||||
<span id="cb4-10"><a href="#cb4-10"></a> GtkTextIter end_iter;</span>
|
||||
<span id="cb4-11"><a href="#cb4-11"></a> <span class="dt">char</span> *contents;</span>
|
||||
<span id="cb4-12"><a href="#cb4-12"></a> <span class="dt">unsigned</span> <span class="dt">int</span> n;</span>
|
||||
<span id="cb4-13"><a href="#cb4-13"></a> <span class="dt">unsigned</span> <span class="dt">int</span> i;</span>
|
||||
<p>Imagine that you are using this editor. First, you run the editor
|
||||
with arguments. The arguments are filenames. The editor reads the files
|
||||
and shows the window with the text of files in it. Then you edit the
|
||||
text. After you finish editing, you exit the editor. The editor updates
|
||||
files just before the window closes.</p>
|
||||
<p>GtkWindow emits the “close-request” signal before it closes. We
|
||||
connect the signal and the handler <code>before_close</code>. A handler
|
||||
is a C function. When a function is connected to a certain signal, we
|
||||
call it a handler. The function <code>before_close</code> is invoked
|
||||
when the signal “close-request” is emitted.</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>g_signal_connect <span class="op">(</span>win<span class="op">,</span> <span class="st">"close-request"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>before_close<span class="op">),</span> NULL<span class="op">);</span></span></code></pre></div>
|
||||
<p>The argument <code>win</code> is a GtkApplicationWindow, in which the
|
||||
signal “close-request” is defined, and <code>before_close</code> is the
|
||||
handler. <code>G_CALLBACK</code> cast is necessary for the handler. The
|
||||
program of <code>before_close</code> is as follows.</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="dt">static</span> gboolean</span>
|
||||
<span id="cb4-2"><a href="#cb4-2"></a>before_close <span class="op">(</span>GtkWindow <span class="op">*</span>win<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-3"><a href="#cb4-3"></a> GtkWidget <span class="op">*</span>nb <span class="op">=</span> GTK_WIDGET <span class="op">(</span>user_data<span class="op">);</span></span>
|
||||
<span id="cb4-4"><a href="#cb4-4"></a> GtkWidget <span class="op">*</span>scr<span class="op">;</span></span>
|
||||
<span id="cb4-5"><a href="#cb4-5"></a> GtkWidget <span class="op">*</span>tv<span class="op">;</span></span>
|
||||
<span id="cb4-6"><a href="#cb4-6"></a> GFile <span class="op">*</span>file<span class="op">;</span></span>
|
||||
<span id="cb4-7"><a href="#cb4-7"></a> <span class="dt">char</span> <span class="op">*</span>pathname<span class="op">;</span></span>
|
||||
<span id="cb4-8"><a href="#cb4-8"></a> GtkTextBuffer <span class="op">*</span>tb<span class="op">;</span></span>
|
||||
<span id="cb4-9"><a href="#cb4-9"></a> GtkTextIter start_iter<span class="op">;</span></span>
|
||||
<span id="cb4-10"><a href="#cb4-10"></a> GtkTextIter end_iter<span class="op">;</span></span>
|
||||
<span id="cb4-11"><a href="#cb4-11"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span>
|
||||
<span id="cb4-12"><a href="#cb4-12"></a> <span class="dt">unsigned</span> <span class="dt">int</span> n<span class="op">;</span></span>
|
||||
<span id="cb4-13"><a href="#cb4-13"></a> <span class="dt">unsigned</span> <span class="dt">int</span> i<span class="op">;</span></span>
|
||||
<span id="cb4-14"><a href="#cb4-14"></a></span>
|
||||
<span id="cb4-15"><a href="#cb4-15"></a> n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb));</span>
|
||||
<span id="cb4-16"><a href="#cb4-16"></a> <span class="cf">for</span> (i = <span class="dv">0</span>; i < n; ++i) {</span>
|
||||
<span id="cb4-17"><a href="#cb4-17"></a> scr = gtk_notebook_get_nth_page (GTK_NOTEBOOK (nb), i);</span>
|
||||
<span id="cb4-18"><a href="#cb4-18"></a> tv = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (scr));</span>
|
||||
<span id="cb4-19"><a href="#cb4-19"></a> file = tfe_text_view_get_file (TFE_TEXT_VIEW (tv));</span>
|
||||
<span id="cb4-20"><a href="#cb4-20"></a> tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
|
||||
<span id="cb4-21"><a href="#cb4-21"></a> gtk_text_buffer_get_bounds (tb, &start_iter, &end_iter);</span>
|
||||
<span id="cb4-22"><a href="#cb4-22"></a> contents = gtk_text_buffer_get_text (tb, &start_iter, &end_iter, FALSE);</span>
|
||||
<span id="cb4-23"><a href="#cb4-23"></a> <span class="cf">if</span> (! g_file_replace_contents (file, contents, strlen (contents), NULL, TRUE, G_FILE_CREATE_NONE, NULL, NULL, NULL)) {</span>
|
||||
<span id="cb4-24"><a href="#cb4-24"></a> pathname = g_file_get_path (file);</span>
|
||||
<span id="cb4-25"><a href="#cb4-25"></a> g_print (<span class="st">"ERROR : Can't save %s."</span>, pathname);</span>
|
||||
<span id="cb4-26"><a href="#cb4-26"></a> g_free (pathname);</span>
|
||||
<span id="cb4-27"><a href="#cb4-27"></a> }</span>
|
||||
<span id="cb4-28"><a href="#cb4-28"></a> g_free (contents);</span>
|
||||
<span id="cb4-29"><a href="#cb4-29"></a> }</span>
|
||||
<span id="cb4-30"><a href="#cb4-30"></a> <span class="cf">return</span> FALSE;</span>
|
||||
<span id="cb4-31"><a href="#cb4-31"></a>}</span></code></pre></div>
|
||||
<p>The numbers on the left of items are line numbers in the source code.</p>
|
||||
<span id="cb4-15"><a href="#cb4-15"></a> n <span class="op">=</span> gtk_notebook_get_n_pages <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">));</span></span>
|
||||
<span id="cb4-16"><a href="#cb4-16"></a> <span class="cf">for</span> <span class="op">(</span>i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> n<span class="op">;</span> <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb4-17"><a href="#cb4-17"></a> scr <span class="op">=</span> gtk_notebook_get_nth_page <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">),</span> i<span class="op">);</span></span>
|
||||
<span id="cb4-18"><a href="#cb4-18"></a> tv <span class="op">=</span> gtk_scrolled_window_get_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">));</span></span>
|
||||
<span id="cb4-19"><a href="#cb4-19"></a> file <span class="op">=</span> tfe_text_view_get_file <span class="op">(</span>TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb4-20"><a href="#cb4-20"></a> tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb4-21"><a href="#cb4-21"></a> gtk_text_buffer_get_bounds <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">);</span></span>
|
||||
<span id="cb4-22"><a href="#cb4-22"></a> contents <span class="op">=</span> gtk_text_buffer_get_text <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">,</span> FALSE<span class="op">);</span></span>
|
||||
<span id="cb4-23"><a href="#cb4-23"></a> <span class="cf">if</span> <span class="op">(!</span> g_file_replace_contents <span class="op">(</span>file<span class="op">,</span> contents<span class="op">,</span> strlen <span class="op">(</span>contents<span class="op">),</span> NULL<span class="op">,</span> TRUE<span class="op">,</span> G_FILE_CREATE_NONE<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">))</span> <span class="op">{</span></span>
|
||||
<span id="cb4-24"><a href="#cb4-24"></a> pathname <span class="op">=</span> g_file_get_path <span class="op">(</span>file<span class="op">);</span></span>
|
||||
<span id="cb4-25"><a href="#cb4-25"></a> g_print <span class="op">(</span><span class="st">"ERROR : Can't save %s."</span><span class="op">,</span> pathname<span class="op">);</span></span>
|
||||
<span id="cb4-26"><a href="#cb4-26"></a> g_free <span class="op">(</span>pathname<span class="op">);</span></span>
|
||||
<span id="cb4-27"><a href="#cb4-27"></a> <span class="op">}</span></span>
|
||||
<span id="cb4-28"><a href="#cb4-28"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span>
|
||||
<span id="cb4-29"><a href="#cb4-29"></a> <span class="op">}</span></span>
|
||||
<span id="cb4-30"><a href="#cb4-30"></a> <span class="cf">return</span> FALSE<span class="op">;</span></span>
|
||||
<span id="cb4-31"><a href="#cb4-31"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>The numbers on the left of items are line numbers in the source
|
||||
code.</p>
|
||||
<ul>
|
||||
<li>15: Gets the number of pages <code>nb</code> has.</li>
|
||||
<li>16-29: For loop with regard to the index to each pages.</li>
|
||||
<li>17-19: Gets GtkScrolledWindow, TfeTextView and a pointer to GFile. The pointer was stored when <code>app_open</code> handler had run. It will be shown later.</li>
|
||||
<li>20-22: Gets GtkTextBuffer and contents. <code>start_iter</code> and <code>end_iter</code> are iterators of the buffer. I don’t want to explain them now because it would take a lot of time. Just remember these lines for the present.</li>
|
||||
<li>23-27: Writes the contents to the file. If it fails, it outputs an error message.</li>
|
||||
<li>17-19: Gets GtkScrolledWindow, TfeTextView and a pointer to GFile.
|
||||
The pointer was stored when <code>app_open</code> handler had run. It
|
||||
will be shown later.</li>
|
||||
<li>20-22: Gets GtkTextBuffer and contents. <code>start_iter</code> and
|
||||
<code>end_iter</code> are iterators of the buffer. I don’t want to
|
||||
explain them now because it would take a lot of time. Just remember
|
||||
these lines for the present.</li>
|
||||
<li>23-27: Writes the contents to the file. If it fails, it outputs an
|
||||
error message.</li>
|
||||
<li>28: Frees <code>contents</code>.</li>
|
||||
</ul>
|
||||
<h2 id="source-code-of-tfe1.c">Source code of tfe1.c</h2>
|
||||
<p>The following is the complete source code of <code>tfe1.c</code>.</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<div class="sourceCode" id="cb5"><pre
|
||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||||
<span id="cb5-2"><a href="#cb5-2"></a></span>
|
||||
<span id="cb5-3"><a href="#cb5-3"></a><span class="co">/* Define TfeTextView Widget which is the child object of GtkTextView */</span></span>
|
||||
<span id="cb5-4"><a href="#cb5-4"></a></span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a><span class="pp">#define TFE_TYPE_TEXT_VIEW tfe_text_view_get_type ()</span></span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a>G_DECLARE_FINAL_TYPE (TfeTextView, tfe_text_view, TFE, TEXT_VIEW, GtkTextView)</span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfeTextView<span class="op">,</span> tfe_text_view<span class="op">,</span> TFE<span class="op">,</span> TEXT_VIEW<span class="op">,</span> GtkTextView<span class="op">)</span></span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a></span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a><span class="kw">struct</span> _TfeTextView</span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></a>{</span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a> GtkTextView parent;</span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> GFile *file;</span>
|
||||
<span id="cb5-12"><a href="#cb5-12"></a>};</span>
|
||||
<span id="cb5-9"><a href="#cb5-9"></a><span class="op">{</span></span>
|
||||
<span id="cb5-10"><a href="#cb5-10"></a> GtkTextView parent<span class="op">;</span></span>
|
||||
<span id="cb5-11"><a href="#cb5-11"></a> GFile <span class="op">*</span>file<span class="op">;</span></span>
|
||||
<span id="cb5-12"><a href="#cb5-12"></a><span class="op">};</span></span>
|
||||
<span id="cb5-13"><a href="#cb5-13"></a></span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a>G_DEFINE_TYPE (TfeTextView, tfe_text_view, GTK_TYPE_TEXT_VIEW);</span>
|
||||
<span id="cb5-14"><a href="#cb5-14"></a>G_DEFINE_TYPE <span class="op">(</span>TfeTextView<span class="op">,</span> tfe_text_view<span class="op">,</span> GTK_TYPE_TEXT_VIEW<span class="op">);</span></span>
|
||||
<span id="cb5-15"><a href="#cb5-15"></a></span>
|
||||
<span id="cb5-16"><a href="#cb5-16"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb5-17"><a href="#cb5-17"></a>tfe_text_view_init (TfeTextView *tv) {</span>
|
||||
<span id="cb5-18"><a href="#cb5-18"></a>}</span>
|
||||
<span id="cb5-17"><a href="#cb5-17"></a>tfe_text_view_init <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-18"><a href="#cb5-18"></a><span class="op">}</span></span>
|
||||
<span id="cb5-19"><a href="#cb5-19"></a></span>
|
||||
<span id="cb5-20"><a href="#cb5-20"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb5-21"><a href="#cb5-21"></a>tfe_text_view_class_init (TfeTextViewClass *class) {</span>
|
||||
<span id="cb5-22"><a href="#cb5-22"></a>}</span>
|
||||
<span id="cb5-21"><a href="#cb5-21"></a>tfe_text_view_class_init <span class="op">(</span>TfeTextViewClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-22"><a href="#cb5-22"></a><span class="op">}</span></span>
|
||||
<span id="cb5-23"><a href="#cb5-23"></a></span>
|
||||
<span id="cb5-24"><a href="#cb5-24"></a><span class="dt">void</span></span>
|
||||
<span id="cb5-25"><a href="#cb5-25"></a>tfe_text_view_set_file (TfeTextView *tv, GFile *f) {</span>
|
||||
<span id="cb5-26"><a href="#cb5-26"></a> tv -> file = f;</span>
|
||||
<span id="cb5-27"><a href="#cb5-27"></a>}</span>
|
||||
<span id="cb5-25"><a href="#cb5-25"></a>tfe_text_view_set_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">,</span> GFile <span class="op">*</span>f<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-26"><a href="#cb5-26"></a> tv <span class="op">-></span> file <span class="op">=</span> f<span class="op">;</span></span>
|
||||
<span id="cb5-27"><a href="#cb5-27"></a><span class="op">}</span></span>
|
||||
<span id="cb5-28"><a href="#cb5-28"></a></span>
|
||||
<span id="cb5-29"><a href="#cb5-29"></a>GFile *</span>
|
||||
<span id="cb5-30"><a href="#cb5-30"></a>tfe_text_view_get_file (TfeTextView *tv) {</span>
|
||||
<span id="cb5-31"><a href="#cb5-31"></a> <span class="cf">return</span> tv -> file;</span>
|
||||
<span id="cb5-32"><a href="#cb5-32"></a>}</span>
|
||||
<span id="cb5-29"><a href="#cb5-29"></a>GFile <span class="op">*</span></span>
|
||||
<span id="cb5-30"><a href="#cb5-30"></a>tfe_text_view_get_file <span class="op">(</span>TfeTextView <span class="op">*</span>tv<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-31"><a href="#cb5-31"></a> <span class="cf">return</span> tv <span class="op">-></span> file<span class="op">;</span></span>
|
||||
<span id="cb5-32"><a href="#cb5-32"></a><span class="op">}</span></span>
|
||||
<span id="cb5-33"><a href="#cb5-33"></a></span>
|
||||
<span id="cb5-34"><a href="#cb5-34"></a>GtkWidget *</span>
|
||||
<span id="cb5-35"><a href="#cb5-35"></a>tfe_text_view_new (<span class="dt">void</span>) {</span>
|
||||
<span id="cb5-36"><a href="#cb5-36"></a> <span class="cf">return</span> GTK_WIDGET (g_object_new (TFE_TYPE_TEXT_VIEW, NULL));</span>
|
||||
<span id="cb5-37"><a href="#cb5-37"></a>}</span>
|
||||
<span id="cb5-34"><a href="#cb5-34"></a>GtkWidget <span class="op">*</span></span>
|
||||
<span id="cb5-35"><a href="#cb5-35"></a>tfe_text_view_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-36"><a href="#cb5-36"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_TEXT_VIEW<span class="op">,</span> NULL<span class="op">));</span></span>
|
||||
<span id="cb5-37"><a href="#cb5-37"></a><span class="op">}</span></span>
|
||||
<span id="cb5-38"><a href="#cb5-38"></a></span>
|
||||
<span id="cb5-39"><a href="#cb5-39"></a><span class="co">/* ---------- end of the definition of TfeTextView ---------- */</span></span>
|
||||
<span id="cb5-40"><a href="#cb5-40"></a></span>
|
||||
<span id="cb5-41"><a href="#cb5-41"></a><span class="dt">static</span> gboolean</span>
|
||||
<span id="cb5-42"><a href="#cb5-42"></a>before_close (GtkWindow *win, gpointer user_data) {</span>
|
||||
<span id="cb5-43"><a href="#cb5-43"></a> GtkWidget *nb = GTK_WIDGET (user_data);</span>
|
||||
<span id="cb5-44"><a href="#cb5-44"></a> GtkWidget *scr;</span>
|
||||
<span id="cb5-45"><a href="#cb5-45"></a> GtkWidget *tv;</span>
|
||||
<span id="cb5-46"><a href="#cb5-46"></a> GFile *file;</span>
|
||||
<span id="cb5-47"><a href="#cb5-47"></a> <span class="dt">char</span> *pathname;</span>
|
||||
<span id="cb5-48"><a href="#cb5-48"></a> GtkTextBuffer *tb;</span>
|
||||
<span id="cb5-49"><a href="#cb5-49"></a> GtkTextIter start_iter;</span>
|
||||
<span id="cb5-50"><a href="#cb5-50"></a> GtkTextIter end_iter;</span>
|
||||
<span id="cb5-51"><a href="#cb5-51"></a> <span class="dt">char</span> *contents;</span>
|
||||
<span id="cb5-52"><a href="#cb5-52"></a> <span class="dt">unsigned</span> <span class="dt">int</span> n;</span>
|
||||
<span id="cb5-53"><a href="#cb5-53"></a> <span class="dt">unsigned</span> <span class="dt">int</span> i;</span>
|
||||
<span id="cb5-42"><a href="#cb5-42"></a>before_close <span class="op">(</span>GtkWindow <span class="op">*</span>win<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-43"><a href="#cb5-43"></a> GtkWidget <span class="op">*</span>nb <span class="op">=</span> GTK_WIDGET <span class="op">(</span>user_data<span class="op">);</span></span>
|
||||
<span id="cb5-44"><a href="#cb5-44"></a> GtkWidget <span class="op">*</span>scr<span class="op">;</span></span>
|
||||
<span id="cb5-45"><a href="#cb5-45"></a> GtkWidget <span class="op">*</span>tv<span class="op">;</span></span>
|
||||
<span id="cb5-46"><a href="#cb5-46"></a> GFile <span class="op">*</span>file<span class="op">;</span></span>
|
||||
<span id="cb5-47"><a href="#cb5-47"></a> <span class="dt">char</span> <span class="op">*</span>pathname<span class="op">;</span></span>
|
||||
<span id="cb5-48"><a href="#cb5-48"></a> GtkTextBuffer <span class="op">*</span>tb<span class="op">;</span></span>
|
||||
<span id="cb5-49"><a href="#cb5-49"></a> GtkTextIter start_iter<span class="op">;</span></span>
|
||||
<span id="cb5-50"><a href="#cb5-50"></a> GtkTextIter end_iter<span class="op">;</span></span>
|
||||
<span id="cb5-51"><a href="#cb5-51"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span>
|
||||
<span id="cb5-52"><a href="#cb5-52"></a> <span class="dt">unsigned</span> <span class="dt">int</span> n<span class="op">;</span></span>
|
||||
<span id="cb5-53"><a href="#cb5-53"></a> <span class="dt">unsigned</span> <span class="dt">int</span> i<span class="op">;</span></span>
|
||||
<span id="cb5-54"><a href="#cb5-54"></a></span>
|
||||
<span id="cb5-55"><a href="#cb5-55"></a> n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb));</span>
|
||||
<span id="cb5-56"><a href="#cb5-56"></a> <span class="cf">for</span> (i = <span class="dv">0</span>; i < n; ++i) {</span>
|
||||
<span id="cb5-57"><a href="#cb5-57"></a> scr = gtk_notebook_get_nth_page (GTK_NOTEBOOK (nb), i);</span>
|
||||
<span id="cb5-58"><a href="#cb5-58"></a> tv = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (scr));</span>
|
||||
<span id="cb5-59"><a href="#cb5-59"></a> file = tfe_text_view_get_file (TFE_TEXT_VIEW (tv));</span>
|
||||
<span id="cb5-60"><a href="#cb5-60"></a> tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
|
||||
<span id="cb5-61"><a href="#cb5-61"></a> gtk_text_buffer_get_bounds (tb, &start_iter, &end_iter);</span>
|
||||
<span id="cb5-62"><a href="#cb5-62"></a> contents = gtk_text_buffer_get_text (tb, &start_iter, &end_iter, FALSE);</span>
|
||||
<span id="cb5-63"><a href="#cb5-63"></a> <span class="cf">if</span> (! g_file_replace_contents (file, contents, strlen (contents), NULL, TRUE, G_FILE_CREATE_NONE, NULL, NULL, NULL)) {</span>
|
||||
<span id="cb5-64"><a href="#cb5-64"></a> pathname = g_file_get_path (file);</span>
|
||||
<span id="cb5-65"><a href="#cb5-65"></a> g_print (<span class="st">"ERROR : Can't save %s."</span>, pathname);</span>
|
||||
<span id="cb5-66"><a href="#cb5-66"></a> g_free (pathname);</span>
|
||||
<span id="cb5-67"><a href="#cb5-67"></a> }</span>
|
||||
<span id="cb5-68"><a href="#cb5-68"></a> g_free (contents);</span>
|
||||
<span id="cb5-69"><a href="#cb5-69"></a> }</span>
|
||||
<span id="cb5-70"><a href="#cb5-70"></a> <span class="cf">return</span> FALSE;</span>
|
||||
<span id="cb5-71"><a href="#cb5-71"></a>}</span>
|
||||
<span id="cb5-55"><a href="#cb5-55"></a> n <span class="op">=</span> gtk_notebook_get_n_pages <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">));</span></span>
|
||||
<span id="cb5-56"><a href="#cb5-56"></a> <span class="cf">for</span> <span class="op">(</span>i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> n<span class="op">;</span> <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-57"><a href="#cb5-57"></a> scr <span class="op">=</span> gtk_notebook_get_nth_page <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">),</span> i<span class="op">);</span></span>
|
||||
<span id="cb5-58"><a href="#cb5-58"></a> tv <span class="op">=</span> gtk_scrolled_window_get_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">));</span></span>
|
||||
<span id="cb5-59"><a href="#cb5-59"></a> file <span class="op">=</span> tfe_text_view_get_file <span class="op">(</span>TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb5-60"><a href="#cb5-60"></a> tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb5-61"><a href="#cb5-61"></a> gtk_text_buffer_get_bounds <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">);</span></span>
|
||||
<span id="cb5-62"><a href="#cb5-62"></a> contents <span class="op">=</span> gtk_text_buffer_get_text <span class="op">(</span>tb<span class="op">,</span> <span class="op">&</span>start_iter<span class="op">,</span> <span class="op">&</span>end_iter<span class="op">,</span> FALSE<span class="op">);</span></span>
|
||||
<span id="cb5-63"><a href="#cb5-63"></a> <span class="cf">if</span> <span class="op">(!</span> g_file_replace_contents <span class="op">(</span>file<span class="op">,</span> contents<span class="op">,</span> strlen <span class="op">(</span>contents<span class="op">),</span> NULL<span class="op">,</span> TRUE<span class="op">,</span> G_FILE_CREATE_NONE<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">))</span> <span class="op">{</span></span>
|
||||
<span id="cb5-64"><a href="#cb5-64"></a> pathname <span class="op">=</span> g_file_get_path <span class="op">(</span>file<span class="op">);</span></span>
|
||||
<span id="cb5-65"><a href="#cb5-65"></a> g_print <span class="op">(</span><span class="st">"ERROR : Can't save %s."</span><span class="op">,</span> pathname<span class="op">);</span></span>
|
||||
<span id="cb5-66"><a href="#cb5-66"></a> g_free <span class="op">(</span>pathname<span class="op">);</span></span>
|
||||
<span id="cb5-67"><a href="#cb5-67"></a> <span class="op">}</span></span>
|
||||
<span id="cb5-68"><a href="#cb5-68"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span>
|
||||
<span id="cb5-69"><a href="#cb5-69"></a> <span class="op">}</span></span>
|
||||
<span id="cb5-70"><a href="#cb5-70"></a> <span class="cf">return</span> FALSE<span class="op">;</span></span>
|
||||
<span id="cb5-71"><a href="#cb5-71"></a><span class="op">}</span></span>
|
||||
<span id="cb5-72"><a href="#cb5-72"></a></span>
|
||||
<span id="cb5-73"><a href="#cb5-73"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb5-74"><a href="#cb5-74"></a>app_activate (GApplication *app, gpointer user_data) {</span>
|
||||
<span id="cb5-75"><a href="#cb5-75"></a> g_print (<span class="st">"You need to give filenames as arguments.</span><span class="sc">\n</span><span class="st">"</span>);</span>
|
||||
<span id="cb5-76"><a href="#cb5-76"></a>}</span>
|
||||
<span id="cb5-74"><a href="#cb5-74"></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="cb5-75"><a href="#cb5-75"></a> g_print <span class="op">(</span><span class="st">"You need to give filenames as arguments.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||
<span id="cb5-76"><a href="#cb5-76"></a><span class="op">}</span></span>
|
||||
<span id="cb5-77"><a href="#cb5-77"></a></span>
|
||||
<span id="cb5-78"><a href="#cb5-78"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||
<span id="cb5-79"><a href="#cb5-79"></a>app_open (GApplication *app, GFile ** files, gint n_files, gchar *hint, gpointer user_data) {</span>
|
||||
<span id="cb5-80"><a href="#cb5-80"></a> GtkWidget *win;</span>
|
||||
<span id="cb5-81"><a href="#cb5-81"></a> GtkWidget *nb;</span>
|
||||
<span id="cb5-82"><a href="#cb5-82"></a> GtkWidget *lab;</span>
|
||||
<span id="cb5-83"><a href="#cb5-83"></a> GtkNotebookPage *nbp;</span>
|
||||
<span id="cb5-84"><a href="#cb5-84"></a> GtkWidget *scr;</span>
|
||||
<span id="cb5-85"><a href="#cb5-85"></a> GtkWidget *tv;</span>
|
||||
<span id="cb5-86"><a href="#cb5-86"></a> GtkTextBuffer *tb;</span>
|
||||
<span id="cb5-87"><a href="#cb5-87"></a> <span class="dt">char</span> *contents;</span>
|
||||
<span id="cb5-88"><a href="#cb5-88"></a> gsize length;</span>
|
||||
<span id="cb5-89"><a href="#cb5-89"></a> <span class="dt">char</span> *filename;</span>
|
||||
<span id="cb5-90"><a href="#cb5-90"></a> <span class="dt">int</span> i;</span>
|
||||
<span id="cb5-79"><a href="#cb5-79"></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="cb5-80"><a href="#cb5-80"></a> GtkWidget <span class="op">*</span>win<span class="op">;</span></span>
|
||||
<span id="cb5-81"><a href="#cb5-81"></a> GtkWidget <span class="op">*</span>nb<span class="op">;</span></span>
|
||||
<span id="cb5-82"><a href="#cb5-82"></a> GtkWidget <span class="op">*</span>lab<span class="op">;</span></span>
|
||||
<span id="cb5-83"><a href="#cb5-83"></a> GtkNotebookPage <span class="op">*</span>nbp<span class="op">;</span></span>
|
||||
<span id="cb5-84"><a href="#cb5-84"></a> GtkWidget <span class="op">*</span>scr<span class="op">;</span></span>
|
||||
<span id="cb5-85"><a href="#cb5-85"></a> GtkWidget <span class="op">*</span>tv<span class="op">;</span></span>
|
||||
<span id="cb5-86"><a href="#cb5-86"></a> GtkTextBuffer <span class="op">*</span>tb<span class="op">;</span></span>
|
||||
<span id="cb5-87"><a href="#cb5-87"></a> <span class="dt">char</span> <span class="op">*</span>contents<span class="op">;</span></span>
|
||||
<span id="cb5-88"><a href="#cb5-88"></a> gsize length<span class="op">;</span></span>
|
||||
<span id="cb5-89"><a href="#cb5-89"></a> <span class="dt">char</span> <span class="op">*</span>filename<span class="op">;</span></span>
|
||||
<span id="cb5-90"><a href="#cb5-90"></a> <span class="dt">int</span> i<span class="op">;</span></span>
|
||||
<span id="cb5-91"><a href="#cb5-91"></a></span>
|
||||
<span id="cb5-92"><a href="#cb5-92"></a> win = gtk_application_window_new (GTK_APPLICATION (app));</span>
|
||||
<span id="cb5-93"><a href="#cb5-93"></a> gtk_window_set_title (GTK_WINDOW (win), <span class="st">"file editor"</span>);</span>
|
||||
<span id="cb5-94"><a href="#cb5-94"></a> gtk_window_maximize (GTK_WINDOW (win));</span>
|
||||
<span id="cb5-92"><a href="#cb5-92"></a> win <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="cb5-93"><a href="#cb5-93"></a> gtk_window_set_title <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> <span class="st">"file editor"</span><span class="op">);</span></span>
|
||||
<span id="cb5-94"><a href="#cb5-94"></a> gtk_window_maximize <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb5-95"><a href="#cb5-95"></a></span>
|
||||
<span id="cb5-96"><a href="#cb5-96"></a> nb = gtk_notebook_new ();</span>
|
||||
<span id="cb5-97"><a href="#cb5-97"></a> gtk_window_set_child (GTK_WINDOW (win), nb);</span>
|
||||
<span id="cb5-96"><a href="#cb5-96"></a> nb <span class="op">=</span> gtk_notebook_new <span class="op">();</span></span>
|
||||
<span id="cb5-97"><a href="#cb5-97"></a> gtk_window_set_child <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">),</span> nb<span class="op">);</span></span>
|
||||
<span id="cb5-98"><a href="#cb5-98"></a></span>
|
||||
<span id="cb5-99"><a href="#cb5-99"></a> <span class="cf">for</span> (i = <span class="dv">0</span>; i < n_files; i++) {</span>
|
||||
<span id="cb5-100"><a href="#cb5-100"></a> <span class="cf">if</span> (g_file_load_contents (files[i], NULL, &contents, &length, NULL, NULL)) {</span>
|
||||
<span id="cb5-101"><a href="#cb5-101"></a> scr = gtk_scrolled_window_new ();</span>
|
||||
<span id="cb5-102"><a href="#cb5-102"></a> tv = tfe_text_view_new ();</span>
|
||||
<span id="cb5-103"><a href="#cb5-103"></a> tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
|
||||
<span id="cb5-104"><a href="#cb5-104"></a> gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);</span>
|
||||
<span id="cb5-105"><a href="#cb5-105"></a> gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);</span>
|
||||
<span id="cb5-99"><a href="#cb5-99"></a> <span class="cf">for</span> <span class="op">(</span>i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> n_files<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-100"><a href="#cb5-100"></a> <span class="cf">if</span> <span class="op">(</span>g_file_load_contents <span class="op">(</span>files<span class="op">[</span>i<span class="op">],</span> NULL<span class="op">,</span> <span class="op">&</span>contents<span class="op">,</span> <span class="op">&</span>length<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">))</span> <span class="op">{</span></span>
|
||||
<span id="cb5-101"><a href="#cb5-101"></a> scr <span class="op">=</span> gtk_scrolled_window_new <span class="op">();</span></span>
|
||||
<span id="cb5-102"><a href="#cb5-102"></a> tv <span class="op">=</span> tfe_text_view_new <span class="op">();</span></span>
|
||||
<span id="cb5-103"><a href="#cb5-103"></a> tb <span class="op">=</span> gtk_text_view_get_buffer <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">));</span></span>
|
||||
<span id="cb5-104"><a href="#cb5-104"></a> gtk_text_view_set_wrap_mode <span class="op">(</span>GTK_TEXT_VIEW <span class="op">(</span>tv<span class="op">),</span> GTK_WRAP_WORD_CHAR<span class="op">);</span></span>
|
||||
<span id="cb5-105"><a href="#cb5-105"></a> gtk_scrolled_window_set_child <span class="op">(</span>GTK_SCROLLED_WINDOW <span class="op">(</span>scr<span class="op">),</span> tv<span class="op">);</span></span>
|
||||
<span id="cb5-106"><a href="#cb5-106"></a></span>
|
||||
<span id="cb5-107"><a href="#cb5-107"></a> tfe_text_view_set_file (TFE_TEXT_VIEW (tv), g_file_dup (files[i]));</span>
|
||||
<span id="cb5-108"><a href="#cb5-108"></a> gtk_text_buffer_set_text (tb, contents, length);</span>
|
||||
<span id="cb5-109"><a href="#cb5-109"></a> g_free (contents);</span>
|
||||
<span id="cb5-110"><a href="#cb5-110"></a> filename = g_file_get_basename (files[i]);</span>
|
||||
<span id="cb5-111"><a href="#cb5-111"></a> lab = gtk_label_new (filename);</span>
|
||||
<span id="cb5-112"><a href="#cb5-112"></a> gtk_notebook_append_page (GTK_NOTEBOOK (nb), scr, lab);</span>
|
||||
<span id="cb5-113"><a href="#cb5-113"></a> nbp = gtk_notebook_get_page (GTK_NOTEBOOK (nb), scr);</span>
|
||||
<span id="cb5-114"><a href="#cb5-114"></a> g_object_set (nbp, <span class="st">"tab-expand"</span>, TRUE, NULL);</span>
|
||||
<span id="cb5-115"><a href="#cb5-115"></a> g_free (filename);</span>
|
||||
<span id="cb5-116"><a href="#cb5-116"></a> } <span class="cf">else</span> <span class="cf">if</span> ((filename = g_file_get_path (files[i])) != NULL) {</span>
|
||||
<span id="cb5-117"><a href="#cb5-117"></a> g_print (<span class="st">"No such file: %s.</span><span class="sc">\n</span><span class="st">"</span>, filename);</span>
|
||||
<span id="cb5-118"><a href="#cb5-118"></a> g_free (filename);</span>
|
||||
<span id="cb5-119"><a href="#cb5-119"></a> } <span class="cf">else</span></span>
|
||||
<span id="cb5-120"><a href="#cb5-120"></a> g_print (<span class="st">"No valid file is given</span><span class="sc">\n</span><span class="st">"</span>);</span>
|
||||
<span id="cb5-121"><a href="#cb5-121"></a> }</span>
|
||||
<span id="cb5-122"><a href="#cb5-122"></a> <span class="cf">if</span> (gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb)) > <span class="dv">0</span>) {</span>
|
||||
<span id="cb5-123"><a href="#cb5-123"></a> g_signal_connect (win, <span class="st">"close-request"</span>, G_CALLBACK (before_close), nb);</span>
|
||||
<span id="cb5-124"><a href="#cb5-124"></a> gtk_widget_show (win);</span>
|
||||
<span id="cb5-125"><a href="#cb5-125"></a> } <span class="cf">else</span></span>
|
||||
<span id="cb5-126"><a href="#cb5-126"></a> gtk_window_destroy (GTK_WINDOW (win));</span>
|
||||
<span id="cb5-127"><a href="#cb5-127"></a>}</span>
|
||||
<span id="cb5-107"><a href="#cb5-107"></a> tfe_text_view_set_file <span class="op">(</span>TFE_TEXT_VIEW <span class="op">(</span>tv<span class="op">),</span> g_file_dup <span class="op">(</span>files<span class="op">[</span>i<span class="op">]));</span></span>
|
||||
<span id="cb5-108"><a href="#cb5-108"></a> gtk_text_buffer_set_text <span class="op">(</span>tb<span class="op">,</span> contents<span class="op">,</span> length<span class="op">);</span></span>
|
||||
<span id="cb5-109"><a href="#cb5-109"></a> g_free <span class="op">(</span>contents<span class="op">);</span></span>
|
||||
<span id="cb5-110"><a href="#cb5-110"></a> filename <span class="op">=</span> g_file_get_basename <span class="op">(</span>files<span class="op">[</span>i<span class="op">]);</span></span>
|
||||
<span id="cb5-111"><a href="#cb5-111"></a> lab <span class="op">=</span> gtk_label_new <span class="op">(</span>filename<span class="op">);</span></span>
|
||||
<span id="cb5-112"><a href="#cb5-112"></a> gtk_notebook_append_page <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">),</span> scr<span class="op">,</span> lab<span class="op">);</span></span>
|
||||
<span id="cb5-113"><a href="#cb5-113"></a> nbp <span class="op">=</span> gtk_notebook_get_page <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">),</span> scr<span class="op">);</span></span>
|
||||
<span id="cb5-114"><a href="#cb5-114"></a> g_object_set <span class="op">(</span>nbp<span class="op">,</span> <span class="st">"tab-expand"</span><span class="op">,</span> TRUE<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||
<span id="cb5-115"><a href="#cb5-115"></a> g_free <span class="op">(</span>filename<span class="op">);</span></span>
|
||||
<span id="cb5-116"><a href="#cb5-116"></a> <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">((</span>filename <span class="op">=</span> g_file_get_path <span class="op">(</span>files<span class="op">[</span>i<span class="op">]))</span> <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-117"><a href="#cb5-117"></a> g_print <span class="op">(</span><span class="st">"No such file: %s.</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> filename<span class="op">);</span></span>
|
||||
<span id="cb5-118"><a href="#cb5-118"></a> g_free <span class="op">(</span>filename<span class="op">);</span></span>
|
||||
<span id="cb5-119"><a href="#cb5-119"></a> <span class="op">}</span> <span class="cf">else</span></span>
|
||||
<span id="cb5-120"><a href="#cb5-120"></a> g_print <span class="op">(</span><span class="st">"No valid file is given</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||||
<span id="cb5-121"><a href="#cb5-121"></a> <span class="op">}</span></span>
|
||||
<span id="cb5-122"><a href="#cb5-122"></a> <span class="cf">if</span> <span class="op">(</span>gtk_notebook_get_n_pages <span class="op">(</span>GTK_NOTEBOOK <span class="op">(</span>nb<span class="op">))</span> <span class="op">></span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
|
||||
<span id="cb5-123"><a href="#cb5-123"></a> g_signal_connect <span class="op">(</span>win<span class="op">,</span> <span class="st">"close-request"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>before_close<span class="op">),</span> nb<span class="op">);</span></span>
|
||||
<span id="cb5-124"><a href="#cb5-124"></a> gtk_widget_show <span class="op">(</span>win<span class="op">);</span></span>
|
||||
<span id="cb5-125"><a href="#cb5-125"></a> <span class="op">}</span> <span class="cf">else</span></span>
|
||||
<span id="cb5-126"><a href="#cb5-126"></a> gtk_window_destroy <span class="op">(</span>GTK_WINDOW <span class="op">(</span>win<span class="op">));</span></span>
|
||||
<span id="cb5-127"><a href="#cb5-127"></a><span class="op">}</span></span>
|
||||
<span id="cb5-128"><a href="#cb5-128"></a></span>
|
||||
<span id="cb5-129"><a href="#cb5-129"></a><span class="dt">int</span></span>
|
||||
<span id="cb5-130"><a href="#cb5-130"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
|
||||
<span id="cb5-131"><a href="#cb5-131"></a> GtkApplication *app;</span>
|
||||
<span id="cb5-132"><a href="#cb5-132"></a> <span class="dt">int</span> stat;</span>
|
||||
<span id="cb5-130"><a href="#cb5-130"></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="cb5-131"><a href="#cb5-131"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||||
<span id="cb5-132"><a href="#cb5-132"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||||
<span id="cb5-133"><a href="#cb5-133"></a></span>
|
||||
<span id="cb5-134"><a href="#cb5-134"></a> app = gtk_application_new (<span class="st">"com.github.ToshioCP.tfe1"</span>, G_APPLICATION_HANDLES_OPEN);</span>
|
||||
<span id="cb5-135"><a href="#cb5-135"></a> g_signal_connect (app, <span class="st">"activate"</span>, G_CALLBACK (app_activate), NULL);</span>
|
||||
<span id="cb5-136"><a href="#cb5-136"></a> g_signal_connect (app, <span class="st">"open"</span>, G_CALLBACK (app_open), NULL);</span>
|
||||
<span id="cb5-137"><a href="#cb5-137"></a> stat =g_application_run (G_APPLICATION (app), argc, argv);</span>
|
||||
<span id="cb5-138"><a href="#cb5-138"></a> g_object_unref (app);</span>
|
||||
<span id="cb5-139"><a href="#cb5-139"></a> <span class="cf">return</span> stat;</span>
|
||||
<span id="cb5-140"><a href="#cb5-140"></a>}</span></code></pre></div>
|
||||
<span id="cb5-134"><a href="#cb5-134"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span><span class="st">"com.github.ToshioCP.tfe1"</span><span class="op">,</span> G_APPLICATION_HANDLES_OPEN<span class="op">);</span></span>
|
||||
<span id="cb5-135"><a href="#cb5-135"></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="cb5-136"><a href="#cb5-136"></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="cb5-137"><a href="#cb5-137"></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="cb5-138"><a href="#cb5-138"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||||
<span id="cb5-139"><a href="#cb5-139"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||||
<span id="cb5-140"><a href="#cb5-140"></a><span class="op">}</span></span></code></pre></div>
|
||||
<ul>
|
||||
<li>107: Sets the pointer to GFile into TfeTextView. <code>files[i]</code> is a pointer to GFile structure. It will be freed by the system. So you need to copy it. <code>g_file_dup</code> duplicates the given GFile structure.</li>
|
||||
<li>123: Connects “close-request” signal and <code>before_close</code> handler. The fourth argument is called user data and it is given to the signal handler. So, <code>nb</code> is given to <code>before_close</code> as the second argument.</li>
|
||||
<li>107: Sets the pointer to GFile into TfeTextView.
|
||||
<code>files[i]</code> is a pointer to GFile structure. It will be freed
|
||||
by the system. So you need to copy it. <code>g_file_dup</code>
|
||||
duplicates the given GFile structure.</li>
|
||||
<li>123: Connects “close-request” signal and <code>before_close</code>
|
||||
handler. The fourth argument is called user data and it is given to the
|
||||
signal handler. So, <code>nb</code> is given to
|
||||
<code>before_close</code> as the second argument.</li>
|
||||
</ul>
|
||||
<p>Now compile and run it. There’s a sample file in the directory <code>tfe</code>. Type <code>./a.out taketori.txt</code>. Modify the contents and close the window. Make sure that the file is modified.</p>
|
||||
<p>Now we got a very simple editor. It’s not smart. We need more features like open, save, saveas, change font and so on. We will add them in the next section and after.</p>
|
||||
<p>Now compile and run it. There’s a sample file in the directory
|
||||
<code>tfe</code>. Type <code>./a.out taketori.txt</code>. Modify the
|
||||
contents and close the window. Make sure that the file is modified.</p>
|
||||
<p>Now we got a very simple editor. It’s not smart. We need more
|
||||
features like open, save, saveas, change font and so on. We will add
|
||||
them in the next section and after.</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>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# How to build Gtk4 Tutorial
|
||||
# How to build Gtk4-Tutorial
|
||||
|
||||
## Quick start guide
|
||||
|
||||
|
@ -24,16 +24,16 @@ Then, click "Download ZIP".
|
|||
- Latex system. Texlive2020 or later version is recommended.
|
||||
It is used to generate the pdf file.
|
||||
|
||||
## Github flavored markdown
|
||||
## GitHub Flavored Markdown
|
||||
|
||||
When you see [gtk4_tutorial github repository](https://github.com/ToshioCP/Gtk4-tutorial), you'll find the contents of the `Readme.md` file.
|
||||
When you see [gtk4_tutorial GitHub repository](https://github.com/ToshioCP/Gtk4-tutorial), you'll find the contents of the `Readme.md` file.
|
||||
This file is written in markdown language.
|
||||
Markdown files have `.md` suffix.
|
||||
|
||||
There are several kinds of markdown language.
|
||||
`Readme.md` uses 'github flavored markdown', which is often shortened as GFM.
|
||||
`Readme.md` uses 'GitHub Flavored Markdown', which is often shortened as GFM.
|
||||
Markdown files in the `gfm` directory are written in GFM.
|
||||
If you are not familiar with it, refer to the page [github flavor markdown spec](https://github.github.com/gfm/).
|
||||
If you are not familiar with it, refer to the page [GitHub Flavor Markdown spec](https://github.github.com/gfm/).
|
||||
|
||||
## Pandoc's markdown
|
||||
|
||||
|
@ -435,7 +435,7 @@ Because the navigation of the previous section of the newly added section needs
|
|||
If you don't do `rake clobber`, then it won't be updated because the the timestamp of .md file in gfm is newer than the one of .src.md file.
|
||||
In this case, using `touch` to the previous section .src.md also works to update the file.
|
||||
|
||||
If you see the github repository (ToshioCP/Gtk4-tutorial), `Readme.md` is shown below the code.
|
||||
If you see the GitHub repository (ToshioCP/Gtk4-tutorial), `Readme.md` is shown below the code.
|
||||
And `Readme.md` includes links to each markdown files.
|
||||
The repository not only stores source files but also shows the whole tutorial.
|
||||
|
||||
|
@ -475,7 +475,7 @@ Rake uses `lib/lib_mk_html_template.rb` to create its own template.
|
|||
The template inserts bootstrap CSS and Javascript through `jsDelivr`.
|
||||
|
||||
The `docs` directory contains all the necessary html files.
|
||||
They are used in the [github pages](https://ToshioCP.github.io/Gtk4-tutorial) of this repository.
|
||||
They are used in the [GitHub pages](https://ToshioCP.github.io/Gtk4-tutorial) of this repository.
|
||||
|
||||
So if you want to publish this tutorial on your own web site, just upload the files in the `docs` directory to your site.
|
||||
|
||||
|
|
24
gfm/sec1.md
24
gfm/sec1.md
|
@ -1,12 +1,12 @@
|
|||
Up: [Readme.md](../Readme.md), Next: [Section 2](sec2.md)
|
||||
Up: [README.md](../README.md), Next: [Section 2](sec2.md)
|
||||
|
||||
# Prerequisite and License
|
||||
|
||||
## Prerequisite
|
||||
|
||||
### Gtk4 on a Linux OS
|
||||
### GTK 4 on a Linux OS
|
||||
|
||||
This tutorial is about Gtk4 libraries.
|
||||
This tutorial is about GTK 4 libraries.
|
||||
It is originally used on Linux with C compiler, but now it is used more widely, on Windows and MacOS, with Vala, Python and so on.
|
||||
However, this tutorial describes only _C programs on Linux_.
|
||||
|
||||
|
@ -14,10 +14,10 @@ If you want to try the examples in the tutorial, you need:
|
|||
|
||||
- PC with Linux distribution like Ubuntu, Debian and so on.
|
||||
- Gcc.
|
||||
- Gtk4.
|
||||
- GTK 4.
|
||||
The stable version of Gtk on Linux distributions is version three at present.
|
||||
You need to install Gtk4 to your computer.
|
||||
See [Section 3](sec3.md) for the installation of Gtk4.
|
||||
You need to install GTK 4 to your computer.
|
||||
See [Section 3](sec3.md) for the installation of GTK 4.
|
||||
|
||||
### Ruby and rake for making the document
|
||||
|
||||
|
@ -40,13 +40,13 @@ You can install it as a package of your distribution or use gem command.
|
|||
|
||||
Copyright (C) 2020 ToshioCP (Toshio Sekiya)
|
||||
|
||||
Gtk4 tutorial repository contains the tutorial document and software such as converters, generators and controllers.
|
||||
All of them make up the 'Gtk4 tutorial' package.
|
||||
This package is simply called 'Gtk4 tutorial' in the following description.
|
||||
'Gtk4 tutorial' is free; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License or, at your option, any later version.
|
||||
Gtk4-tutorial repository contains the tutorial document and software such as converters, generators and controllers.
|
||||
All of them make up the 'Gtk4-tutorial' package.
|
||||
This package is simply called 'Gtk4-tutorial' in the following description.
|
||||
'Gtk4-tutorial' is free; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License or, at your option, any later version.
|
||||
|
||||
'Gtk4 tutorial' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
'Gtk4-tutorial' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the [GNU General Public License](https://www.gnu.org/licenses/gpl-3.0.html) for more details.
|
||||
|
||||
|
||||
Up: [Readme.md](../Readme.md), Next: [Section 2](sec2.md)
|
||||
Up: [README.md](../README.md), Next: [Section 2](sec2.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 12](sec12.md), Next: [Section 14](sec14.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 12](sec12.md), Next: [Section 14](sec14.md)
|
||||
|
||||
# Functions in TfeTextView
|
||||
|
||||
|
@ -406,9 +406,9 @@ Then, it emits "open-response" signal with the parameter `TFE_OPEN_RESPONSE_SUCC
|
|||
Now let's think about the whole process between the caller and TfeTextView.
|
||||
It is shown in the following diagram and you would think that it is really complicated.
|
||||
Because signal is the only way for GtkFileChooserDialog to communicate with others.
|
||||
In Gtk3, `gtk_dialog_run` function is available.
|
||||
In GTK 3, `gtk_dialog_run` function is available.
|
||||
It simplifies the process.
|
||||
However, in Gtk4, `gtk_dialog_run` is unavailable any more.
|
||||
However, in GTK 4, `gtk_dialog_run` is unavailable any more.
|
||||
|
||||
![Caller and TfeTextView](../image/open.png)
|
||||
|
||||
|
@ -450,4 +450,4 @@ All the source files are listed in [Section 16](sec16.md).
|
|||
You can find them under [src/tfe5](../src/tfe5) and [src/tfetextview](../src/tfetextview) directories.
|
||||
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 12](sec12.md), Next: [Section 14](sec14.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 12](sec12.md), Next: [Section 14](sec14.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 14](sec14.md), Next: [Section 16](sec16.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 14](sec14.md), Next: [Section 16](sec16.md)
|
||||
|
||||
# tfeapplication.c
|
||||
|
||||
|
@ -124,7 +124,7 @@ textview {color: yellow; ...}
|
|||
~~~
|
||||
|
||||
Class, ID and some other things can be applied to the selector like Web CSS.
|
||||
Refer to [Gtk4 API Reference, CSS in Gtk](https://docs.gtk.org/gtk4/css-overview.html) for further information.
|
||||
Refer to [GTK 4 API Reference, CSS in Gtk](https://docs.gtk.org/gtk4/css-overview.html) for further information.
|
||||
|
||||
In line 30, the CSS is a string.
|
||||
|
||||
|
@ -321,4 +321,4 @@ If you use git, run the terminal and type the following.
|
|||
|
||||
The source files are under [/src/tfe5](../src/tfe5) directory.
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 14](sec14.md), Next: [Section 16](sec16.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 14](sec14.md), Next: [Section 16](sec16.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 17](sec17.md), Next: [Section 19](sec19.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 17](sec17.md), Next: [Section 19](sec19.md)
|
||||
|
||||
# Stateful action
|
||||
|
||||
|
@ -381,7 +381,7 @@ Useless GMenuItem are freed.
|
|||
- 79-80: GMenuModel `menubar` is inserted to `app`.
|
||||
Sets show menubar property of `win` to `TRUE`.
|
||||
Note: `gtk_application_window_set_show_menubar` creates GtkPopoverMenubar from GMenuModel.
|
||||
This is a different point between Gtk3 and Gtk4.
|
||||
This is a different point between GTK 3 and GTK 4.
|
||||
And you can use GtkPopoverMenubar directly and set it as a descendant widget of the window.
|
||||
You may use GtkBox as a child widget of the window and insert GtkPopoverMenubar as the first child of the box.
|
||||
- 82-87: Sets CSS.
|
||||
|
@ -400,4 +400,4 @@ The provider is added to GdkDisplay.
|
|||
- 90: Shows the window.
|
||||
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 17](sec17.md), Next: [Section 19](sec19.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 17](sec17.md), Next: [Section 19](sec19.md)
|
||||
|
|
124
gfm/sec2.md
124
gfm/sec2.md
|
@ -1,26 +1,26 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md)
|
||||
|
||||
# Installing Gtk4 into Linux distributions
|
||||
# Installing GTK 4 into Linux distributions
|
||||
|
||||
This section describes how to install Gtk4 into Linux distributions.
|
||||
This section describes how to install GTK 4 into Linux distributions.
|
||||
|
||||
This tutorial is without any warranty.
|
||||
If you want to install Gtk4 to your computer, do it at your own risk.
|
||||
If you want to install GTK 4 to your computer, do it at your own risk.
|
||||
|
||||
The information in this section is the one on April/27/2022.
|
||||
The words 'at present' and/or 'now' in this section means 'April/27/2022'.
|
||||
|
||||
There are three possible way to install Gtk4.
|
||||
There are three possible way to install GTK 4.
|
||||
|
||||
- Install it from the distribution packages.
|
||||
- Build it from the source file.
|
||||
- Install a Gnome 40 distribution with the gnome-boxes.
|
||||
- Install a GNOME 40 distribution with the GNOME Boxes.
|
||||
|
||||
## Installation from the distribution packages
|
||||
|
||||
The first way is easy to install.
|
||||
It is a recommended way.
|
||||
I've installed Gtk4 packages in Ubuntu 21.04.
|
||||
I've installed GTK 4 packages in Ubuntu 21.04.
|
||||
(Now, my Ubuntu version is 21.10).
|
||||
|
||||
~~~
|
||||
|
@ -29,29 +29,29 @@ $ sudo apt-get install libgtk-4-bin libgtk-4-common libgtk-4-dev libgtk-4-doc
|
|||
|
||||
Fedora, Arch, Debian and OpenSUSE are also possible.
|
||||
See [Installing GTK from packages](https://www.gtk.org/docs/installations/linux#installing-gtk-from-packages).
|
||||
The following table shows the distributions which support Gtk4.
|
||||
The following table shows the distributions which support GTK 4.
|
||||
|
||||
|Distribution| version |Gtk4 | Gnome40 |
|
||||
|:----------:|:-------------------------:|:---:|:------------:|
|
||||
| Fedora | 36 |4.4.2| Gnome42 |
|
||||
| Ubuntu | 22.04lts | 4.4 |Gnome41(4.6.2)|
|
||||
| Debian | bookworm(testing) |4.6.5| Gnome42 |
|
||||
| Arch | rolling release |4.6.5| Gnome42 |
|
||||
| Gentoo | rolling release |4.6.5| Gnome42 |
|
||||
| OpenSUSE |Tumbleweed(rolling release)|4.6.5| Gnome42 |
|
||||
|Distribution| version |GTK 4| GNOME 40 |
|
||||
|:----------:|:-------------------------:|:---:|:-------------:|
|
||||
| Fedora | 36 |4.4.2| GNOME 42 |
|
||||
| Ubuntu | 22.04lts | 4.4 |GNOME 41(4.6.2)|
|
||||
| Debian | bookworm(testing) |4.6.5| GNOME 42 |
|
||||
| Arch | rolling release |4.6.5| GNOME 42 |
|
||||
| Gentoo | rolling release |4.6.5| GNOME 42 |
|
||||
| OpenSUSE |Tumbleweed(rolling release)|4.6.5| GNOME 42 |
|
||||
|
||||
If you've installed Gtk4 from the packages, you don't need to read the rest of this section.
|
||||
If you've installed GTK 4 from the packages, you don't need to read the rest of this section.
|
||||
|
||||
## Installation from the source file
|
||||
|
||||
If your operating system doesn't have Gtk4 packages, you need to build it from the source.
|
||||
Or, if you want the latest version of Gtk4 (4.6.3), you also need to build it from the source.
|
||||
If your operating system doesn't have GTK 4 packages, you need to build it from the source.
|
||||
Or, if you want the latest version of GTK 4 (4.6.3), you also need to build it from the source.
|
||||
|
||||
I installed Gtk4 from the source in January 2021.
|
||||
I installed GTK 4 from the source in January 2021.
|
||||
So, the following information is old, especially for the version of each software.
|
||||
For the latest information, see [Gtk API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html).
|
||||
For the latest information, see [GTK API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html).
|
||||
|
||||
### Prerequisites for Gtk4 installation
|
||||
### Prerequisites for GTK 4 installation
|
||||
|
||||
- Linux operating system. For example, Ubuntu 20.10 or 20.04LTS.
|
||||
Other distributions might be OK.
|
||||
|
@ -60,14 +60,14 @@ Other distributions might be OK.
|
|||
|
||||
### Installation target
|
||||
|
||||
I installed Gtk4 under the directory `$HOME/local`.
|
||||
I installed GTK 4 under the directory `$HOME/local`.
|
||||
This is a private user area.
|
||||
|
||||
If you want to install it in the system area, `/opt/gtk4` is one of good choices.
|
||||
[Gtk API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html) gives an installation example to `/opt/gtk4`.
|
||||
[GTK API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html) gives an installation example to `/opt/gtk4`.
|
||||
|
||||
Don't install it to `/usr/local` which is the default.
|
||||
It is used by Ubuntu applications which are not build on Gtk4.
|
||||
It is used by Ubuntu applications which are not build on GTK 4.
|
||||
Therefore, the risk is high and probably bad things will happen.
|
||||
Actually I did it and I needed to reinstall Ubuntu.
|
||||
|
||||
|
@ -76,9 +76,9 @@ Actually I did it and I needed to reinstall Ubuntu.
|
|||
Most of the necessary libraries are included by Ubuntu 20.10.
|
||||
Therefore, they can be installed with `apt-get` command.
|
||||
You don't need to install them from the source tarballs.
|
||||
You can skip the subsections below about prerequisite library installation (Glib, Pango, Gdk-pixbuf and Gtk-doc).
|
||||
You can skip the subsections below about prerequisite library installation (GLib, Pango, GdkPixbuf and GTK-doc).
|
||||
|
||||
### Glib installation
|
||||
### GLib installation
|
||||
|
||||
If your Ubuntu is 20.04LTS, you need to install prerequisite libraries from the tarballs.
|
||||
Check the version of your library and if it is lower than the necessary version, install it from the source.
|
||||
|
@ -91,15 +91,15 @@ $ pkg-config --modversion glib-2.0
|
|||
~~~
|
||||
|
||||
The necessary version is 2.66.0 or higher.
|
||||
Therefore, the example above shows that you need to install Glib.
|
||||
Therefore, the example above shows that you need to install GLib.
|
||||
|
||||
I installed 2.67.1 which was the latest version at that time (January 2021).
|
||||
Download Glib source files from the repository, then decompress and extract files.
|
||||
Download GLib source files from the repository, then decompress and extract files.
|
||||
|
||||
$ wget https://download.gnome.org/sources/glib/2.67/glib-2.67.1.tar.xz
|
||||
$ tar -Jxf glib-2.67.1.tar.xz
|
||||
|
||||
Some packages are required to build Glib.
|
||||
Some packages are required to build GLib.
|
||||
You can find them if you run meson.
|
||||
|
||||
$ meson --prefix $HOME/local _build
|
||||
|
@ -109,14 +109,14 @@ For example,
|
|||
|
||||
$ sudo apt-get install -y libpcre2-dev libffi-dev
|
||||
|
||||
After that, compile Glib.
|
||||
After that, compile GLib.
|
||||
|
||||
$ rm -rf _build
|
||||
$ meson --prefix $HOME/local _build
|
||||
$ ninja -C _build
|
||||
$ ninja -C _build install
|
||||
|
||||
Set several environment variables so that the Glib libraries installed can be used by build tools.
|
||||
Set several environment variables so that the GLib libraries installed can be used by build tools.
|
||||
Make a text file below and save it as `env.sh`
|
||||
|
||||
# compiler
|
||||
|
@ -165,7 +165,7 @@ Now `$HOME/local/share` needs to be added to `XDG_DATA_DIRS`, or error will occu
|
|||
|
||||
$ export XDG_DATA_DIRS=$HOME/local/share:$XDG_DATA_DIRS
|
||||
|
||||
### Gdk-pixbuf and Gtk-doc installation
|
||||
### GdkPixbuf and GTK-Doc installation
|
||||
|
||||
Download and untar.
|
||||
|
||||
|
@ -176,19 +176,19 @@ Download and untar.
|
|||
|
||||
Same as before, install prerequisite packages, then compile and install them.
|
||||
|
||||
The installation of Gtk-doc put `gtk-doc.pc` under `$HOME/local/share/pkgconfig`.
|
||||
The installation of GTK-Doc put `gtk-doc.pc` under `$HOME/local/share/pkgconfig`.
|
||||
This file is used by pkg-config, which is one of the build tools.
|
||||
The directory needs to be added to the environment variable `PKG_CONFIG_PATH`
|
||||
|
||||
$ export PKG_CONFIG_PATH="$HOME/local/share/pkgconfig:$PKG_CONFIG_PATH"
|
||||
|
||||
### Gtk4 installation
|
||||
### GTK 4 installation
|
||||
|
||||
If you want the latest development version of Gtk4, use git and clone the repository.
|
||||
If you want the latest development version of GTK 4, use git and clone the repository.
|
||||
|
||||
$ git clone https://gitlab.gnome.org/GNOME/gtk.git
|
||||
$ git clone https://gitlab.gnome.org/gnome/gtk.git
|
||||
|
||||
If you want a stable version of Gtk4, then download it from [Gnome source website](https://download.gnome.org/sources/gtk/).
|
||||
If you want a stable version of GTK 4, then download it from [GNOME source website](https://download.gnome.org/sources/gtk/).
|
||||
The latest version is 4.3.1 (13/June/2021).
|
||||
|
||||
Compile and install it.
|
||||
|
@ -197,7 +197,7 @@ Compile and install it.
|
|||
$ ninja -C _build
|
||||
$ ninja -C _build install
|
||||
|
||||
If you want to know more information, refer to [Gtk4 API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html).
|
||||
If you want to know more information, refer to [GTK 4 API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html).
|
||||
|
||||
### Modify env.sh
|
||||
|
||||
|
@ -222,18 +222,18 @@ Modify `env.sh`.
|
|||
# girepository-1.0
|
||||
export GI_TYPELIB_PATH=$HOME/local/lib/x86_64-linux-gnu/girepository-1.0
|
||||
|
||||
Include this file by . (dot) command before using Gtk4 libraries.
|
||||
Include this file by . (dot) command before using GTK 4 libraries.
|
||||
|
||||
You may think you can add them in your `.profile`.
|
||||
But it's a wrong decision.
|
||||
Never write them to your `.profile`.
|
||||
The environment variables above are necessary only when you compile and run Gtk4 applications.
|
||||
The environment variables above are necessary only when you compile and run GTK 4 applications.
|
||||
Otherwise it's not necessary.
|
||||
If you changed the environment variables above and run Gtk3 applications, it probably causes serious damage.
|
||||
If you changed the environment variables above and run GTK 3 applications, it probably causes serious damage.
|
||||
|
||||
### Compiling Gtk4 applications
|
||||
### Compiling GTK 4 applications
|
||||
|
||||
Before you compile Gtk4 applications, define environment variables above.
|
||||
Before you compile GTK 4 applications, define environment variables above.
|
||||
|
||||
$ . env.sh
|
||||
|
||||
|
@ -242,20 +242,20 @@ For example, to compile `sample.c`, type the following.
|
|||
|
||||
$ gcc `pkg-config --cflags gtk4` sample.c `pkg-config --libs gtk4`
|
||||
|
||||
To know how to compile Gtk4 applications, refer to the section 3 (GtkApplication and GtkApplicationWindow) and after.
|
||||
To know how to compile GTK 4 applications, refer to the section 3 (GtkApplication and GtkApplicationWindow) and after.
|
||||
|
||||
## Installing Fedora 34 with gnome-boxes
|
||||
## Installing Fedora 34 with GNOME Boxes
|
||||
|
||||
The last part of this section is about Gnome40 and gnome-boxes.
|
||||
Gnome 40 is a new version of Gnome desktop system.
|
||||
And Gtk4 is installed in the distribution.
|
||||
See [Gnome 40 website](https://forty.gnome.org/) first.
|
||||
The last part of this section is about GNOME 40 and GNOME Boxes.
|
||||
GNOME 40 is a new version of GNOME desktop system.
|
||||
And GTK 4 is installed in the distribution.
|
||||
See [GNOME 40 website](https://forty.gnome.org/) first.
|
||||
|
||||
*However, Gnome40 is not necessary to compile and run Gtk4 applications.*
|
||||
*However, GNOME 40 is not necessary to compile and run GTK 4 applications.*
|
||||
|
||||
There are seven choices at present.
|
||||
|
||||
- Gnome OS
|
||||
- GNOME OS
|
||||
- Arch Linux
|
||||
- Gentoo Linux
|
||||
- Fedora 36
|
||||
|
@ -263,19 +263,19 @@ There are seven choices at present.
|
|||
- Ubuntu 22.04
|
||||
- Debian bookworm
|
||||
|
||||
I've installed Fedora 34 with gnome-boxes.
|
||||
I've installed Fedora 34 with GNOME Boxes.
|
||||
My OS was Ubuntu 21.04 at that time.
|
||||
Gnome-boxes creates a virtual machine in Ubuntu and Fedora will be installed to that virtual machine.
|
||||
GNOME Boxes creates a virtual machine in Ubuntu and Fedora will be installed to that virtual machine.
|
||||
|
||||
The instruction is as follows.
|
||||
|
||||
1. Download Fedora 34 iso file.
|
||||
There is an link at the end of [Gnome 40 website](https://forty.gnome.org/).
|
||||
There is an link at the end of [GNOME 40 website](https://forty.gnome.org/).
|
||||
2. Install gnome-boxes with apt-get command.
|
||||
~~~
|
||||
$ sudo apt-get install gnome-boxes
|
||||
~~~
|
||||
3. Run gnome-boxes.
|
||||
3. Run GNOME Boxes.
|
||||
4. Click on `+` button on the top left corner and launch a box creation wizard by clicking `Create a Virtual Machine ...`.
|
||||
Then a dialog appears.
|
||||
Click on `Operationg System Image File` and select the iso file you have downloaded.
|
||||
|
@ -283,23 +283,23 @@ Click on `Operationg System Image File` and select the iso file you have downloa
|
|||
Follow the instructions by the installer.
|
||||
At the end of the installation, the installer instructs to reboot the system.
|
||||
Click on the right of the title bar and select reboot or shutdown.
|
||||
6. Your display is back to the initial window of gnome-boxes, but there is a button `Fedora 34 Workstation` on the upper left of the window.
|
||||
6. Your display is back to the initial window of GNOME Boxes, but there is a button `Fedora 34 Workstation` on the upper left of the window.
|
||||
Click on the button then Fedora will be executed.
|
||||
7. A setup dialog appears.
|
||||
Setup Fedora according to the wizard.
|
||||
|
||||
Now you can use Fedora.
|
||||
It includes Gtk4 libraries already.
|
||||
But you need to install the Gtk4 development package.
|
||||
It includes GTK 4 libraries already.
|
||||
But you need to install the GTK 4 development package.
|
||||
Use `dnf` to install `gtk4.x86_64` package.
|
||||
|
||||
~~~
|
||||
$ sudo dnf install gtk4.x86_64
|
||||
~~~
|
||||
|
||||
### Gtk4 compilation test
|
||||
### GTK 4 compilation test
|
||||
|
||||
You can test the Gtk4 development packages by compiling files which are based on Gtk4.
|
||||
You can test the GTK 4 development packages by compiling files which are based on GTK 4.
|
||||
I've tried compiling `tfe` text editor, which is written in section 21.
|
||||
|
||||
1. Run Firefox.
|
||||
|
@ -371,4 +371,4 @@ $ tfe
|
|||
Then, the window of `tfe` text editor appears.
|
||||
The compilation and execution have succeeded.
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md)
|
||||
|
|
18
gfm/sec20.md
18
gfm/sec20.md
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 19](sec19.md), Next: [Section 21](sec21.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 19](sec19.md), Next: [Section 21](sec21.md)
|
||||
|
||||
# GtkMenuButton, accelerators, font, pango and gsettings
|
||||
|
||||
|
@ -183,7 +183,7 @@ You can define more than one accelerator keys and the list must ends with NULL (
|
|||
If you want to do so, the array length needs to be three or more.
|
||||
The parser recognizes "\<control\>o", "\<Shift\>\<Alt\>F2", "\<Ctrl\>minus" and so on.
|
||||
If you want to use symbol key like "\<Ctrl\>-", use "\<Ctrl\>minus" instead.
|
||||
Such relation between lower case and symbol (its character code) is specified in [`gdkkeysyms.h`](https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/gdkkeysyms.h) in the Gtk4 source code.
|
||||
Such relation between lower case and symbol (its character code) is specified in [`gdkkeysyms.h`](https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/gdkkeysyms.h) in the GTK 4 source code.
|
||||
|
||||
## Saveas handler
|
||||
|
||||
|
@ -276,7 +276,7 @@ Transient-for specifies a temporary parent window, which the dialog's location i
|
|||
- internal-child attribute is used in the child tag above.
|
||||
GtkDialog has a GtkBox child widget.
|
||||
Its id is "content_area" in `gtkdialog.ui`, which is the ui file of GtkDialog.
|
||||
(It is in the Gtk4 source files.)
|
||||
(It is in the GTK 4 source files.)
|
||||
This box is provided for users to add content widgets in it.
|
||||
The tag `<child internal-child="content_area">` is put at the top of the contents.
|
||||
Then you need to specify an object tag and define its class as GtkBox and its id as content_area.
|
||||
|
@ -936,7 +936,7 @@ Other common types are:
|
|||
- "i": gint32.
|
||||
- "d": double.
|
||||
|
||||
Further information is in [Glib API Reference, VarientType](https://docs.gtk.org/glib/struct.VariantType.html).
|
||||
Further information is in [GLib API Reference, VarientType](https://docs.gtk.org/glib/struct.VariantType.html).
|
||||
|
||||
### gsettings
|
||||
|
||||
|
@ -1006,7 +1006,7 @@ org.gnome.calculator number-format 'automatic'
|
|||
org.gnome.calculator show-zeroes false
|
||||
~~~
|
||||
|
||||
This schema is used by Gnome Calculator.
|
||||
This schema is used by GNOME Calculator.
|
||||
Run the calculator and change the mode, then check the schema again.
|
||||
|
||||
~~~
|
||||
|
@ -1033,7 +1033,7 @@ org.gnome.calculator button-mode 'advanced'
|
|||
|
||||
~~~
|
||||
|
||||
Now we know that Gnome Calculator used gsettings and it has set `button-mode` key to "advanced".
|
||||
Now we know that GNOME Calculator used gsettings and it has set `button-mode` key to "advanced".
|
||||
The value remains even the calculator quits.
|
||||
So when the calculator is run again, it will appear as an advanced mode calculator.
|
||||
|
||||
|
@ -1165,14 +1165,14 @@ Just create a GSettings object and bind it to a property of an object.
|
|||
|
||||
## Installation
|
||||
|
||||
It is a good idea to install your application in `$HOME/local/bin` directory if you have installed Gtk4 from the source (See Section 2).
|
||||
It is a good idea to install your application in `$HOME/local/bin` directory if you have installed GTK 4 from the source (See Section 2).
|
||||
Then you need to put `--prefix=$HOME/local` option to meson like this.
|
||||
|
||||
~~~
|
||||
$ meson --prefix=$HOME/local _build
|
||||
~~~
|
||||
|
||||
If you've installed Gtk4 from the distribution package, `--prefix` option isn't necessary.
|
||||
If you've installed GTK 4 from the distribution package, `--prefix` option isn't necessary.
|
||||
You just install `tfe` to the default bin directory like `/usr/local/bin`.
|
||||
|
||||
Modify `meson.build` and add install option and set it true in executable function.
|
||||
|
@ -1256,4 +1256,4 @@ The screenshot is as follows.
|
|||
![tfe6](../image/tfe6.png)
|
||||
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 19](sec19.md), Next: [Section 21](sec21.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 19](sec19.md), Next: [Section 21](sec21.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 20](sec20.md), Next: [Section 22](sec22.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 20](sec20.md), Next: [Section 22](sec22.md)
|
||||
|
||||
# Template XML and composite widget
|
||||
|
||||
|
@ -825,7 +825,7 @@ Meson.build
|
|||
|
||||
## Compilation and installation.
|
||||
|
||||
If you build Gtk4 from the source, use `--prefix` option.
|
||||
If you build GTK 4 from the source, use `--prefix` option.
|
||||
|
||||
~~~
|
||||
$ meson --prefix=$HOME/local _build
|
||||
|
@ -833,7 +833,7 @@ $ ninja -C _build
|
|||
$ ninja -C _build install
|
||||
~~~
|
||||
|
||||
If you install Gtk4 from the distribution packages, you don't need the prefix option.
|
||||
If you install GTK 4 from the distribution packages, you don't need the prefix option.
|
||||
Maybe you need root privilege to install it.
|
||||
|
||||
~~~
|
||||
|
@ -852,4 +852,4 @@ It isn't good to put many things into one file.
|
|||
And it is important to think about the relationship between source files and widget structures.
|
||||
It is appropriate that they correspond to each other in many cases.
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 20](sec20.md), Next: [Section 22](sec22.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 20](sec20.md), Next: [Section 22](sec22.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 23](sec23.md), Next: [Section 25](sec25.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 23](sec23.md), Next: [Section 25](sec25.md)
|
||||
|
||||
# Combine GtkDrawingArea and TfeTextView
|
||||
|
||||
|
@ -349,8 +349,8 @@ An argument "export_dynamic: true" is added to executable function.
|
|||
|
||||
## Compile and execute it
|
||||
|
||||
First you need to export some variables (refer to [Section 2](sec2.md)) if you've installed Gtk4 from the source.
|
||||
If you've installed Gtk4 from the distribution packages, you don't need to do this.
|
||||
First you need to export some variables (refer to [Section 2](sec2.md)) if you've installed GTK 4 from the source.
|
||||
If you've installed GTK 4 from the distribution packages, you don't need to do this.
|
||||
|
||||
$ . env.sh
|
||||
|
||||
|
@ -374,4 +374,4 @@ Probably it is more appropriate.
|
|||
Using textview is unnatural.
|
||||
It is a good practice to make such application by yourself.
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 23](sec23.md), Next: [Section 25](sec25.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 23](sec23.md), Next: [Section 25](sec25.md)
|
||||
|
|
14
gfm/sec26.md
14
gfm/sec26.md
|
@ -1,12 +1,12 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 25](sec25.md), Next: [Section 27](sec27.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 25](sec25.md), Next: [Section 27](sec27.md)
|
||||
|
||||
# GtkListView
|
||||
|
||||
Gtk4 has added new list objects GtkListView, GtkGridView and GtkColumnView.
|
||||
GTK 4 has added new list objects GtkListView, GtkGridView and GtkColumnView.
|
||||
The new feature is described in [Gtk API Reference, List Widget Overview](https://docs.gtk.org/gtk4/section-list-widget.html).
|
||||
|
||||
Gtk4 has other means to implement lists.
|
||||
They are GtkListBox and GtkTreeView which are took over from Gtk3.
|
||||
GTK 4 has other means to implement lists.
|
||||
They are GtkListBox and GtkTreeView which are took over from GTK 3.
|
||||
There's an article in [Gtk Development blog](https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/) about list widgets by Matthias Clasen.
|
||||
He described why GtkListView are developed to replace GtkListBox and GtkTreeView.
|
||||
|
||||
|
@ -59,7 +59,7 @@ There are functions to add items to the list or remove items from the list.
|
|||
- `gtk_string_list_remove` removes an item from the list
|
||||
- `gtk_string_list_get_string` gets a string in the list
|
||||
|
||||
See [Gtk4 API Reference, GtkStringList](https://docs.gtk.org/gtk4/class.StringList.html) for further information.
|
||||
See [GTK 4 API Reference, GtkStringList](https://docs.gtk.org/gtk4/class.StringList.html) for further information.
|
||||
|
||||
I'll explain the other list objects later.
|
||||
|
||||
|
@ -201,7 +201,7 @@ GtkNoSelection is used, so user can't select any item.
|
|||
|
||||
The file `list1.c` is located under the directory [src/misc](../src/misc).
|
||||
Make a shell script below and save it to your bin directory.
|
||||
(If you've installed Gtk4 from the source to $HOME/local, then your bin directory is $Home/local/bin.
|
||||
(If you've installed GTK 4 from the source to $HOME/local, then your bin directory is $Home/local/bin.
|
||||
Otherwise, $Home/bin is your private bin directory.)
|
||||
|
||||
~~~Shell
|
||||
|
@ -547,4 +547,4 @@ $ ./a.out
|
|||
![screenshot list3](../image/list3.png)
|
||||
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 25](sec25.md), Next: [Section 27](sec27.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 25](sec25.md), Next: [Section 27](sec27.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 26](sec26.md), Next: [Section 28](sec28.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 26](sec26.md), Next: [Section 28](sec28.md)
|
||||
|
||||
# GtkGridView and activate signal
|
||||
|
||||
|
@ -475,7 +475,7 @@ The third parameter is GAppLaunchContext, but this program gives NULL instead.
|
|||
The last parameter is the pointer to the pointer to a GError.
|
||||
- 34: `g_list_free_full` frees the memories used by the list and items.
|
||||
|
||||
If your distribution supports Gtk4, using `g_app_info_launch_default_for_uri` is convenient.
|
||||
If your distribution supports GTK 4, using `g_app_info_launch_default_for_uri` is convenient.
|
||||
The function automatically determines the default application from the file and launches it.
|
||||
For example, if the file is text, then it launches gedit with the file.
|
||||
Such functionality comes from desktop.
|
||||
|
@ -569,4 +569,4 @@ If you feel some difficulty, it is better for you to separate the ui file.
|
|||
A directory [src/list5](../src/list5) includes the ui file above.
|
||||
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 26](sec26.md), Next: [Section 28](sec28.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 26](sec26.md), Next: [Section 28](sec28.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.md)
|
||||
|
||||
# GtkApplication and GtkApplicationWindow
|
||||
|
||||
|
@ -10,7 +10,7 @@ Usually people write programming code to make an application.
|
|||
What are applications?
|
||||
Applications are software that runs using libraries, which includes the
|
||||
OS, frameworks and so on.
|
||||
In Gtk4 programming, the GtkApplication is a program (or executable) that runs
|
||||
In GTK 4 programming, the GtkApplication is a program (or executable) that runs
|
||||
using Gtk libraries.
|
||||
|
||||
The basic way to write a GtkApplication is as follows.
|
||||
|
@ -280,7 +280,7 @@ As it destroys itself, the GtkWindow is also destroyed.
|
|||
|
||||
The function `gtk_widget_show` is used to show the window.
|
||||
|
||||
Gtk4 changes the default widget visibility to on, so every widget doesn't need this function to show itself.
|
||||
GTK 4 changes the default widget visibility to on, so every widget doesn't need this function to show itself.
|
||||
But, there's an exception.
|
||||
Top window (this term will be explained later) isn't visible when it is created.
|
||||
So you need to use the function above to show the window.
|
||||
|
@ -327,4 +327,4 @@ Compile it and run `a.out`, then you will see a bigger window with its title "pr
|
|||
|
||||
![Screenshot of the window](../image/screenshot_pr4.png)
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 5](sec5.md), Next: [Section 7](sec7.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 5](sec5.md), Next: [Section 7](sec7.md)
|
||||
|
||||
# String and memory management
|
||||
|
||||
|
@ -139,7 +139,7 @@ The array `b` is created on the stack then the function is called, disappears wh
|
|||
You can also get, use and release memory from the heap area.
|
||||
The standard C library provides `malloc` to get memory and `free` to put back memory.
|
||||
GLib provides the functions `g_new` and `g_free` to do the same thing, with support for
|
||||
some additional Glib functionality.
|
||||
some additional GLib functionality.
|
||||
|
||||
~~~C
|
||||
g_new (struct_type, n_struct)
|
||||
|
@ -188,7 +188,7 @@ g_free (t);
|
|||
|
||||
If the argument doesn't point allocated memory it will cause an error, specifically, a segmentation fault.
|
||||
|
||||
Some Glib functions allocate memory.
|
||||
Some GLib functions allocate memory.
|
||||
For example, `g_strdup` allocates memory and copies a string given as an argument.
|
||||
|
||||
~~~C
|
||||
|
@ -232,4 +232,4 @@ const int x = 10; /* initialization is OK. */
|
|||
x = 20; /* This is illegal because x is qualified with const */
|
||||
~~~
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 5](sec5.md), Next: [Section 7](sec7.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 5](sec5.md), Next: [Section 7](sec7.md)
|
||||
|
|
10
gfm/sec8.md
10
gfm/sec8.md
|
@ -1,8 +1,8 @@
|
|||
Up: [Readme.md](../Readme.md), Prev: [Section 7](sec7.md), Next: [Section 9](sec9.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 7](sec7.md), Next: [Section 9](sec9.md)
|
||||
|
||||
# Defining a Child object
|
||||
# Defining a child object
|
||||
|
||||
## A Very Simple Editor
|
||||
## A very simple editor
|
||||
|
||||
In the previous section we made a very simple file viewer.
|
||||
Now we go on to rewrite it and turn it into very simple editor.
|
||||
|
@ -54,7 +54,7 @@ particularly for beginners.
|
|||
So, I will just show you the way how to write the code and avoid the theoretical side.
|
||||
If you want to know about GObject system, refer to another [tutorial](https://github.com/ToshioCP/Gobject-tutorial).
|
||||
|
||||
## How to Define a Child Object of GtkTextView
|
||||
## How to define a child object of GtkTextView
|
||||
|
||||
Let's define the TfeTextView object, which is a child object of GtkTextView.
|
||||
First, look at the program below.
|
||||
|
@ -382,4 +382,4 @@ It's not smart.
|
|||
We need more features like open, save, saveas, change font and so on.
|
||||
We will add them in the next section and after.
|
||||
|
||||
Up: [Readme.md](../Readme.md), Prev: [Section 7](sec7.md), Next: [Section 9](sec9.md)
|
||||
Up: [README.md](../README.md), Prev: [Section 7](sec7.md), Next: [Section 9](sec9.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# How to build Gtk4 Tutorial
|
||||
# How to build Gtk4-Tutorial
|
||||
|
||||
## Quick start guide
|
||||
|
||||
|
@ -24,16 +24,16 @@ Then, click "Download ZIP".
|
|||
- Latex system. Texlive2020 or later version is recommended.
|
||||
It is used to generate the pdf file.
|
||||
|
||||
## Github flavored markdown
|
||||
## GitHub Flavored Markdown
|
||||
|
||||
When you see [gtk4_tutorial github repository](https://github.com/ToshioCP/Gtk4-tutorial), you'll find the contents of the `Readme.md` file.
|
||||
When you see [gtk4_tutorial GitHub repository](https://github.com/ToshioCP/Gtk4-tutorial), you'll find the contents of the `Readme.md` file.
|
||||
This file is written in markdown language.
|
||||
Markdown files have `.md` suffix.
|
||||
|
||||
There are several kinds of markdown language.
|
||||
`Readme.md` uses 'github flavored markdown', which is often shortened as GFM.
|
||||
`Readme.md` uses 'GitHub Flavored Markdown', which is often shortened as GFM.
|
||||
Markdown files in the `gfm` directory are written in GFM.
|
||||
If you are not familiar with it, refer to the page [github flavor markdown spec](https://github.github.com/gfm/).
|
||||
If you are not familiar with it, refer to the page [GitHub Flavor Markdown spec](https://github.github.com/gfm/).
|
||||
|
||||
## Pandoc's markdown
|
||||
|
||||
|
@ -435,7 +435,7 @@ Because the navigation of the previous section of the newly added section needs
|
|||
If you don't do `rake clobber`, then it won't be updated because the the timestamp of .md file in gfm is newer than the one of .src.md file.
|
||||
In this case, using `touch` to the previous section .src.md also works to update the file.
|
||||
|
||||
If you see the github repository (ToshioCP/Gtk4-tutorial), `Readme.md` is shown below the code.
|
||||
If you see the GitHub repository (ToshioCP/Gtk4-tutorial), `Readme.md` is shown below the code.
|
||||
And `Readme.md` includes links to each markdown files.
|
||||
The repository not only stores source files but also shows the whole tutorial.
|
||||
|
||||
|
@ -475,7 +475,7 @@ Rake uses `lib/lib_mk_html_template.rb` to create its own template.
|
|||
The template inserts bootstrap CSS and Javascript through `jsDelivr`.
|
||||
|
||||
The `docs` directory contains all the necessary html files.
|
||||
They are used in the [github pages](https://ToshioCP.github.io/Gtk4-tutorial) of this repository.
|
||||
They are used in the [GitHub pages](https://ToshioCP.github.io/Gtk4-tutorial) of this repository.
|
||||
|
||||
So if you want to publish this tutorial on your own web site, just upload the files in the `docs` directory to your site.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#### Contents of this Repository
|
||||
|
||||
This tutorial illustrates how to write C programs with the Gtk4 library.
|
||||
This tutorial illustrates how to write C programs with the GTK 4 library.
|
||||
It focuses on beginners so the contents are limited to the basics.
|
||||
The table of contents is at the end of this abstract.
|
||||
|
||||
|
@ -9,27 +9,27 @@ The table of contents is at the end of this abstract.
|
|||
- Section 26 to 29 describes the list model and the list view (GtkListView, GtkGridView and GtkColumnView).
|
||||
It also describes GtkExpression.
|
||||
|
||||
The latest version of the tutorial is located at [Gtk4-tutorial github repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
||||
The latest version of the tutorial is located at [Gtk4-tutorial GitHub repository](https://github.com/ToshioCP/Gtk4-tutorial).
|
||||
You can read it from there directly without having to download anything.
|
||||
|
||||
#### Gtk4 Documentation
|
||||
#### GTK 4 Documentation
|
||||
|
||||
Please refer to [Gtk API Reference](https://docs.gtk.org/gtk4/index.html)
|
||||
and [Gnome Developer Documentation Website](https://developer.gnome.org/) for further information.
|
||||
Please refer to [GTK API Reference](https://docs.gtk.org/gtk4/index.html)
|
||||
and [GNOME Developer Documentation Website](https://developer.gnome.org/) for further information.
|
||||
|
||||
These websites are newly opened lately (Aug/2021).
|
||||
The old documentation is located at [Gtk Reference Manual](https://developer-old.gnome.org/gtk4/stable/) and [Gnome Developer Center](https://developer-old.gnome.org/).
|
||||
The old documentation is located at [GTK Reference Manual](https://developer-old.gnome.org/gtk4/stable/) and [GNOME Developer Center](https://developer-old.gnome.org/).
|
||||
The new website is in progress at present, so you might need to refer to the old version.
|
||||
|
||||
If you want to know about GObject and the type system, please refer to [GObject tutorial](https://github.com/ToshioCP/Gobject-tutorial).
|
||||
The GObject details are easy to understand and also necessary to know when writing Gtk4 programs.
|
||||
The GObject details are easy to understand and also necessary to know when writing GTK 4 programs.
|
||||
|
||||
#### Contribution
|
||||
|
||||
This tutorial is under development and unstable.
|
||||
Even though the codes of the examples have been tested on Gtk4 version 4.0, bugs may still exist.
|
||||
Even though the codes of the examples have been tested on GTK 4 (version 4.0), bugs may still exist.
|
||||
If you find any bugs, errors or mistakes in the tutorial and C examples, please let me know.
|
||||
You can post it to [github issues](https://github.com/ToshioCP/Gtk4-tutorial/issues).
|
||||
You can post it to [GitHub issues](https://github.com/ToshioCP/Gtk4-tutorial/issues).
|
||||
You can also post corrected files as a commit to [pull request](https://github.com/ToshioCP/Gtk4-tutorial/pulls).
|
||||
When you make corrections, correct the source files, which are under the 'src' directory,
|
||||
then run `rake` to create to create the output file. The GFM files under the 'gfm' directory are automatically updated.
|
||||
|
@ -43,9 +43,9 @@ If you want to get a HTML or PDF version, you can make them with `rake`, which i
|
|||
Type `rake html` for HTML.
|
||||
Type `rake pdf` for PDF.
|
||||
@@@if gfm
|
||||
There is a documentation \("[How to build Gtk4 Tutorial](Readme_for_developers.src.md)"\) that describes how to make them.
|
||||
There is a documentation \("[How to build GTK 4 Tutorial](Readme_for_developers.src.md)"\) that describes how to make them.
|
||||
@@@elif html
|
||||
There is a documentation \("[How to build Gtk4 Tutorial](Readme_for_developers.src.md)"\) that describes how to make them.
|
||||
There is a documentation \("[How to build GTK 4 Tutorial](Readme_for_developers.src.md)"\) that describes how to make them.
|
||||
@@@elif latex
|
||||
An appendix "How to build Gtk4 Tutorial" describes how to make them.
|
||||
An appendix "How to build GTK 4 Tutorial" describes how to make them.
|
||||
@@@end
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
## Prerequisite
|
||||
|
||||
### Gtk4 on a Linux OS
|
||||
### GTK 4 on a Linux OS
|
||||
|
||||
This tutorial is about Gtk4 libraries.
|
||||
This tutorial is about GTK 4 libraries.
|
||||
It is originally used on Linux with C compiler, but now it is used more widely, on Windows and MacOS, with Vala, Python and so on.
|
||||
However, this tutorial describes only _C programs on Linux_.
|
||||
|
||||
|
@ -12,10 +12,10 @@ If you want to try the examples in the tutorial, you need:
|
|||
|
||||
- PC with Linux distribution like Ubuntu, Debian and so on.
|
||||
- Gcc.
|
||||
- Gtk4.
|
||||
- GTK 4.
|
||||
The stable version of Gtk on Linux distributions is version three at present.
|
||||
You need to install Gtk4 to your computer.
|
||||
See [Section 3](sec3.src.md) for the installation of Gtk4.
|
||||
You need to install GTK 4 to your computer.
|
||||
See [Section 3](sec3.src.md) for the installation of GTK 4.
|
||||
|
||||
### Ruby and rake for making the document
|
||||
|
||||
|
@ -38,11 +38,11 @@ You can install it as a package of your distribution or use gem command.
|
|||
|
||||
Copyright (C) 2020 ToshioCP (Toshio Sekiya)
|
||||
|
||||
Gtk4 tutorial repository contains the tutorial document and software such as converters, generators and controllers.
|
||||
All of them make up the 'Gtk4 tutorial' package.
|
||||
This package is simply called 'Gtk4 tutorial' in the following description.
|
||||
'Gtk4 tutorial' is free; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License or, at your option, any later version.
|
||||
Gtk4-tutorial repository contains the tutorial document and software such as converters, generators and controllers.
|
||||
All of them make up the 'Gtk4-tutorial' package.
|
||||
This package is simply called 'Gtk4-tutorial' in the following description.
|
||||
'Gtk4-tutorial' is free; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License or, at your option, any later version.
|
||||
|
||||
'Gtk4 tutorial' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
'Gtk4-tutorial' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the [GNU General Public License](https://www.gnu.org/licenses/gpl-3.0.html) for more details.
|
||||
|
||||
|
|
|
@ -215,9 +215,9 @@ Then, it emits "open-response" signal with the parameter `TFE_OPEN_RESPONSE_SUCC
|
|||
Now let's think about the whole process between the caller and TfeTextView.
|
||||
It is shown in the following diagram and you would think that it is really complicated.
|
||||
Because signal is the only way for GtkFileChooserDialog to communicate with others.
|
||||
In Gtk3, `gtk_dialog_run` function is available.
|
||||
In GTK 3, `gtk_dialog_run` function is available.
|
||||
It simplifies the process.
|
||||
However, in Gtk4, `gtk_dialog_run` is unavailable any more.
|
||||
However, in GTK 4, `gtk_dialog_run` is unavailable any more.
|
||||
|
||||
![Caller and TfeTextView](../image/open.png){width=12.405cm height=9.225cm}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ textview {color: yellow; ...}
|
|||
~~~
|
||||
|
||||
Class, ID and some other things can be applied to the selector like Web CSS.
|
||||
Refer to [Gtk4 API Reference, CSS in Gtk](https://docs.gtk.org/gtk4/css-overview.html) for further information.
|
||||
Refer to [GTK 4 API Reference, CSS in Gtk](https://docs.gtk.org/gtk4/css-overview.html) for further information.
|
||||
|
||||
In line 30, the CSS is a string.
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ Useless GMenuItem are freed.
|
|||
- 79-80: GMenuModel `menubar` is inserted to `app`.
|
||||
Sets show menubar property of `win` to `TRUE`.
|
||||
Note: `gtk_application_window_set_show_menubar` creates GtkPopoverMenubar from GMenuModel.
|
||||
This is a different point between Gtk3 and Gtk4.
|
||||
This is a different point between GTK 3 and GTK 4.
|
||||
And you can use GtkPopoverMenubar directly and set it as a descendant widget of the window.
|
||||
You may use GtkBox as a child widget of the window and insert GtkPopoverMenubar as the first child of the box.
|
||||
- 82-87: Sets CSS.
|
||||
|
|
118
src/sec2.src.md
118
src/sec2.src.md
|
@ -1,24 +1,24 @@
|
|||
# Installing Gtk4 into Linux distributions
|
||||
# Installing GTK 4 into Linux distributions
|
||||
|
||||
This section describes how to install Gtk4 into Linux distributions.
|
||||
This section describes how to install GTK 4 into Linux distributions.
|
||||
|
||||
This tutorial is without any warranty.
|
||||
If you want to install Gtk4 to your computer, do it at your own risk.
|
||||
If you want to install GTK 4 to your computer, do it at your own risk.
|
||||
|
||||
The information in this section is the one on April/27/2022.
|
||||
The words 'at present' and/or 'now' in this section means 'April/27/2022'.
|
||||
|
||||
There are three possible way to install Gtk4.
|
||||
There are three possible way to install GTK 4.
|
||||
|
||||
- Install it from the distribution packages.
|
||||
- Build it from the source file.
|
||||
- Install a Gnome 40 distribution with the gnome-boxes.
|
||||
- Install a GNOME 40 distribution with the GNOME Boxes.
|
||||
|
||||
## Installation from the distribution packages
|
||||
|
||||
The first way is easy to install.
|
||||
It is a recommended way.
|
||||
I've installed Gtk4 packages in Ubuntu 21.04.
|
||||
I've installed GTK 4 packages in Ubuntu 21.04.
|
||||
(Now, my Ubuntu version is 21.10).
|
||||
|
||||
~~~
|
||||
|
@ -27,31 +27,31 @@ $ sudo apt-get install libgtk-4-bin libgtk-4-common libgtk-4-dev libgtk-4-doc
|
|||
|
||||
Fedora, Arch, Debian and OpenSUSE are also possible.
|
||||
See [Installing GTK from packages](https://www.gtk.org/docs/installations/linux#installing-gtk-from-packages).
|
||||
The following table shows the distributions which support Gtk4.
|
||||
The following table shows the distributions which support GTK 4.
|
||||
|
||||
@@@table
|
||||
|Distribution|version|Gtk4|Gnome40|
|
||||
|Distribution|version|GTK 4|GNOME 40|
|
||||
|:-:|:-:|:-:|:-:|
|
||||
|Fedora|36|4.4.2|Gnome42|
|
||||
|Ubuntu|22.04lts|4.4|Gnome41(4.6.2)|
|
||||
|Debian|bookworm(testing)|4.6.5|Gnome42|
|
||||
|Arch|rolling release|4.6.5|Gnome42|
|
||||
|Gentoo|rolling release|4.6.5|Gnome42|
|
||||
|OpenSUSE|Tumbleweed(rolling release)|4.6.5|Gnome42|
|
||||
|Fedora|36|4.4.2|GNOME 42|
|
||||
|Ubuntu|22.04lts|4.4|GNOME 41(4.6.2)|
|
||||
|Debian|bookworm(testing)|4.6.5|GNOME 42|
|
||||
|Arch|rolling release|4.6.5|GNOME 42|
|
||||
|Gentoo|rolling release|4.6.5|GNOME 42|
|
||||
|OpenSUSE|Tumbleweed(rolling release)|4.6.5|GNOME 42|
|
||||
@@@
|
||||
|
||||
If you've installed Gtk4 from the packages, you don't need to read the rest of this section.
|
||||
If you've installed GTK 4 from the packages, you don't need to read the rest of this section.
|
||||
|
||||
## Installation from the source file
|
||||
|
||||
If your operating system doesn't have Gtk4 packages, you need to build it from the source.
|
||||
Or, if you want the latest version of Gtk4 (4.6.3), you also need to build it from the source.
|
||||
If your operating system doesn't have GTK 4 packages, you need to build it from the source.
|
||||
Or, if you want the latest version of GTK 4 (4.6.3), you also need to build it from the source.
|
||||
|
||||
I installed Gtk4 from the source in January 2021.
|
||||
I installed GTK 4 from the source in January 2021.
|
||||
So, the following information is old, especially for the version of each software.
|
||||
For the latest information, see [Gtk API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html).
|
||||
For the latest information, see [GTK API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html).
|
||||
|
||||
### Prerequisites for Gtk4 installation
|
||||
### Prerequisites for GTK 4 installation
|
||||
|
||||
- Linux operating system. For example, Ubuntu 20.10 or 20.04LTS.
|
||||
Other distributions might be OK.
|
||||
|
@ -60,14 +60,14 @@ Other distributions might be OK.
|
|||
|
||||
### Installation target
|
||||
|
||||
I installed Gtk4 under the directory `$HOME/local`.
|
||||
I installed GTK 4 under the directory `$HOME/local`.
|
||||
This is a private user area.
|
||||
|
||||
If you want to install it in the system area, `/opt/gtk4` is one of good choices.
|
||||
[Gtk API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html) gives an installation example to `/opt/gtk4`.
|
||||
[GTK API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html) gives an installation example to `/opt/gtk4`.
|
||||
|
||||
Don't install it to `/usr/local` which is the default.
|
||||
It is used by Ubuntu applications which are not build on Gtk4.
|
||||
It is used by Ubuntu applications which are not build on GTK 4.
|
||||
Therefore, the risk is high and probably bad things will happen.
|
||||
Actually I did it and I needed to reinstall Ubuntu.
|
||||
|
||||
|
@ -76,9 +76,9 @@ Actually I did it and I needed to reinstall Ubuntu.
|
|||
Most of the necessary libraries are included by Ubuntu 20.10.
|
||||
Therefore, they can be installed with `apt-get` command.
|
||||
You don't need to install them from the source tarballs.
|
||||
You can skip the subsections below about prerequisite library installation (Glib, Pango, Gdk-pixbuf and Gtk-doc).
|
||||
You can skip the subsections below about prerequisite library installation (GLib, Pango, GdkPixbuf and GTK-doc).
|
||||
|
||||
### Glib installation
|
||||
### GLib installation
|
||||
|
||||
If your Ubuntu is 20.04LTS, you need to install prerequisite libraries from the tarballs.
|
||||
Check the version of your library and if it is lower than the necessary version, install it from the source.
|
||||
|
@ -91,15 +91,15 @@ $ pkg-config --modversion glib-2.0
|
|||
~~~
|
||||
|
||||
The necessary version is 2.66.0 or higher.
|
||||
Therefore, the example above shows that you need to install Glib.
|
||||
Therefore, the example above shows that you need to install GLib.
|
||||
|
||||
I installed 2.67.1 which was the latest version at that time (January 2021).
|
||||
Download Glib source files from the repository, then decompress and extract files.
|
||||
Download GLib source files from the repository, then decompress and extract files.
|
||||
|
||||
$ wget https://download.gnome.org/sources/glib/2.67/glib-2.67.1.tar.xz
|
||||
$ tar -Jxf glib-2.67.1.tar.xz
|
||||
|
||||
Some packages are required to build Glib.
|
||||
Some packages are required to build GLib.
|
||||
You can find them if you run meson.
|
||||
|
||||
$ meson --prefix $HOME/local _build
|
||||
|
@ -109,14 +109,14 @@ For example,
|
|||
|
||||
$ sudo apt-get install -y libpcre2-dev libffi-dev
|
||||
|
||||
After that, compile Glib.
|
||||
After that, compile GLib.
|
||||
|
||||
$ rm -rf _build
|
||||
$ meson --prefix $HOME/local _build
|
||||
$ ninja -C _build
|
||||
$ ninja -C _build install
|
||||
|
||||
Set several environment variables so that the Glib libraries installed can be used by build tools.
|
||||
Set several environment variables so that the GLib libraries installed can be used by build tools.
|
||||
Make a text file below and save it as `env.sh`
|
||||
|
||||
# compiler
|
||||
|
@ -165,7 +165,7 @@ Now `$HOME/local/share` needs to be added to `XDG_DATA_DIRS`, or error will occu
|
|||
|
||||
$ export XDG_DATA_DIRS=$HOME/local/share:$XDG_DATA_DIRS
|
||||
|
||||
### Gdk-pixbuf and Gtk-doc installation
|
||||
### GdkPixbuf and GTK-Doc installation
|
||||
|
||||
Download and untar.
|
||||
|
||||
|
@ -176,19 +176,19 @@ Download and untar.
|
|||
|
||||
Same as before, install prerequisite packages, then compile and install them.
|
||||
|
||||
The installation of Gtk-doc put `gtk-doc.pc` under `$HOME/local/share/pkgconfig`.
|
||||
The installation of GTK-Doc put `gtk-doc.pc` under `$HOME/local/share/pkgconfig`.
|
||||
This file is used by pkg-config, which is one of the build tools.
|
||||
The directory needs to be added to the environment variable `PKG_CONFIG_PATH`
|
||||
|
||||
$ export PKG_CONFIG_PATH="$HOME/local/share/pkgconfig:$PKG_CONFIG_PATH"
|
||||
|
||||
### Gtk4 installation
|
||||
### GTK 4 installation
|
||||
|
||||
If you want the latest development version of Gtk4, use git and clone the repository.
|
||||
If you want the latest development version of GTK 4, use git and clone the repository.
|
||||
|
||||
$ git clone https://gitlab.gnome.org/GNOME/gtk.git
|
||||
$ git clone https://gitlab.gnome.org/gnome/gtk.git
|
||||
|
||||
If you want a stable version of Gtk4, then download it from [Gnome source website](https://download.gnome.org/sources/gtk/).
|
||||
If you want a stable version of GTK 4, then download it from [GNOME source website](https://download.gnome.org/sources/gtk/).
|
||||
The latest version is 4.3.1 (13/June/2021).
|
||||
|
||||
Compile and install it.
|
||||
|
@ -197,7 +197,7 @@ Compile and install it.
|
|||
$ ninja -C _build
|
||||
$ ninja -C _build install
|
||||
|
||||
If you want to know more information, refer to [Gtk4 API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html).
|
||||
If you want to know more information, refer to [GTK 4 API Reference, Building GTK](https://docs.gtk.org/gtk4/building.html).
|
||||
|
||||
### Modify env.sh
|
||||
|
||||
|
@ -222,18 +222,18 @@ Modify `env.sh`.
|
|||
# girepository-1.0
|
||||
export GI_TYPELIB_PATH=$HOME/local/lib/x86_64-linux-gnu/girepository-1.0
|
||||
|
||||
Include this file by . (dot) command before using Gtk4 libraries.
|
||||
Include this file by . (dot) command before using GTK 4 libraries.
|
||||
|
||||
You may think you can add them in your `.profile`.
|
||||
But it's a wrong decision.
|
||||
Never write them to your `.profile`.
|
||||
The environment variables above are necessary only when you compile and run Gtk4 applications.
|
||||
The environment variables above are necessary only when you compile and run GTK 4 applications.
|
||||
Otherwise it's not necessary.
|
||||
If you changed the environment variables above and run Gtk3 applications, it probably causes serious damage.
|
||||
If you changed the environment variables above and run GTK 3 applications, it probably causes serious damage.
|
||||
|
||||
### Compiling Gtk4 applications
|
||||
### Compiling GTK 4 applications
|
||||
|
||||
Before you compile Gtk4 applications, define environment variables above.
|
||||
Before you compile GTK 4 applications, define environment variables above.
|
||||
|
||||
$ . env.sh
|
||||
|
||||
|
@ -242,20 +242,20 @@ For example, to compile `sample.c`, type the following.
|
|||
|
||||
$ gcc `pkg-config --cflags gtk4` sample.c `pkg-config --libs gtk4`
|
||||
|
||||
To know how to compile Gtk4 applications, refer to the section 3 (GtkApplication and GtkApplicationWindow) and after.
|
||||
To know how to compile GTK 4 applications, refer to the section 3 (GtkApplication and GtkApplicationWindow) and after.
|
||||
|
||||
## Installing Fedora 34 with gnome-boxes
|
||||
## Installing Fedora 34 with GNOME Boxes
|
||||
|
||||
The last part of this section is about Gnome40 and gnome-boxes.
|
||||
Gnome 40 is a new version of Gnome desktop system.
|
||||
And Gtk4 is installed in the distribution.
|
||||
See [Gnome 40 website](https://forty.gnome.org/) first.
|
||||
The last part of this section is about GNOME 40 and GNOME Boxes.
|
||||
GNOME 40 is a new version of GNOME desktop system.
|
||||
And GTK 4 is installed in the distribution.
|
||||
See [GNOME 40 website](https://forty.gnome.org/) first.
|
||||
|
||||
*However, Gnome40 is not necessary to compile and run Gtk4 applications.*
|
||||
*However, GNOME 40 is not necessary to compile and run GTK 4 applications.*
|
||||
|
||||
There are seven choices at present.
|
||||
|
||||
- Gnome OS
|
||||
- GNOME OS
|
||||
- Arch Linux
|
||||
- Gentoo Linux
|
||||
- Fedora 36
|
||||
|
@ -263,19 +263,19 @@ There are seven choices at present.
|
|||
- Ubuntu 22.04
|
||||
- Debian bookworm
|
||||
|
||||
I've installed Fedora 34 with gnome-boxes.
|
||||
I've installed Fedora 34 with GNOME Boxes.
|
||||
My OS was Ubuntu 21.04 at that time.
|
||||
Gnome-boxes creates a virtual machine in Ubuntu and Fedora will be installed to that virtual machine.
|
||||
GNOME Boxes creates a virtual machine in Ubuntu and Fedora will be installed to that virtual machine.
|
||||
|
||||
The instruction is as follows.
|
||||
|
||||
1. Download Fedora 34 iso file.
|
||||
There is an link at the end of [Gnome 40 website](https://forty.gnome.org/).
|
||||
There is an link at the end of [GNOME 40 website](https://forty.gnome.org/).
|
||||
2. Install gnome-boxes with apt-get command.
|
||||
~~~
|
||||
$ sudo apt-get install gnome-boxes
|
||||
~~~
|
||||
3. Run gnome-boxes.
|
||||
3. Run GNOME Boxes.
|
||||
4. Click on `+` button on the top left corner and launch a box creation wizard by clicking `Create a Virtual Machine ...`.
|
||||
Then a dialog appears.
|
||||
Click on `Operationg System Image File` and select the iso file you have downloaded.
|
||||
|
@ -283,23 +283,23 @@ Click on `Operationg System Image File` and select the iso file you have downloa
|
|||
Follow the instructions by the installer.
|
||||
At the end of the installation, the installer instructs to reboot the system.
|
||||
Click on the right of the title bar and select reboot or shutdown.
|
||||
6. Your display is back to the initial window of gnome-boxes, but there is a button `Fedora 34 Workstation` on the upper left of the window.
|
||||
6. Your display is back to the initial window of GNOME Boxes, but there is a button `Fedora 34 Workstation` on the upper left of the window.
|
||||
Click on the button then Fedora will be executed.
|
||||
7. A setup dialog appears.
|
||||
Setup Fedora according to the wizard.
|
||||
|
||||
Now you can use Fedora.
|
||||
It includes Gtk4 libraries already.
|
||||
But you need to install the Gtk4 development package.
|
||||
It includes GTK 4 libraries already.
|
||||
But you need to install the GTK 4 development package.
|
||||
Use `dnf` to install `gtk4.x86_64` package.
|
||||
|
||||
~~~
|
||||
$ sudo dnf install gtk4.x86_64
|
||||
~~~
|
||||
|
||||
### Gtk4 compilation test
|
||||
### GTK 4 compilation test
|
||||
|
||||
You can test the Gtk4 development packages by compiling files which are based on Gtk4.
|
||||
You can test the GTK 4 development packages by compiling files which are based on GTK 4.
|
||||
I've tried compiling `tfe` text editor, which is written in section 21.
|
||||
|
||||
1. Run Firefox.
|
||||
|
|
|
@ -155,7 +155,7 @@ You can define more than one accelerator keys and the list must ends with NULL (
|
|||
If you want to do so, the array length needs to be three or more.
|
||||
The parser recognizes "\<control\>o", "\<Shift\>\<Alt\>F2", "\<Ctrl\>minus" and so on.
|
||||
If you want to use symbol key like "\<Ctrl\>-", use "\<Ctrl\>minus" instead.
|
||||
Such relation between lower case and symbol (its character code) is specified in [`gdkkeysyms.h`](https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/gdkkeysyms.h) in the Gtk4 source code.
|
||||
Such relation between lower case and symbol (its character code) is specified in [`gdkkeysyms.h`](https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/gdkkeysyms.h) in the GTK 4 source code.
|
||||
|
||||
## Saveas handler
|
||||
|
||||
|
@ -224,7 +224,7 @@ Transient-for specifies a temporary parent window, which the dialog's location i
|
|||
- internal-child attribute is used in the child tag above.
|
||||
GtkDialog has a GtkBox child widget.
|
||||
Its id is "content_area" in `gtkdialog.ui`, which is the ui file of GtkDialog.
|
||||
(It is in the Gtk4 source files.)
|
||||
(It is in the GTK 4 source files.)
|
||||
This box is provided for users to add content widgets in it.
|
||||
The tag `<child internal-child="content_area">` is put at the top of the contents.
|
||||
Then you need to specify an object tag and define its class as GtkBox and its id as content_area.
|
||||
|
@ -711,7 +711,7 @@ Other common types are:
|
|||
- "i": gint32.
|
||||
- "d": double.
|
||||
|
||||
Further information is in [Glib API Reference, VarientType](https://docs.gtk.org/glib/struct.VariantType.html).
|
||||
Further information is in [GLib API Reference, VarientType](https://docs.gtk.org/glib/struct.VariantType.html).
|
||||
|
||||
### gsettings
|
||||
|
||||
|
@ -781,7 +781,7 @@ org.gnome.calculator number-format 'automatic'
|
|||
org.gnome.calculator show-zeroes false
|
||||
~~~
|
||||
|
||||
This schema is used by Gnome Calculator.
|
||||
This schema is used by GNOME Calculator.
|
||||
Run the calculator and change the mode, then check the schema again.
|
||||
|
||||
~~~
|
||||
|
@ -808,7 +808,7 @@ org.gnome.calculator button-mode 'advanced'
|
|||
|
||||
~~~
|
||||
|
||||
Now we know that Gnome Calculator used gsettings and it has set `button-mode` key to "advanced".
|
||||
Now we know that GNOME Calculator used gsettings and it has set `button-mode` key to "advanced".
|
||||
The value remains even the calculator quits.
|
||||
So when the calculator is run again, it will appear as an advanced mode calculator.
|
||||
|
||||
|
@ -935,14 +935,14 @@ Just create a GSettings object and bind it to a property of an object.
|
|||
|
||||
## Installation
|
||||
|
||||
It is a good idea to install your application in `$HOME/local/bin` directory if you have installed Gtk4 from the source (See Section 2).
|
||||
It is a good idea to install your application in `$HOME/local/bin` directory if you have installed GTK 4 from the source (See Section 2).
|
||||
Then you need to put `--prefix=$HOME/local` option to meson like this.
|
||||
|
||||
~~~
|
||||
$ meson --prefix=$HOME/local _build
|
||||
~~~
|
||||
|
||||
If you've installed Gtk4 from the distribution package, `--prefix` option isn't necessary.
|
||||
If you've installed GTK 4 from the distribution package, `--prefix` option isn't necessary.
|
||||
You just install `tfe` to the default bin directory like `/usr/local/bin`.
|
||||
|
||||
Modify `meson.build` and add install option and set it true in executable function.
|
||||
|
|
|
@ -274,7 +274,7 @@ tfe7/meson.build
|
|||
|
||||
## Compilation and installation.
|
||||
|
||||
If you build Gtk4 from the source, use `--prefix` option.
|
||||
If you build GTK 4 from the source, use `--prefix` option.
|
||||
|
||||
~~~
|
||||
$ meson --prefix=$HOME/local _build
|
||||
|
@ -282,7 +282,7 @@ $ ninja -C _build
|
|||
$ ninja -C _build install
|
||||
~~~
|
||||
|
||||
If you install Gtk4 from the distribution packages, you don't need the prefix option.
|
||||
If you install GTK 4 from the distribution packages, you don't need the prefix option.
|
||||
Maybe you need root privilege to install it.
|
||||
|
||||
~~~
|
||||
|
|
|
@ -128,8 +128,8 @@ color/meson.build
|
|||
|
||||
## Compile and execute it
|
||||
|
||||
First you need to export some variables (refer to [Section 2](sec2.src.md)) if you've installed Gtk4 from the source.
|
||||
If you've installed Gtk4 from the distribution packages, you don't need to do this.
|
||||
First you need to export some variables (refer to [Section 2](sec2.src.md)) if you've installed GTK 4 from the source.
|
||||
If you've installed GTK 4 from the distribution packages, you don't need to do this.
|
||||
|
||||
$ . env.sh
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# GtkListView
|
||||
|
||||
Gtk4 has added new list objects GtkListView, GtkGridView and GtkColumnView.
|
||||
GTK 4 has added new list objects GtkListView, GtkGridView and GtkColumnView.
|
||||
The new feature is described in [Gtk API Reference, List Widget Overview](https://docs.gtk.org/gtk4/section-list-widget.html).
|
||||
|
||||
Gtk4 has other means to implement lists.
|
||||
They are GtkListBox and GtkTreeView which are took over from Gtk3.
|
||||
GTK 4 has other means to implement lists.
|
||||
They are GtkListBox and GtkTreeView which are took over from GTK 3.
|
||||
There's an article in [Gtk Development blog](https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/) about list widgets by Matthias Clasen.
|
||||
He described why GtkListView are developed to replace GtkListBox and GtkTreeView.
|
||||
|
||||
|
@ -65,7 +65,7 @@ There are functions to add items to the list or remove items from the list.
|
|||
- `gtk_string_list_remove` removes an item from the list
|
||||
- `gtk_string_list_get_string` gets a string in the list
|
||||
|
||||
See [Gtk4 API Reference, GtkStringList](https://docs.gtk.org/gtk4/class.StringList.html) for further information.
|
||||
See [GTK 4 API Reference, GtkStringList](https://docs.gtk.org/gtk4/class.StringList.html) for further information.
|
||||
|
||||
I'll explain the other list objects later.
|
||||
|
||||
|
@ -129,7 +129,7 @@ misc/list1.c
|
|||
|
||||
The file `list1.c` is located under the directory [src/misc](misc).
|
||||
Make a shell script below and save it to your bin directory.
|
||||
(If you've installed Gtk4 from the source to $HOME/local, then your bin directory is $Home/local/bin.
|
||||
(If you've installed GTK 4 from the source to $HOME/local, then your bin directory is $Home/local/bin.
|
||||
Otherwise, $Home/bin is your private bin directory.)
|
||||
|
||||
@@@if gfm
|
||||
|
|
|
@ -256,7 +256,7 @@ The third parameter is GAppLaunchContext, but this program gives NULL instead.
|
|||
The last parameter is the pointer to the pointer to a GError.
|
||||
- 34: `g_list_free_full` frees the memories used by the list and items.
|
||||
|
||||
If your distribution supports Gtk4, using `g_app_info_launch_default_for_uri` is convenient.
|
||||
If your distribution supports GTK 4, using `g_app_info_launch_default_for_uri` is convenient.
|
||||
The function automatically determines the default application from the file and launches it.
|
||||
For example, if the file is text, then it launches gedit with the file.
|
||||
Such functionality comes from desktop.
|
||||
|
|
|
@ -8,7 +8,7 @@ Usually people write programming code to make an application.
|
|||
What are applications?
|
||||
Applications are software that runs using libraries, which includes the
|
||||
OS, frameworks and so on.
|
||||
In Gtk4 programming, the GtkApplication is a program (or executable) that runs
|
||||
In GTK 4 programming, the GtkApplication is a program (or executable) that runs
|
||||
using Gtk libraries.
|
||||
|
||||
The basic way to write a GtkApplication is as follows.
|
||||
|
@ -241,7 +241,7 @@ As it destroys itself, the GtkWindow is also destroyed.
|
|||
|
||||
The function `gtk_widget_show` is used to show the window.
|
||||
|
||||
Gtk4 changes the default widget visibility to on, so every widget doesn't need this function to show itself.
|
||||
GTK 4 changes the default widget visibility to on, so every widget doesn't need this function to show itself.
|
||||
But, there's an exception.
|
||||
Top window (this term will be explained later) isn't visible when it is created.
|
||||
So you need to use the function above to show the window.
|
||||
|
|
|
@ -137,7 +137,7 @@ The array `b` is created on the stack then the function is called, disappears wh
|
|||
You can also get, use and release memory from the heap area.
|
||||
The standard C library provides `malloc` to get memory and `free` to put back memory.
|
||||
GLib provides the functions `g_new` and `g_free` to do the same thing, with support for
|
||||
some additional Glib functionality.
|
||||
some additional GLib functionality.
|
||||
|
||||
~~~C
|
||||
g_new (struct_type, n_struct)
|
||||
|
@ -186,7 +186,7 @@ g_free (t);
|
|||
|
||||
If the argument doesn't point allocated memory it will cause an error, specifically, a segmentation fault.
|
||||
|
||||
Some Glib functions allocate memory.
|
||||
Some GLib functions allocate memory.
|
||||
For example, `g_strdup` allocates memory and copies a string given as an argument.
|
||||
|
||||
~~~C
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Defining a Child object
|
||||
# Defining a child object
|
||||
|
||||
## A Very Simple Editor
|
||||
## A very simple editor
|
||||
|
||||
In the previous section we made a very simple file viewer.
|
||||
Now we go on to rewrite it and turn it into very simple editor.
|
||||
|
@ -52,7 +52,7 @@ particularly for beginners.
|
|||
So, I will just show you the way how to write the code and avoid the theoretical side.
|
||||
If you want to know about GObject system, refer to another [tutorial](https://github.com/ToshioCP/Gobject-tutorial).
|
||||
|
||||
## How to Define a Child Object of GtkTextView
|
||||
## How to define a child object of GtkTextView
|
||||
|
||||
Let's define the TfeTextView object, which is a child object of GtkTextView.
|
||||
First, look at the program below.
|
||||
|
|
Loading…
Add table
Reference in a new issue