Latex and pdf file generation is supported.

This commit is contained in:
Toshio Sekiya 2021-01-11 11:15:04 +09:00
parent 63434371c3
commit 568ecd439c
33 changed files with 251 additions and 46 deletions

1
.gitignore vendored
View file

@ -3,6 +3,7 @@
insertfunc.rb
pickoutfunc.rb
src/img.rb
src/imgsize.rb
src/toi.rb
src/misc/a.out
src/tfv/a.out

View file

@ -3,7 +3,6 @@ require 'rake/clean'
require_relative 'lib/lib_sec_file.rb'
require_relative 'lib/lib_src2md.rb'
srcfiles = []
FileList['src/*.src.md'].each do |file|
srcfiles << Sec_file.new(file)
@ -15,6 +14,12 @@ mdfilenames = srcfiles.map {|srcfile| srcfile.to_md}
htmlfilenames = srcfiles.map {|srcfile| "html/"+srcfile.to_html}
texfilenames = srcfiles.map {|srcfile| "latex/"+srcfile.to_tex}
["html", "latex"].each do |d|
if ! Dir.exist?(d)
Dir.mkdir(d)
end
end
CLEAN.append(*mdfilenames)
CLEAN << "Readme.md"
@ -72,6 +77,26 @@ You should be careful because there exists bugs, errors or mistakes.
<ul>
EOS
# Preamble for latex files.
main = <<'EOS'
\documentclass[a4paper]{article}
\include{helper.tex}
\title{Gtk4 tutorial for beginners}
\author{Toshio Sekiya}
\begin{document}
\maketitle
\tableofcontents
EOS
helper = <<'EOS'
\usepackage[pdftex]{graphicx}
\usepackage[colorlinks=true,linkcolor=black]{hyperref}
\usepackage[margin=2.4cm]{geometry}
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
EOS
# tasks
task default: :md
@ -93,7 +118,7 @@ end
0.upto(srcfiles.size - 1) do |i|
file srcfiles[i].to_md => (srcfiles[i].c_files << srcfiles[i].path) do
src2md srcfiles[i].path, srcfiles[i].to_md
src2md srcfiles[i].path, srcfiles[i].to_md, -1
if srcfiles.size == 1
nav = "Up: [Readme.md](Readme.md)\n"
elsif i == 0
@ -116,7 +141,7 @@ file "html/index.html" do
0.upto(srcfiles.size-1) do |i|
h = File.open(srcfiles[i].path) { |file| file.readline }
h = h.gsub(/^#* */,"").chomp
file_index = file_index + "<li> <a href=\"#{srcfiles[i].to_html}\">#{h}</a> </li>\n"
file_index += "<li> <a href=\"#{srcfiles[i].to_html}\">#{h}</a> </li>\n"
end
file_index += ("</ul>\n" + tail)
IO.write("html/index.html",file_index)
@ -124,7 +149,12 @@ end
0.upto(srcfiles.size - 1) do |i|
file "html/"+srcfiles[i].to_html => (srcfiles[i].c_files << srcfiles[i].path) do
src2md srcfiles[i].path, "html/"+srcfiles[i].to_md
src2md srcfiles[i].path, "html/"+srcfiles[i].to_md, -1
buf = IO.readlines "html/"+srcfiles[i].to_md
buf.each do |line|
line.gsub!(/(\[[^\]]*\])\((sec\d+)\.md\)/,"\\1(\\2.html)")
end
IO.write "html/"+srcfiles[i].to_md, buf.join
sh "pandoc -o html/#{srcfiles[i].to_html} html/#{srcfiles[i].to_md}"
File.delete("html/#{srcfiles[i].to_md}")
if srcfiles.size == 1
@ -147,7 +177,41 @@ end
end
end
task pdf: "latex" do
sh "cd latex; pdflatex main.tex"
sh "cd latex; pdflatex main.tex"
sh "mv latex/main.pdf latex/gtk4_tutorial.pdf"
end
task latex: texfilenames+["latex/main.tex"]
file "latex/main.tex" do
0.upto(srcfiles.size-1) do |i|
main += " \\input{#{srcfiles[i].to_tex}}\n"
end
main += "\\end{document}\n"
IO.write("latex/main.tex", main)
IO.write("latex/helper.tex", helper)
end
0.upto(srcfiles.size - 1) do |i|
file "latex/"+srcfiles[i].to_tex => (srcfiles[i].c_files << srcfiles[i].path) do
src2md srcfiles[i].path, "latex/"+srcfiles[i].to_md, 80
sh "pandoc -o latex/#{srcfiles[i].to_tex} latex/#{srcfiles[i].to_md}"
File.delete("latex/#{srcfiles[i].to_md}")
end
end
task :clean
task :cleanhtml do
sh "rm html/*"
if Dir.exist?("html") && (! Dir.empty?("html"))
sh "rm html/*"
end
end
task :cleanlatex do
if Dir.exist?("latex") && (! Dir.empty?("latex"))
sh "rm latex/*"
end
end
task cleanall: [:clean, :cleanhtml, :cleanlatex]

