mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2025-01-12 20:03:28 +01:00
Latex and pdf file generation is supported.
This commit is contained in:
parent
63434371c3
commit
568ecd439c
33 changed files with 251 additions and 46 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -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
|
||||
|
|
74
Rakefile
74
Rakefile
|
@ -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]
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
2
sec1.md
2
sec1.md
|
@ -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)
|
||||
|
|
2
sec10.md
2
sec10.md
|
@ -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)
|
||||
|
|
4
sec11.md
4
sec11.md
|
@ -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)
|
||||
|
|
12
sec12.md
12
sec12.md
|
@ -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)
|
||||
|
|
2
sec13.md
2
sec13.md
|
@ -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)
|
||||
|
|
8
sec14.md
8
sec14.md
|
@ -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)
|
||||
|
|
2
sec15.md
2
sec15.md
|
@ -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)
|
||||
|
|
2
sec16.md
2
sec16.md
|
@ -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)
|
||||
|
|
2
sec17.md
2
sec17.md
|
@ -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)
|
||||
|
|
2
sec2.md
2
sec2.md
|
@ -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)
|
||||
|
|
2
sec3.md
2
sec3.md
|
@ -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)
|
||||
|
|
2
sec4.md
2
sec4.md
|
@ -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)
|
||||
|
|
2
sec5.md
2
sec5.md
|
@ -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)
|
||||
|
|
2
sec6.md
2
sec6.md
|
@ -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)
|
||||
|
|
6
sec7.md
6
sec7.md
|
@ -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)
|
||||
|
|
2
sec8.md
2
sec8.md
|
@ -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)
|
||||
|
|
2
sec9.md
2
sec9.md
|
@ -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)
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
$$$
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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`.
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
Loading…
Reference in a new issue