View file

@ -1,8 +1,61 @@
# lib_src2md.rb
require 'pathname'
def src2md srcmd, md
# The method 'src2md' convert .src.md file into .md file.
# The output .md file is fit for the final format, which is one of markdown, html and latex.
# - Links to relative URL are removed for latex. Otherwise, it remains.
# See "Hyperref and relative link" below for further explanation.
# - Width and height for images are removed for markdown and html. it remains for latex.
# ![sample](sample_image){width=10cm height=5cm} => ![sample](sample_image) for markdown and html
# ---- Hyperref and relative link ----
# Hyperref package makes internal link possible.
# The target of the link is made with '\hypertarget' command.
# And the link is made with '\hyperlink' command.
# For example,
# (sec11.tex)
# \hyperlink{tfeapplication.c}{Section 13}
# ... ...
# (sec13.tex)
# \hypertarget{tfeapplication.c}{%
# \section{tfeapplication.c}\label{tfeapplication.c}}
# If you click the text 'Section 13' in sec11.tex, then you can move to '13 tfeapplication.c', which is section 13 in sec13.tex.
# The following lines are the original one in sec11.md and the result in sec11.tex, which is generated by pandoc.
# (sec11.md)
# All the source files are listed in [Section 13](sec13.tex).
# (sec11.tex)
# All the source files are listed in \href{sec13.tex}{Section 13}.
# Therefore, if you want to correct the link in sec11.tex, you need to do the followings.
# 1. Look at the first line of sec13.md and get the section heading (tfeapplication.c).
# 2. substitute "\hyperlink{tfeapplication.c}{Section 13}" for "\href{sec13.tex}{Section 13}".
# The following lines are another conversion case by pandoc.
# (sec7.md)
# The source code of `tfe3.c` is stored in [src/tfe](../src/tfe) directory.
# (sec7.tex)
# The source code of \texttt{tfe3.c} is stored in \href{../src/tfe}{src/tfe} directory.
# The pdf file generated by pdflatex recognizes that the link 'href{../src/tfe}' points a pdf file '../src/tfe.pdf'.
# To avoid generating such incorrect links, it is good to remove the links from the original markdown file.
# If the target is full URL, which means absolute URL begins with "http", no problem happens.
# This Rakefile just remove the links if its target is relative URL.
# If you want to revive the link with relative URL, refer the description above.
# ---- Folding verbatim lines ----
# When C sourcefiles or subshell output are included, the lines are folded to fit in 'width'.
# Before they are folded, four space characters are prepended to the line.
# Therefore, 'width' must be at least five.
# Otherwise the lines are not folded.
def src2md srcmd, md, width
src_buf = IO.readlines srcmd
src_dir = File.dirname srcmd
md_dir = File.dirname md
# type is 'the type of the target', which is one of "markdown", "html" and "latex".
type = md_dir == "." ? "markdown" : md_dir
md_buf = []
comflag = false
src_buf.each do |line|
@ -55,16 +108,53 @@ def src2md srcmd, md
end
end
end
width = tmp_buf.size.to_s.length
ln_width = tmp_buf.size.to_s.length
n = 1
tmp_buf.each do |l|
md_buf << sprintf(" %#{width}d %s", n, l)
l = sprintf(" %#{ln_width}d %s", n, l)
md_buf << l
n += 1
end
else
md_buf << line.gsub(/(!\[[^\]]*\])\(..\/([^\)]*)\)/, "\\1(\\2)")
md_buf << change_rel_link(line, src_dir, File.dirname(md))
end
end
tmp_buf = md_buf
md_buf = []
tmp_buf.each do |line|
if line =~ /^ / && width.instance_of?(Integer) && width >= 5
indent = line =~ /^( *\d+ +)/ ? " "*$1.length : " "
while line.instance_of?(String) && line.length > width
md_buf << line[0, width]+"\n"
line = line[width .. -1].gsub(/^/,indent)
end
elsif type == "latex"
line.gsub!(/(^|[^!])\[([^\]]*)\]\((?~http)\)/,"\\1\\2") # remove link
else # type == "markdown" or "html"
line.gsub!(/(!\[[^\]]*\]\([^\)]*\)) *{width *= *\d*(|\.\d*)cm *height *= *\d*(|\.\d*)cm}/,"\\1")
end
md_buf << line
end
IO.write(md,md_buf.join)
end
def change_rel_link line, src_dir, basedir
p_basedir = Pathname.new basedir
left = ""
right = line
while right =~ /(!?\[[^\]]*\])\((.*)\)/
left = $`
right = $'
name = $1
link = $2
if name =~ /\[(S|s)ection (\d+)\]/
link = "sec#{$2}.md"
elsif ! (link =~ /^(http|\/)/)
p_link = Pathname.new "#{src_dir}/#{link}"
link = p_link.relative_path_from(p_basedir).to_s
end
left += "#{name}(#{link})"
end
left + right
end

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Next: [Section 2](sec2.md)
# Prerequisite and Licence
## Prerequisite
@ -51,4 +52,5 @@ as published by the Free Software Foundation; either version 3 of the License, o
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)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 9](sec9.md), Next: [Section 11](sec11.md)
# Signals
## Signals
@ -160,4 +161,5 @@ The following is extract from `tfetexties.c`.
- "open-response" signal has one parameter.
The fourth parameter is the parameter.
Up: [Readme.md](Readme.md), Prev: [Section 9](sec9.md), Next: [Section 11](sec11.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 10](sec10.md), Next: [Section 12](sec12.md)
# Functions in TfeTextView
In this section I will explain each function in TfeTextView object.
@ -356,6 +357,7 @@ Otherwise, if the caller free the GFile object, `tv->file` is no more guaranteed
## Source file of tfetextview.c
All the source files are listed in [Section 13](https://github.com/ToshioCP/Gtk4-tutorial/blob/main/sec13.md).
All the source files are listed in [Section 14](sec14.md).
Up: [Readme.md](Readme.md), Prev: [Section 10](sec10.md), Next: [Section 12](sec12.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 11](sec11.md), Next: [Section 13](sec13.md)
# Functions with GtkNotebook
GtkNotebook is a very important object in the text file editor `tfe`.
@ -26,7 +27,15 @@ The GFile `file` is copied and set in the TfeTextView object.
- 4-5: `notebook_page_open` shows a file chooser dialog. Then, user chooses a file and the file is set into GtkTextBuffer.
- 1-2: `notebook_page_save` saves the contents in GtkTextBuffer into the file, which has been set in the TfeTextView.
You probably find that the functions above are higher level functions of `tfe_text_view_new`, `tfe_text_view_new_with_file`, `tef_text_view_open` and `tfe_text_view_save` respectively.
You probably find that the functions above are higher level functions of
- `tfe_text_view_new`
- `tfe_text_view_new_with_file`
- `tef_text_view_open`
- `tfe_text_view_save`
respectively.
There are two layers.
One of them is `tfe_text_view ...`, which is the lower level layer.
The other is `note_book ...`, which is the higher level layer.
@ -208,4 +217,5 @@ Otherwise (file is NULL), assign untitled string to `filename`.
- 16-17: Free `filename` and unref `file`.
Up: [Readme.md](Readme.md), Prev: [Section 11](sec11.md), Next: [Section 13](sec13.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 12](sec12.md), Next: [Section 14](sec14.md)
# tfeapplication.c
`tfeapplication.c` includes all the code other than `tfetxtview.c` and `tfenotebook.c`.
@ -267,4 +268,5 @@ First, get the top level window and call `gtk_window_destroy`.
In this file, just the source file names are modified.
Up: [Readme.md](Readme.md), Prev: [Section 12](sec12.md), Next: [Section 14](sec14.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 13](sec13.md), Next: [Section 15](sec15.md)
# tfe5 source files
The followings are the source files of tfe5.
@ -219,7 +220,7 @@ The followings are the source files of tfe5.
116 }
117
### tfenotebook.h
## tfenotebook.h
1 void
2 notebook_page_save(GtkNotebook *nb);
@ -608,7 +609,7 @@ The followings are the source files of tfe5.
## Total number of lines, words and charcters
$ wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfe5/tfetextview.c tfe5/tfetextview.h tfe5/tfe.ui
$ LANG=C wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfe5/tfetextview.c tfe5/tfetextview.h tfe5/tfe.ui
10 17 279 tfe5/meson.build
117 348 3576 tfe5/tfeapplication.c
6 9 153 tfe5/tfe.gresource.xml
@ -618,5 +619,6 @@ The followings are the source files of tfe5.
218 635 7769 tfe5/tfetextview.c
29 49 561 tfe5/tfetextview.h
64 105 2266 tfe5/tfe.ui
576 1507 17864 合計
576 1507 17864 total
Up: [Readme.md](Readme.md), Prev: [Section 13](sec13.md), Next: [Section 15](sec15.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 14](sec14.md), Next: [Section 16](sec16.md)
# Menu and action
## Menu
@ -213,4 +214,5 @@ The structure of the menu is shown in the diagram below.
![Screenshot of menu1](image/menu1_screenshot.png)
Up: [Readme.md](Readme.md), Prev: [Section 14](sec14.md), Next: [Section 16](sec16.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 15](sec15.md), Next: [Section 17](sec17.md)
# Stateful action
Some actions have states.
@ -368,4 +369,5 @@ Other GtkLabel have no effect from this.
The provider is added to GdkDisplay.
- 90: Show the window.
Up: [Readme.md](Readme.md), Prev: [Section 15](sec15.md), Next: [Section 17](sec17.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 16](sec16.md)
# Ui file for menu and action entries
## Ui file for menu
@ -336,4 +337,5 @@ meson.build
9
10 executable('menu3', sourcefiles, resources, dependencies: gtkdep)
Up: [Readme.md](Readme.md), Prev: [Section 16](sec16.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md)
# GtkApplication and GtkApplicationWindow
## GtkApplication
@ -282,4 +283,5 @@ The program sets the title and the default size of the window.
Compile it and run `a.out`, then you will see a bigger window with its title "pr4".
![Screenshot of the window](image/screenshot_pr4.png)
Up: [Readme.md](Readme.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.md)
# Widgets (1)
## GtkLabel, GtkButton and Gtkbox
@ -313,4 +314,5 @@ Then, these two buttons are appended to the box.
The handler corresponds to `btn1` changes its label.
The handler corresponds to `btn2` destroys the top-level window and the application quits.
Up: [Readme.md](Readme.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 3](sec3.md), Next: [Section 5](sec5.md)
# Widgets (2)
## GtkTextView, GtkTextbuffer and GtkScrolledWindow
@ -162,4 +163,5 @@ Now compile and run it.
This time the window doesn't extend even if you type a lot of characters.
It just scrolls.
Up: [Readme.md](Readme.md), Prev: [Section 3](sec3.md), Next: [Section 5](sec5.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 4](sec4.md), Next: [Section 6](sec6.md)
# Widgets (3)
## Open signal
@ -302,4 +303,5 @@ The numbers at the left of the following items are line numbers in the source co
- 46: free the memory pointed by `filename`
- 53-56: If at least one file was read, then the number of GtkNotebookPage is greater than zero. If it's true, then show the window. If it's false, then destroy the window.
Up: [Readme.md](Readme.md), Prev: [Section 4](sec4.md), Next: [Section 6](sec6.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 5](sec5.md), Next: [Section 7](sec7.md)
# Define Child object
## Very simple editor
@ -347,4 +348,5 @@ 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 5](sec5.md), Next: [Section 7](sec7.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 6](sec6.md), Next: [Section 8](sec8.md)
# Ui file and GtkBuiler
## New, open and save button
@ -343,9 +344,9 @@ Only functions `on_open` are shown as follows.
47 gtk_window_destroy (GTK_WINDOW (win));
48 }
The source code of `tfe3.c` is stored in [src/tfe](https://github.com/ToshioCP/Gtk4-tutorial/tree/main/src/tfe) directory.
The source code of `tfe3.c` is stored in [src/tfe](src/tfe) directory.
If you want to see it, click the link above.
In the same way, you can get the source files below in the directory [src/tfe](https://github.com/ToshioCP/Gtk4-tutorial/tree/main/src/tfe).
In the same way, you can get the source files below in the directory [src/tfe](src/tfe).
### Using ui string
@ -450,4 +451,5 @@ Modify tfe3.c and save it as tfe3_r.c
Then, compile and run it.
The window appears and it is the same as the screenshot at the beginning of this page.
Up: [Readme.md](Readme.md), Prev: [Section 6](sec6.md), Next: [Section 8](sec8.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 7](sec7.md), Next: [Section 9](sec9.md)
# Build system
## What do we need to think about to manage big source files?
@ -423,4 +424,5 @@ I think meson and ninja is the best choice for the present.
We divided a file into some categorized files and used a build tool.
This method is used by many developers.
Up: [Readme.md](Readme.md), Prev: [Section 7](sec7.md), Next: [Section 9](sec9.md)

View file

@ -1,4 +1,5 @@
Up: [Readme.md](Readme.md), Prev: [Section 8](sec8.md), Next: [Section 10](sec10.md)
# Instance and class
This section and the following four sections are explanations about the next version of the text file editor (tfe).
@ -416,4 +417,5 @@ And `gobject` is a pointer to TfeTextView instance which is casted as a GObject
After that, `dh3` calls `dh2`, and `dh2` calls `dh1`.
Finally all the references are released.
Up: [Readme.md](Readme.md), Prev: [Section 8](sec8.md), Next: [Section 10](sec10.md)

View file

@ -108,7 +108,7 @@ The buttons are Cancel and Save.
- 1-16: `saveas_dialog_response` signal handler.
- 6-14: If the response is `GTK_RESPONSE_ACCEPT`, which is set to the argument when the user has clicked on Save button, then gets a pointer to the GFile object, set it to `tv->file`, turn on the modified bit of the GtkTextBuffer, emits "change-file" signal then call `tfe_text_view_save` to save the buffer to the file.
![Saveas process](../image/saveas.png)
![Saveas process](../image/saveas.png){width=10.7cm height=5.16cm}
When you use GtkFileChooserDialog, you need to divide the program into two parts.
They are a function which generates GtkFileChooserDialog and the signal handler.
@ -159,7 +159,7 @@ In Gtk3, `gtk_dialog_run` function is available.
It simplifies the process.
However, in Gtk4, `gtk_dialog_run`is unavailable any more.
![Caller and TfeTextView](../image/open.png)
![Caller and TfeTextView](../image/open.png){width=12.405cm height=9.225cm}
1. A caller get a pointer `tv` to TfeTextView by calling `tfe_text_view_new`.
2. The caller connects the handler (left bottom in the diagram) and the signal "open-response".
@ -179,5 +179,5 @@ Otherwise, if the caller free the GFile object, `tv->file` is no more guaranteed
## Source file of tfetextview.c
All the source files are listed in [Section 13](https://github.com/ToshioCP/Gtk4-tutorial/blob/main/sec13.md).
All the source files are listed in [Section 14](sec14.src.md).

View file

@ -14,7 +14,15 @@ The GFile `file` is copied and set in the TfeTextView object.
- 4-5: `notebook_page_open` shows a file chooser dialog. Then, user chooses a file and the file is set into GtkTextBuffer.
- 1-2: `notebook_page_save` saves the contents in GtkTextBuffer into the file, which has been set in the TfeTextView.
You probably find that the functions above are higher level functions of `tfe_text_view_new`, `tfe_text_view_new_with_file`, `tef_text_view_open` and `tfe_text_view_save` respectively.
You probably find that the functions above are higher level functions of
- `tfe_text_view_new`
- `tfe_text_view_new_with_file`
- `tef_text_view_open`
- `tfe_text_view_save`
respectively.
There are two layers.
One of them is `tfe_text_view ...`, which is the lower level layer.
The other is `note_book ...`, which is the higher level layer.

View file

@ -22,7 +22,7 @@ The followings are the source files of tfe5.
@@@ tfe5/tfeapplication.c
### tfenotebook.h
## tfenotebook.h
@@@ tfe5/tfenotebook.h
@ -41,5 +41,5 @@ The followings are the source files of tfe5.
## Total number of lines, words and charcters
$$$
wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfe5/tfetextview.c tfe5/tfetextview.h tfe5/tfe.ui
LANG=C wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfe5/tfetextview.c tfe5/tfetextview.h tfe5/tfe.ui
$$$

View file

@ -5,7 +5,7 @@
Users often use menus to tell the command to the computer.
It is like this:
![Menu](../image/menu.png)
![Menu](../image/menu.png){width=5.985cm height=5.055cm}
Now let's analyze the menu above.
There are two types of object.
@ -18,7 +18,7 @@ They are called "menu".
Menu is an ordered list of items.
They are similar to arrays.
![Menu structure](../image/menu_structure.png)
![Menu structure](../image/menu_structure.png){width=10.23cm height=3.57cm}
- Menubar is a menu which has three items, which are "File", "Edit" and "View".
- The menu item labeled "Edit" has a link to the submenu which has two items.
@ -162,7 +162,7 @@ The structure of the menu is shown in the diagram below.
- 30: Set GtkApplicationWindow to show the menubar.
- 31: Show the window.
![menu and action](../image/menu1.png)
![menu and action](../image/menu1.png){width=12.555cm height=3.285cm}
![Screenshot of menu1](../image/menu1_screenshot.png)
![Screenshot of menu1](../image/menu1_screenshot.png){width=6.0cm height=5.115cm}

View file

@ -197,7 +197,7 @@ It is the string "s" given at the generation time.
The following code includes stateful actions above.
This program has menus like this:
![menu2](../image/menu2.png)
![menu2](../image/menu2.png){width=6.03cm height=5.115cm}
- 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.

View file

@ -57,7 +57,7 @@ So, we usually prefer the former ui file style.
The following is a screenshot of the sample program in this section.
Its name is `menu3`.
![menu3](../image/menu3.png)
![menu3](../image/menu3.png){width=6.0cm height=5.055cm}
The following is the ui file of the menu in `menu3`.

View file

@ -163,7 +163,7 @@ And GtkWidget is a base object from which all the GUI objects derive.
GtkWindow includes GtkWidget at the top of its object.
![GtkWindow and GtkWidget](../image/window_widget.png)
![GtkWindow and GtkWidget](../image/window_widget.png){width=9.0cm height=6.0cm}
The function `gtk_window_new` is defined as follows.
@ -214,7 +214,7 @@ Save the program as `pr3.c` and compile and run it.
A small window appears.
![Screenshot of the window](../image/screenshot_pr3.png)
![Screenshot of the window](../image/screenshot_pr3.png){width=3.3cm height=3.825cm}
Click on the close button then the window disappears and the program finishes.
@ -235,4 +235,4 @@ So you don't need to call `gtk_window_set_application` any more.
The program sets the title and the default size of the window.
Compile it and run `a.out`, then you will see a bigger window with its title "pr4".
![Screenshot of the window](../image/screenshot_pr4.png)
![Screenshot of the window](../image/screenshot_pr4.png){width=6.3cm height=5.325cm}

View file

@ -19,7 +19,7 @@ Then compile and run it.
A window with a message "Hello." appears.
![Screenshot of the label](../image/screenshot_lb1.png)
![Screenshot of the label](../image/screenshot_lb1.png){width=6.3cm height=5.325cm}
There's only a little change between `pr4.c` and `lb1.c`.
Diff is a good program to know the difference between two files.
@ -69,7 +69,7 @@ The suffix cb means "call back".
Name the program `lb2.c` and save it.
Now compile and run it.
![Screenshot of the label](../image/screenshot_lb2.png)
![Screenshot of the label](../image/screenshot_lb2.png){width=11.205cm height=6.945cm}
A window with the button appears.
Click the button (it is a large button, you can click everywhere inside the window), then a string "Clicked." appears on the shell terminal.
@ -115,7 +115,7 @@ The following procedure shows the way to add two buttons in a window.
After this, the Widgets are connected as following diagram.
![Parent-child relationship](../image/box.png)
![Parent-child relationship](../image/box.png){width=7.725cm height=2.055cm}
Now, code it.
@ -135,7 +135,7 @@ The next function fills a box with children, giving them equal space.
After that, two buttons `btn1` and `btn2` are generated and the signal handlers are set.
Then, these two buttons are appended to the box.
![Screenshot of the box](../image/screenshot_lb4.png)
![Screenshot of the box](../image/screenshot_lb4.png){width=6.3cm height=5.325cm}
The handler corresponds to `btn1` changes its label.
The handler corresponds to `btn2` destroys the top-level window and the application quits.

View file

@ -23,7 +23,7 @@ In line 30, `tv` is set to `win` as a child.
Now compile and run it.
![GtkTextView](../image/screenshot_tfv1.png)
![GtkTextView](../image/screenshot_tfv1.png){width=6.3cm height=5.325cm}
There's an I-beam pointer in the window.
You can add or delete any characters on GtkTextview.

View file

@ -95,7 +95,7 @@ Then compile and run it.
$ comp tfv3
$ ./a.out tfv3.c
![File viewer](../image/screenshot_tfv3.png)
![File viewer](../image/screenshot_tfv3.png){width=6.3cm height=5.325cm}
Now I want to explain the program `tfv3.c`.
First, the function `main` changes in only two lines.
@ -142,7 +142,7 @@ If it fails, it outputs an error message and destroys the window.
GtkNotebook is a container widget that contains multiple children with tabs in it.
![GtkNotebook](../image/screenshot_gtk_notebook.png)
![GtkNotebook](../image/screenshot_gtk_notebook.png){width=13.2cm height=5.325cm}
Look at the screenshots above.
The left one is a window at the startup.

View file

@ -39,7 +39,7 @@ What we are thinking about now is "child object".
A child object includes its parent object.
And a child object derives everything from the parent object.
![Child widget of GtkTwxtView](../image/child.png)
![Child widget of GtkTwxtView](../image/child.png){width=9.675cm height=4.89cm}
We will define TfeTextView as a child object of GtkTextView.
It has everything that GtkTextView has.

View file

@ -9,7 +9,7 @@ It is better to make "New", "Open", "Save" and "Close" buttons.
This section describes how to put those buttons into the window.
Signals and handlers will be explained later.
![Screenshot of the file editor](../image/screenshot_tfe2.png)
![Screenshot of the file editor](../image/screenshot_tfe2.png){width=9.3cm height=6.825cm}
The screenshot above shows the layout.
The function `on_open` in the source code `tfe2.c` is as follows.
@ -97,9 +97,9 @@ Only functions `on_open` are shown as follows.
@@@ tfe/tfe3.c on_open
The source code of `tfe3.c` is stored in [src/tfe](https://github.com/ToshioCP/Gtk4-tutorial/tree/main/src/tfe) directory.
The source code of `tfe3.c` is stored in [src/tfe](tfe) directory.
If you want to see it, click the link above.
In the same way, you can get the source files below in the directory [src/tfe](https://github.com/ToshioCP/Gtk4-tutorial/tree/main/src/tfe).
In the same way, you can get the source files below in the directory [src/tfe](tfe).
### Using ui string

View file

@ -86,7 +86,7 @@ This is very important.
It guarantees a child widget to derive all the features from ancestors.
The structure of `TfeTextView` is like the following diagram.
![The structure of the instance TfeTextView](../image/TfeTextView.png)
![The structure of the instance TfeTextView](../image/TfeTextView.png){width=14.39cm height=2.16cm}
## Generate TfeTextView instance
@ -186,7 +186,7 @@ Override is rewriting ancestors' class methods in the descendent class.)
TfeTextViewClass includes its ancsestors' class in it.
It is illustrated in the following diagram.
![The structure of TfeTextView Class](../image/TfeTextViewClass.png)
![The structure of TfeTextView Class](../image/TfeTextViewClass.png){width=16.02cm height=8.34cm}
## Destruction of TfeTextView
@ -202,7 +202,7 @@ At this moment, no object refers C and the reference count of C is zero.
This means C is no longer useful.
Then C destructs itself and finally the memories allocated to C is freed.
![Reference count of B](../image/refcount.png)
![Reference count of B](../image/refcount.png){width=15.855cm height=2.475cm}
The idea above is based on an assumption that an object refered by nothing has reference count of zero.
When the reference count drops to zero, the object starts its destruction process.
@ -238,7 +238,7 @@ Look at the following diagram.
There are four classes -- GObjectClass (GInitiallyUnownedClass), GtkWidgetClass, GtkTextViewClass and TfeTextViewClass.
Each class has its own dispose handler -- `dh1`, `dh2`, `dh3` and `tfe_text_view_dispose`.
![dispose handers](../image/dispose_handler.png)
![dispose handers](../image/dispose_handler.png){width=14.925cm height=4.455cm}
Now, look at the `tfe_text_view_dispose` program above.
It first releases the reference to GFile object pointed by `tv->file`.