├── .gitignore
├── .test
├── .travis.yml
├── Gopkg.lock
├── Gopkg.toml
├── LICENSE
├── Makefile
├── README.md
├── TODO
├── _example
├── action
│ └── action.go
├── alignment
│ └── alignment.go
├── arrow
│ └── arrow.go
├── builder
│ ├── builder.go
│ ├── callback
│ │ └── callback.go
│ └── hello.ui
├── clipboard
│ └── clipboard.go
├── demo
│ └── demo.go
├── dnd
│ └── dnd.go
├── drawable
│ └── drawable.go
├── event
│ └── event.go
├── example.mk
├── expander
│ └── expander.go
├── iconview
│ └── iconview.go
├── idle
│ └── idle.go
├── listview
│ └── listview.go
├── locale
│ └── locale.go
├── notebook
│ └── notebook.go
├── number
│ └── number.go
├── sourceview
│ └── sourceview.go
├── spinbutton
│ └── spinbutton.go
├── statusicon
│ └── statusicon.go
├── table
│ └── table.go
├── textview
│ └── textview.go
├── thread
│ └── thread.go
├── toolbar
│ └── toolbar.go
├── toolpalette
│ ├── toolpalette.go
│ └── turkey.jpg
├── treeview
│ └── treeview.go
└── twitterstream
│ ├── settings.json.example
│ └── twitterstream.go
├── data
├── go-gtk-logo.png
├── mattn-logo.png
├── win32-demo.png
└── win32-twitter.png
├── gdk
├── gdk.go
├── gdk.go.h
├── gdk_freebsd.go
├── gdk_linux.go
├── gdk_quartz_darwin.go
├── gdk_windows.go
└── gdk_x11_darwin.go
├── gdkpixbuf
├── gdkpixbuf.go
└── gdkpixbuf.go.h
├── gio
├── gio.go
└── gio.go.h
├── glib
├── glib.go
└── glib.go.h
├── gtk
├── gtk.go
├── gtk.go.h
├── gtk_internal_test.go
├── gtk_test.go
└── gtk_x11.go
├── gtkgl
├── gdkgl.go
├── gtkgl.go.h
└── gtkglarea.go
├── gtksourceview
├── gtksourceview.go
└── gtksourceview.go.h
├── gtkspell
└── gtkspell.go
├── pango
├── pango.go
└── pango.go.h
└── tools
├── gogtkinfo
└── gogtkinfo.go
└── make_inline_pixbuf
└── make_inline_pixbuf.go
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | _obj
3 | *.cgo?.*
4 | _cgo_*
5 | main
6 | *.exe
7 | tags
8 | .idea
9 | vendor
10 |
11 | # example binaries
12 | example/action/action
13 | example/alignment/alignment
14 | example/arrow/arrow
15 | example/builder/builder
16 | example/clipboard/clipboard
17 | example/demo/demo
18 | example/dnd/dnd
19 | example/drawable/drawable
20 | example/event/event
21 | example/expander/expander
22 | example/iconview/iconview
23 | example/listview/listview
24 | example/locale/locale
25 | example/notebook/notebook
26 | example/number/number
27 | example/sourceview/sourceview
28 | example/spinbutton/spinbutton
29 | example/statusicon/statusicon
30 | example/table/table
31 | example/thread/thread
32 | example/toolbar/toolbar
33 | example/treeview/treeview
34 | example/twitterstream/twitterstream
35 |
36 | coverage.txt
37 |
38 | *.swp
39 |
--------------------------------------------------------------------------------
/.test:
--------------------------------------------------------------------------------
1 | make example
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | go:
4 | - 1.6
5 | - 1.7
6 | - 1.8
7 | - 1.9.3
8 |
9 | env:
10 | global:
11 | - DEP_VERSION="0.4.1"
12 | - secure: "ByVmoy5LqIJf/hn3G/eNasDasbTkG5jud7ZumMTUP+gdBE98/olKffQXkrfFKq1e6My5G/XVp9tTEB7fz1hKxFpOwOAr/OwTTGqXRieNZhV/YQKKepAUvQE5XxAxbiV9RqsaLCcErlvAJgidn9cJAtnjvtvSncy/k1r5DIUsZIM="
13 |
14 | before_install:
15 | # Download the binary to bin folder in $GOPATH
16 | - curl -L -s https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 -o $GOPATH/bin/dep
17 | # Make the binary executable
18 | - chmod +x $GOPATH/bin/dep
19 |
20 | install:
21 | - dep ensure
22 |
23 | script: xvfb-run go test -v -race -coverprofile=coverage.txt -covermode=atomic ./gtk
24 |
25 | after_success:
26 | - bash <(curl -s https://codecov.io/bash)
27 |
28 | addons:
29 | apt:
30 | packages:
31 | - libgtk2.0-dev
32 | - xvfb
33 |
--------------------------------------------------------------------------------
/Gopkg.lock:
--------------------------------------------------------------------------------
1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
2 |
3 |
4 | [[projects]]
5 | name = "github.com/davecgh/go-spew"
6 | packages = ["spew"]
7 | revision = "346938d642f2ec3594ed81d874461961cd0faa76"
8 | version = "v1.1.0"
9 |
10 | [[projects]]
11 | branch = "master"
12 | name = "github.com/mattn/go-pointer"
13 | packages = ["."]
14 | revision = "1d30dc4b6f28271a3bd126071d4d0363e618415b"
15 |
16 | [[projects]]
17 | name = "github.com/pmezard/go-difflib"
18 | packages = ["difflib"]
19 | revision = "792786c7400a136282c1664665ae0a8db921c6c2"
20 | version = "v1.0.0"
21 |
22 | [[projects]]
23 | name = "github.com/stretchr/testify"
24 | packages = ["assert"]
25 | revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
26 | version = "v1.2.1"
27 |
28 | [solve-meta]
29 | analyzer-name = "dep"
30 | analyzer-version = 1
31 | inputs-digest = "a295491a6204f7afbbd0d9296cb3f5e4878c06352e31b9afdea4a19ba26aa083"
32 | solver-name = "gps-cdcl"
33 | solver-version = 1
34 |
--------------------------------------------------------------------------------
/Gopkg.toml:
--------------------------------------------------------------------------------
1 | # Gopkg.toml example
2 | #
3 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
4 | # for detailed Gopkg.toml documentation.
5 | #
6 | # required = ["github.com/user/thing/cmd/thing"]
7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8 | #
9 | # [[constraint]]
10 | # name = "github.com/user/project"
11 | # version = "1.0.0"
12 | #
13 | # [[constraint]]
14 | # name = "github.com/user/project2"
15 | # branch = "dev"
16 | # source = "github.com/myfork/project2"
17 | #
18 | # [[override]]
19 | # name = "github.com/x/y"
20 | # version = "2.4.0"
21 | #
22 | # [prune]
23 | # non-go = false
24 | # go-tests = true
25 | # unused-packages = true
26 |
27 |
28 | [[constraint]]
29 | branch = "master"
30 | name = "github.com/garyburd/go-oauth"
31 |
32 | [[constraint]]
33 | branch = "master"
34 | name = "github.com/mattn/go-pointer"
35 |
36 | [[constraint]]
37 | name = "github.com/stretchr/testify"
38 | version = "1.2.1"
39 |
40 | [prune]
41 | go-tests = true
42 | unused-packages = true
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Yasuhiro Matsumoto
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors
14 | may be used to endorse or promote products derived from this software without
15 | specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | include _example/example.mk
2 |
3 | .DEFAULT_GOAL := all
4 | .PHONY: all
5 | all:
6 | cd pango && go get -x
7 | cd glib && go get -x
8 | cd gdk && go get -x
9 | cd gdkpixbuf && go get -x
10 | cd gtk && go get -x
11 | cd gtksourceview && go get -x
12 | #cd gtkgl && go get -x .
13 | #cd gtkspell && go get -x .
14 |
15 | .PHONY: all
16 | fmt:
17 | cd pango && go fmt .
18 | cd glib && go fmt .
19 | cd gdk && go fmt .
20 | cd gdkpixbuf && go fmt .
21 | cd gtk && go fmt .
22 | cd gtksourceview && go fmt .
23 | #cd gtkgl && go fmt .
24 | #cd gtkspell && go fmt .
25 |
26 | .PHONY: clean
27 | clean: clean-example
28 | @true
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # go-gtk
2 |
3 | [](https://travis-ci.org/mattn/go-gtk)
4 | [](https://codecov.io/gh/mattn/go-gtk)
5 |
6 | ## WHATS
7 |
8 | Go bindings for GTK
9 |
10 | ## SCREENSHOT
11 |
12 | 
13 |
14 | ## INSTALL
15 |
16 | You can experiment with go-gtk
17 | by running the various example programs:
18 |
19 | git clone https://github.com/mattn/go-gtk
20 | cd go-gtk
21 | go get ...
22 | make example
23 | ./example/demo/demo
24 |
25 | Or
26 |
27 | go get github.com/mattn/go-gtk/gtk
28 |
29 | Don't forget, that you need the GTK-Development-Packages.
30 |
31 | If you use linux, you should install `libgtk+-2.0` and packages that depend on gtk.
32 |
33 | On Debian and Debian derived distributions you can run (as root):
34 |
35 | apt-get install libgtk2.0-dev libglib2.0-dev libgtksourceview2.0-dev
36 |
37 | If you use windows, find gtk binary packages from here:
38 |
39 | * [https://www.gtk.org/docs/installations/windows](https://www.gtk.org/docs/installations/windows)
40 |
41 | ## EMBEDDING
42 |
43 | It is possible to embed a pixbuf image with:
44 | ```sh
45 | $ go run tools/make_inline_pixbuf/make_inline_pixbuf.go logoPNG data/go-gtk-logo.png > logo.gen.go
46 | ```
47 |
48 | And then load it with:
49 | ```go
50 | pb := gdkpixbuf.NewPixbufFromData(logoPNG)
51 | ```
52 |
53 | ## LICENSE
54 |
55 | The library is available under the same terms and conditions as the Go, the BSD style license, and the LGPL (GNU Lesser General Public License). The idea is that if you can use Go (and Gtk) in a project, you should also be able to use go-gtk.
56 |
57 | ## AUTHOR
58 |
59 | * Yasuhiro Matsumoto
60 |
61 | ## CONTRIBUTE AUTHORS
62 |
63 | * David Roundy
64 | * Mark Andrew Gerads
65 | * Tobias Kortkamp
66 | * Mikhail Trushnikov
67 | * Federico Sogaro
68 | * Crazy2be
69 | * Daniël de Kok
70 | * Erik Lissel
71 | * Jeffrey Bolle
72 | * Leonhard Küper
73 | * Matt Joiner
74 | * SQP
75 | * Steven T
76 | * Taru Karttunen
77 | * Utkan Güngördü
78 | * matiaslina
79 | * Dag Robøle
80 | * Denis Dyakov
81 | * Giuseppe Mazzotta
82 |
83 | ## GOAL
84 |
85 | Hopefully support following widgets and methods enough to run general application.
86 |
87 | (output of tools/gogtkinfo)
88 |
89 | Main Loop and Events : 30% ( 8/ 26)
90 | GtkAccelGroup : 15% ( 3/ 19)
91 | GtkAccelMap : 0% ( 0/ 14)
92 | GtkClipboard : 29% ( 9/ 31)
93 | Drag and Drop : 11% ( 4/ 35)
94 | GtkIconTheme : 9% ( 3/ 33)
95 | GtkStockItem : 66% ( 4/ 6)
96 | Themeable Stock Images : 2% ( 1/ 42)
97 | Resource Files : 14% ( 4/ 28)
98 | GtkSettings : 40% ( 6/ 15)
99 | GtkBinding : 0% ( 0/ 14)
100 | Graphics Contexts : 0% ( 0/ 2)
101 | GtkStyle : 9% ( 6/ 64)
102 | Selections : 8% ( 4/ 47)
103 | Version Information : 0% ( 0/ 6)
104 | Testing : 0% ( 0/ 16)
105 | Filesystem Utilities : 0% ( 0/ 7)
106 | GtkDialog : 63% ( 12/ 19)
107 | GtkMessageDialog : 62% ( 5/ 8)
108 | GtkWindow : 53% ( 55/102)
109 | GtkWindowGroup : 0% ( 0/ 5)
110 | GtkAboutDialog : 90% ( 29/ 32)
111 | GtkAssistant : 91% ( 21/ 23)
112 | GtkOffscreenWindow : 0% ( 0/ 3)
113 | GtkAccelLabel : 83% ( 5/ 6)
114 | GtkImage : 32% ( 10/ 31)
115 | GtkLabel : 86% ( 39/ 45)
116 | GtkProgressBar : 100% ( 12/ 12)
117 | GtkStatusbar : 77% ( 7/ 9)
118 | GtkInfoBar : 100% ( 12/ 12)
119 | GtkStatusIcon : 68% ( 26/ 38)
120 | GtkSpinner : 100% ( 3/ 3)
121 | GtkButton : 100% ( 28/ 28)
122 | GtkCheckButton : 100% ( 3/ 3)
123 | GtkRadioButton : 100% ( 8/ 8)
124 | GtkToggleButton : 100% ( 9/ 9)
125 | GtkLinkButton : 75% ( 6/ 8)
126 | GtkScaleButton : 100% ( 9/ 9)
127 | GtkVolumeButton : 100% ( 1/ 1)
128 | GtkEntry : 44% ( 28/ 63)
129 | GtkEntryBuffer : 72% ( 8/ 11)
130 | GtkEntryCompletion : 96% ( 25/ 26)
131 | GtkHScale : 100% ( 2/ 2)
132 | GtkVScale : 100% ( 2/ 2)
133 | GtkSpinButton : 100% ( 30/ 30)
134 | GtkEditable : 100% ( 13/ 13)
135 | GtkTextIter : 25% ( 23/ 91)
136 | GtkTextMark : 0% ( 0/ 7)
137 | GtkTextBuffer : 67% ( 52/ 77)
138 | GtkTextTag : 83% ( 5/ 6)
139 | GtkTextAttributes : 100% ( 5/ 5)
140 | GtkTextTagTable : 83% ( 5/ 6)
141 | GtkTextView : 29% ( 19/ 64)
142 | GtkTreePath : 90% ( 18/ 20)
143 | GtkTreeRowReference : 60% ( 6/ 10)
144 | GtkTreeIter : 100% ( 2/ 2)
145 | GtkTreeModel : 57% ( 15/ 26)
146 | GtkTreeSelection : 78% ( 18/ 23)
147 | GtkTreeViewColumn : 61% ( 34/ 55)
148 | GtkTreeView : 19% ( 19/ 98)
149 | GtkTreeView drag-and-drop : 0% ( 0/ 7)
150 | GtkCellView : 0% ( 0/ 11)
151 | GtkIconView : 17% ( 11/ 62)
152 | GtkTreeSortable : 87% ( 7/ 8)
153 | GtkTreeModelSort : 0% ( 0/ 9)
154 | GtkTreeModelFilter : 0% ( 0/ 11)
155 | GtkCellLayout : 0% ( 0/ 9)
156 | GtkCellRenderer : 100% ( 2/ 2)
157 | GtkCellEditable : 0% ( 0/ 3)
158 | GtkCellRendererAccel : 100% ( 1/ 1)
159 | GtkCellRendererCombo : 100% ( 1/ 1)
160 | GtkCellRendererPixbuf : 100% ( 1/ 1)
161 | GtkCellRendererProgress : 100% ( 1/ 1)
162 | GtkCellRendererSpin : 100% ( 1/ 1)
163 | GtkCellRendererText : 100% ( 2/ 2)
164 | GtkCellRendererToggle : 100% ( 7/ 7)
165 | GtkCellRendererSpinner : 100% ( 1/ 1)
166 | GtkListStore : 84% ( 16/ 19)
167 | GtkTreeStore : 80% ( 17/ 21)
168 | GtkComboBox : 78% ( 30/ 38)
169 | GtkComboBoxText : 100% ( 7/ 7)
170 | GtkComboBoxEntry : 80% ( 4/ 5)
171 | GtkMenu : 48% ( 13/ 27)
172 | GtkMenuBar : 100% ( 5/ 5)
173 | GtkMenuItem : 90% ( 18/ 20)
174 | GtkImageMenuItem : 54% ( 6/ 11)
175 | GtkRadioMenuItem : 44% ( 4/ 9)
176 | GtkCheckMenuItem : 100% ( 10/ 10)
177 | GtkSeparatorMenuItem : 100% ( 1/ 1)
178 | GtkTearoffMenuItem : 100% ( 1/ 1)
179 | GtkToolShell : 0% ( 0/ 9)
180 | GtkToolbar : 63% ( 24/ 38)
181 | GtkToolItem : 76% ( 19/ 25)
182 | GtkToolPalette : 59% ( 13/ 22)
183 | GtkToolItemGroup : 47% ( 8/ 17)
184 | GtkSeparatorToolItem : 100% ( 3/ 3)
185 | GtkToolButton : 100% ( 15/ 15)
186 | GtkMenuToolButton : 85% ( 6/ 7)
187 | GtkToggleToolButton : 100% ( 5/ 5)
188 | GtkRadioToolButton : 33% ( 2/ 6)
189 | GtkUIManager : 29% ( 5/ 17)
190 | GtkActionGroup : 55% ( 11/ 20)
191 | GtkAction : 93% ( 44/ 47)
192 | GtkToggleAction : 100% ( 6/ 6)
193 | GtkRadioAction : 100% ( 5/ 5)
194 | GtkRecentAction : 75% ( 3/ 4)
195 | GtkActivatable : 66% ( 4/ 6)
196 | GtkColorButton : 100% ( 10/ 10)
197 | GtkColorSelectionDialog : 0% ( 0/ 2)
198 | GtkColorSelection : 0% ( 0/ 21)
199 | GtkHSV : 0% ( 0/ 8)
200 | GtkFileChooser : 27% ( 16/ 58)
201 | GtkFileChooserButton : 18% ( 2/ 11)
202 | GtkFileChooserDialog : 100% ( 1/ 1)
203 | GtkFileChooserWidget : 50% ( 1/ 2)
204 | GtkFileFilter : 55% ( 5/ 9)
205 | GtkFontButton : 100% ( 14/ 14)
206 | GtkFontSelection : 28% ( 4/ 14)
207 | GtkFontSelectionDialog : 100% ( 8/ 8)
208 | GtkInputDialog : 0% ( 0/ 1)
209 | GtkAlignment : 100% ( 4/ 4)
210 | GtkAspectFrame : 0% ( 0/ 2)
211 | GtkHBox : 100% ( 1/ 1)
212 | GtkVBox : 100% ( 1/ 1)
213 | GtkHButtonBox : 0% ( 0/ 5)
214 | GtkVButtonBox : 0% ( 0/ 5)
215 | GtkFixed : 100% ( 5/ 5)
216 | GtkHPaned : 100% ( 1/ 1)
217 | GtkVPaned : 100% ( 1/ 1)
218 | GtkLayout : 100% ( 12/ 12)
219 | GtkNotebook : 90% ( 50/ 55)
220 | GtkTable : 93% ( 14/ 15)
221 | GtkExpander : 87% ( 14/ 16)
222 | GtkOrientable : 0% ( 0/ 2)
223 | GtkFrame : 100% ( 9/ 9)
224 | GtkHSeparator : 100% ( 1/ 1)
225 | GtkVSeparator : 100% ( 1/ 1)
226 | GtkScrollbar : 100% ( 0/ 0)
227 | GtkHScrollbar : 100% ( 1/ 1)
228 | GtkVScrollbar : 100% ( 1/ 1)
229 | GtkScrolledWindow : 86% ( 13/ 15)
230 | GtkPrintOperation : 13% ( 5/ 36)
231 | GtkPrintContext : 18% ( 2/ 11)
232 | GtkPrintSettings : 0% ( 0/ 74)
233 | GtkPageSetup : 0% ( 0/ 25)
234 | GtkPaperSize : 0% ( 0/ 21)
235 | GtkPrinter : 0% ( 0/ 23)
236 | GtkPrintJob : 0% ( 0/ 10)
237 | GtkPrintUnixDialog : 0% ( 0/ 18)
238 | GtkPageSetupUnixDialog : 0% ( 0/ 5)
239 | GtkAdjustment : 83% ( 15/ 18)
240 | GtkArrow : 100% ( 2/ 2)
241 | GtkCalendar : 0% ( 0/ 17)
242 | GtkDrawingArea : 100% ( 2/ 2)
243 | GtkEventBox : 20% ( 1/ 5)
244 | GtkHandleBox : 0% ( 0/ 8)
245 | GtkIMContextSimple : 0% ( 0/ 2)
246 | GtkIMMulticontext : 0% ( 0/ 4)
247 | GtkSizeGroup : 100% ( 8/ 8)
248 | GtkTooltip : 60% ( 6/ 10)
249 | GtkViewport : 100% ( 9/ 9)
250 | GtkAccessible : 100% ( 3/ 3)
251 | GtkBin : 100% ( 1/ 1)
252 | GtkBox : 100% ( 11/ 11)
253 | GtkButtonBox : 0% ( 0/ 10)
254 | GtkContainer : 48% ( 16/ 33)
255 | GtkItem : 100% ( 3/ 3)
256 | GtkMenuShell : 27% ( 3/ 11)
257 | GtkMisc : 100% ( 4/ 4)
258 | GtkObject : 100% ( 2/ 2)
259 | GtkPaned : 88% ( 8/ 9)
260 | GtkRange : 53% ( 16/ 30)
261 | GtkScale : 90% ( 9/ 10)
262 | GtkSeparator : 100% ( 0/ 0)
263 | GtkWidget : 54% (101/187)
264 | GtkIMContext : 0% ( 0/ 11)
265 | GtkPlug : 0% ( 0/ 7)
266 | GtkSocket : 0% ( 0/ 5)
267 | GtkRecentManager : 0% ( 0/ 37)
268 | GtkRecentChooser : 0% ( 0/ 33)
269 | GtkRecentChooserDialog : 0% ( 0/ 2)
270 | GtkRecentChooserMenu : 0% ( 0/ 4)
271 | GtkRecentChooserWidget : 0% ( 0/ 2)
272 | GtkRecentFilter : 0% ( 0/ 12)
273 | GtkBuildable : 0% ( 0/ 10)
274 |
275 | Total progress : 48% (1539/3177)
276 |
277 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | * more widgets.
2 | * main loop handling (using goroutine) (done)
3 | * split gtksourceview from gtk package (done)
4 | * copyright header in sources
5 |
--------------------------------------------------------------------------------
/_example/action/action.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 | "unsafe"
7 |
8 | "github.com/mattn/go-gtk/glib"
9 | "github.com/mattn/go-gtk/gtk"
10 | )
11 |
12 | func CreateWindow() *gtk.Window {
13 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
14 | window.SetDefaultSize(700, 300)
15 | vbox := gtk.NewVBox(false, 1)
16 | CreateMenuAndToolbar(window, vbox)
17 | CreateActivatableDemo(vbox)
18 | window.Add(vbox)
19 | return window
20 | }
21 |
22 | func CreateMenuAndToolbar(w *gtk.Window, vbox *gtk.VBox) {
23 | action_group := gtk.NewActionGroup("my_group")
24 | ui_manager := CreateUIManager()
25 | accel_group := ui_manager.GetAccelGroup()
26 | w.AddAccelGroup(accel_group)
27 | AddFileMenuActions(action_group)
28 | AddEditMenuActions(action_group)
29 | AddChoicesMenuActions(action_group)
30 | ui_manager.InsertActionGroup(action_group, 0)
31 | menubar := ui_manager.GetWidget("/MenuBar")
32 | vbox.PackStart(menubar, false, false, 0)
33 | toolbar := ui_manager.GetWidget("/ToolBar")
34 | vbox.PackStart(toolbar, false, false, 0)
35 | eventbox := gtk.NewEventBox()
36 | vbox.PackStart(eventbox, false, false, 0)
37 | // label := gtk.NewLabel("Right-click to see the popup menu.")
38 | // vbox.PackStart(label, false, false, 0)
39 | }
40 |
41 | func CreateActivatableDemo(vbox *gtk.VBox) {
42 | action_entry := gtk.NewAction("ActionEntry",
43 | "Button attached to Action", "", gtk.STOCK_INFO)
44 | action_entry.Connect("activate", func() {
45 | fmt.Println("Action clicked")
46 | })
47 | frame1 := gtk.NewFrame("GtkActivatable interface demonstration")
48 | frame1.SetBorderWidth(5)
49 | hbox2 := gtk.NewHBox(false, 5)
50 | hbox2.SetSizeRequest(400, 50)
51 | hbox2.SetBorderWidth(5)
52 | button1 := gtk.NewButton()
53 | button1.SetSizeRequest(250, 0)
54 | button1.SetRelatedAction(action_entry)
55 | hbox2.PackStart(button1, false, false, 0)
56 | hbox2.PackStart(gtk.NewVSeparator(), false, false, 0)
57 | button2 := gtk.NewButtonWithLabel("Hide Action")
58 | button2.SetSizeRequest(150, 0)
59 | button2.Connect("clicked", func() {
60 | action_entry.SetVisible(false)
61 | fmt.Println("Hide Action")
62 | })
63 | hbox2.PackStart(button2, false, false, 0)
64 | button3 := gtk.NewButtonWithLabel("Unhide Action")
65 | button3.SetSizeRequest(150, 0)
66 | button3.Connect("clicked", func() {
67 | action_entry.SetVisible(true)
68 | fmt.Println("Show Action")
69 | })
70 | hbox2.PackStart(button3, false, false, 0)
71 | frame1.Add(hbox2)
72 | vbox.PackStart(frame1, false, true, 0)
73 | }
74 |
75 | func CreateUIManager() *gtk.UIManager {
76 | UI_INFO := `
77 |
78 |
79 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | `
112 | ui_manager := gtk.NewUIManager()
113 | ui_manager.AddUIFromString(UI_INFO)
114 | return ui_manager
115 | }
116 |
117 | func OnMenuFileNewGeneric() {
118 | fmt.Println("A File|New menu item was selected.")
119 | }
120 |
121 | func OnMenuFileQuit() {
122 | fmt.Println("quit app...")
123 | gtk.MainQuit()
124 | }
125 |
126 | func OnMenuOther(ctx *glib.CallbackContext) {
127 | v := reflect.ValueOf(ctx.Target())
128 | if v.Kind() == reflect.Ptr {
129 | fmt.Printf("Item %s(%p) was selected", v.Elem(), v.Interface())
130 | fmt.Println()
131 | if w, ok := v.Elem().Interface().(gtk.IWidget); ok {
132 | v := reflect.ValueOf(ctx.Target())
133 | v2 := v.Elem()
134 | fmt.Println(v.Kind(), v2.Kind())
135 | fmt.Println("Menu item ", w.GetName(), " was selected")
136 | }
137 | }
138 | }
139 |
140 | func OnMenuOther2(widget unsafe.Pointer, event unsafe.Pointer,
141 | data unsafe.Pointer) {
142 | fmt.Println("Menu item ", "", " was selected")
143 | }
144 |
145 | func AddFileMenuActions(action_group *gtk.ActionGroup) {
146 | action_group.AddAction(gtk.NewAction("FileMenu", "File", "", ""))
147 |
148 | action_filenewmenu := gtk.NewAction("FileNew", "", "", gtk.STOCK_NEW)
149 | action_group.AddAction(action_filenewmenu)
150 |
151 | action_new := gtk.NewAction("FileNewStandard", "_New",
152 | "Create a new file", gtk.STOCK_NEW)
153 | action_new.Connect("activate", OnMenuFileNewGeneric)
154 | action_group.AddActionWithAccel(action_new, "")
155 |
156 | action_new_foo := gtk.NewAction("FileNewFoo", "New Foo",
157 | "Create new foo", gtk.STOCK_NEW)
158 | action_new_foo.Connect("activate", OnMenuFileNewGeneric)
159 | action_group.AddAction(action_new_foo)
160 |
161 | action_new_goo := gtk.NewAction("FileNewGoo", "_New Goo",
162 | "Create new goo", gtk.STOCK_NEW)
163 | action_new_goo.Connect("activate", OnMenuFileNewGeneric)
164 | action_group.AddAction(action_new_goo)
165 |
166 | action_filequit := gtk.NewAction("FileQuit", "", "", gtk.STOCK_QUIT)
167 | action_filequit.Connect("activate", OnMenuFileQuit)
168 | action_group.AddActionWithAccel(action_filequit, "")
169 | }
170 |
171 | func AddEditMenuActions(action_group *gtk.ActionGroup) {
172 | action_group.AddAction(gtk.NewAction("EditMenu", "Edit", "", ""))
173 |
174 | action_editcopy := gtk.NewAction("EditCopy", "", "", gtk.STOCK_COPY)
175 | action_editcopy.Connect("activate", OnMenuOther)
176 | action_group.AddActionWithAccel(action_editcopy, "")
177 |
178 | action_editpaste := gtk.NewAction("EditPaste", "", "", gtk.STOCK_PASTE)
179 | action_editpaste.Connect("activate", OnMenuOther)
180 | action_group.AddActionWithAccel(action_editpaste, "")
181 |
182 | action_editsomething := gtk.NewAction("EditSomething", "Something", "", "")
183 | action_editsomething.Connect("activate", OnMenuOther)
184 | action_group.AddActionWithAccel(action_editsomething, "S")
185 | }
186 |
187 | func AddChoicesMenuActions(action_group *gtk.ActionGroup) {
188 | action_group.AddAction(gtk.NewAction("ChoicesMenu", "Choices", "", ""))
189 |
190 | var ra_list []*gtk.RadioAction
191 | ra_one := gtk.NewRadioAction("ChoiceOne", "One", "", "", 1)
192 | ra_list = append(ra_list, ra_one)
193 |
194 | ra_two := gtk.NewRadioAction("ChoiceTwo", "Two", "", "", 2)
195 | ra_list = append(ra_list, ra_two)
196 |
197 | ra_three := gtk.NewRadioAction("ChoiceThree", "Three", "", "", 2)
198 | ra_list = append(ra_list, ra_three)
199 |
200 | var sl *glib.SList
201 | for _, ra := range ra_list {
202 | ra.SetGroup(sl)
203 | sl = ra.GetGroup()
204 | action_group.AddAction(ra)
205 | }
206 |
207 | ra_last := gtk.NewToggleAction("ChoiceToggle", "Toggle", "", "")
208 | ra_last.SetActive(true)
209 | action_group.AddAction(ra_last)
210 | }
211 |
212 | func main() {
213 | gtk.Init(nil)
214 | window := CreateWindow()
215 | window.SetPosition(gtk.WIN_POS_CENTER)
216 | window.Connect("destroy", func(ctx *glib.CallbackContext) {
217 | fmt.Println("destroy pending...")
218 | gtk.MainQuit()
219 | }, "foo")
220 | window.ShowAll()
221 | gtk.Main()
222 | }
223 |
--------------------------------------------------------------------------------
/_example/alignment/alignment.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/mattn/go-gtk/gtk"
5 | "os"
6 | )
7 |
8 | func main() {
9 | gtk.Init(&os.Args)
10 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
11 | window.SetTitle("Alignment")
12 | window.Connect("destroy", gtk.MainQuit)
13 |
14 | notebook := gtk.NewNotebook()
15 | window.Add(notebook)
16 |
17 | align := gtk.NewAlignment(0.5, 0.5, 0.5, 0.5)
18 | notebook.AppendPage(align, gtk.NewLabel("Alignment"))
19 |
20 | button := gtk.NewButtonWithLabel("Hello World!")
21 | align.Add(button)
22 |
23 | fixed := gtk.NewFixed()
24 | notebook.AppendPage(fixed, gtk.NewLabel("Fixed"))
25 |
26 | button2 := gtk.NewButtonWithLabel("Pulse")
27 | fixed.Put(button2, 30, 30)
28 |
29 | progress := gtk.NewProgressBar()
30 | fixed.Put(progress, 30, 70)
31 |
32 | button.Connect("clicked", func() {
33 | progress.SetFraction(0.1 + 0.9*progress.GetFraction()) //easter egg
34 | })
35 | button2.Connect("clicked", func() {
36 | progress.Pulse()
37 | })
38 |
39 | window.ShowAll()
40 | window.SetSizeRequest(200, 200)
41 |
42 | gtk.Main()
43 | }
44 |
--------------------------------------------------------------------------------
/_example/arrow/arrow.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/mattn/go-gtk/gtk"
5 | "os"
6 | )
7 |
8 | func createArrowButton(at gtk.ArrowType, st gtk.ShadowType) *gtk.Button {
9 | b := gtk.NewButton()
10 | a := gtk.NewArrow(at, st)
11 |
12 | b.Add(a)
13 |
14 | b.Show()
15 | a.Show()
16 |
17 | return b
18 | }
19 |
20 | func main() {
21 | gtk.Init(&os.Args)
22 |
23 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
24 | window.SetTitle("Arrow Buttons")
25 | window.Connect("destroy", gtk.MainQuit)
26 |
27 | box := gtk.NewHBox(false, 0)
28 | box.Show()
29 | window.Add(box)
30 |
31 | up := createArrowButton(gtk.ARROW_UP, gtk.SHADOW_IN)
32 | down := createArrowButton(gtk.ARROW_DOWN, gtk.SHADOW_OUT)
33 | left := createArrowButton(gtk.ARROW_LEFT, gtk.SHADOW_ETCHED_IN)
34 | right := createArrowButton(gtk.ARROW_RIGHT, gtk.SHADOW_ETCHED_OUT)
35 |
36 | box.PackStart(up, false, false, 3)
37 | box.PackStart(down, false, false, 3)
38 | box.PackStart(left, false, false, 3)
39 | box.PackStart(right, false, false, 3)
40 |
41 | up.Clicked(func() { println("↑") })
42 | down.Clicked(func() { println("↓") })
43 | left.Clicked(func() { println("←") })
44 | right.Clicked(func() { println("→") })
45 |
46 | window.Show()
47 | gtk.Main()
48 | }
49 |
--------------------------------------------------------------------------------
/_example/builder/builder.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 |
6 | "github.com/mattn/go-gtk/_example/builder/callback"
7 | "github.com/mattn/go-gtk/gtk"
8 | )
9 |
10 | //"github.com/mattn/go-gtk/example/builder/callback"
11 | func main() {
12 | gtk.Init(&os.Args)
13 |
14 | builder := gtk.NewBuilder()
15 |
16 | builder.AddFromFile("hello.ui")
17 | obj := builder.GetObject("window1")
18 |
19 | window := gtk.WidgetFromObject(obj)
20 | window.Show()
21 | window.Connect("destroy", gtk.MainQuit)
22 |
23 | callback.Init(builder)
24 |
25 | gtk.Main()
26 | }
27 |
--------------------------------------------------------------------------------
/_example/builder/callback/callback.go:
--------------------------------------------------------------------------------
1 | package callback
2 |
3 | import (
4 | "unsafe"
5 |
6 | "github.com/mattn/go-gtk/glib"
7 | "github.com/mattn/go-gtk/gtk"
8 | )
9 |
10 | var aboutdialog *gtk.AboutDialog
11 |
12 | func Init(builder *gtk.Builder) {
13 | aboutdialog = >k.AboutDialog{
14 | *(*gtk.Dialog)(unsafe.Pointer(&builder.GetObject("aboutdialog1").Object))}
15 | builder.ConnectSignalsFull(func(builder *gtk.Builder, obj *glib.GObject, sig, handler string, conn *glib.GObject, flags glib.ConnectFlags, user_data interface{}) {
16 | switch handler {
17 | case "on_imagemenuitem1_activate":
18 | obj.SignalConnect(sig, on_imagemenuitem1_activate, user_data, flags)
19 | case "on_show_aboutdialog_activate":
20 | obj.SignalConnect(sig, on_show_aboutdialog_activate, user_data, flags)
21 | case "gtk_widget_hide":
22 | obj.SignalConnect(sig, func(c *glib.CallbackContext) {
23 | gtk.WidgetFromObject(c.Target().(*glib.GObject)).Hide()
24 | }, nil, flags)
25 | }
26 | }, nil)
27 | }
28 |
29 | //export on_imagemenuitem1_activate
30 | func on_imagemenuitem1_activate() {
31 | gtk.MainQuit()
32 | }
33 |
34 | //export on_show_aboutdialog_activate
35 | func on_show_aboutdialog_activate() {
36 | aboutdialog.Run()
37 | }
38 |
--------------------------------------------------------------------------------
/_example/builder/hello.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
42 |
43 | True
44 | False
45 | ../../data/mattn-logo.png
46 |
47 |
48 | False
49 | builder
50 |
51 |
52 | True
53 | False
54 |
55 |
112 |
113 | False
114 | True
115 | 0
116 |
117 |
118 |
119 |
120 | False
121 | True
122 | True
123 | True
124 | True
125 | <b>http://mattn.kaoriya.net/</b>
126 | image1
127 | none
128 | http://mattn.kaoriya.net/
129 |
130 |
131 | True
132 | True
133 | 1
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/_example/clipboard/clipboard.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/gdk"
6 | "github.com/mattn/go-gtk/gtk"
7 | )
8 |
9 | func main() {
10 | gtk.Init(nil)
11 | clipboard := gtk.NewClipboardGetForDisplay(
12 | gdk.DisplayGetDefault(),
13 | gdk.SELECTION_CLIPBOARD)
14 | fmt.Println(clipboard.WaitForText())
15 | clipboard.SetText("helloworld")
16 | gtk.MainIterationDo(true)
17 | clipboard.Store()
18 | gtk.MainIterationDo(true)
19 | }
20 |
--------------------------------------------------------------------------------
/_example/demo/demo.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "os/exec"
7 | "path/filepath"
8 | "regexp"
9 | "sort"
10 | "strings"
11 |
12 | "github.com/mattn/go-gtk/gdkpixbuf"
13 | "github.com/mattn/go-gtk/glib"
14 | "github.com/mattn/go-gtk/gtk"
15 | )
16 |
17 | func uniq(strings []string) (ret []string) {
18 | return
19 | }
20 |
21 | func authors() []string {
22 | if b, err := exec.Command("git", "log").Output(); err == nil {
23 | lines := strings.Split(string(b), "\n")
24 |
25 | var a []string
26 | r := regexp.MustCompile(`^Author:\s*([^ <]+).*$`)
27 | for _, e := range lines {
28 | ms := r.FindStringSubmatch(e)
29 | if ms == nil {
30 | continue
31 | }
32 | a = append(a, ms[1])
33 | }
34 | sort.Strings(a)
35 | var p string
36 | lines = []string{}
37 | for _, e := range a {
38 | if p == e {
39 | continue
40 | }
41 | lines = append(lines, e)
42 | p = e
43 | }
44 | return lines
45 | }
46 | return []string{"Yasuhiro Matsumoto "}
47 | }
48 |
49 | func main() {
50 | gtk.Init(&os.Args)
51 |
52 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
53 | window.SetPosition(gtk.WIN_POS_CENTER)
54 | window.SetTitle("GTK Go!")
55 | window.SetIconName("gtk-dialog-info")
56 | window.Connect("destroy", func(ctx *glib.CallbackContext) {
57 | fmt.Println("got destroy!", ctx.Data().(string))
58 | gtk.MainQuit()
59 | }, "foo")
60 |
61 | //--------------------------------------------------------
62 | // GtkVBox
63 | //--------------------------------------------------------
64 | vbox := gtk.NewVBox(false, 1)
65 |
66 | //--------------------------------------------------------
67 | // GtkMenuBar
68 | //--------------------------------------------------------
69 | menubar := gtk.NewMenuBar()
70 | vbox.PackStart(menubar, false, false, 0)
71 |
72 | //--------------------------------------------------------
73 | // GtkVPaned
74 | //--------------------------------------------------------
75 | vpaned := gtk.NewVPaned()
76 | vbox.Add(vpaned)
77 |
78 | //--------------------------------------------------------
79 | // GtkFrame
80 | //--------------------------------------------------------
81 | frame1 := gtk.NewFrame("Demo")
82 | framebox1 := gtk.NewVBox(false, 1)
83 | frame1.Add(framebox1)
84 |
85 | frame2 := gtk.NewFrame("Demo")
86 | framebox2 := gtk.NewVBox(false, 1)
87 | frame2.Add(framebox2)
88 |
89 | vpaned.Pack1(frame1, false, false)
90 | vpaned.Pack2(frame2, false, false)
91 |
92 | //--------------------------------------------------------
93 | // GtkImage
94 | //--------------------------------------------------------
95 | dir, _ := filepath.Split(os.Args[0])
96 | imagefile := filepath.Join(dir, "../../data/go-gtk-logo.png")
97 |
98 | label := gtk.NewLabel("Go Binding for GTK")
99 | label.ModifyFontEasy("DejaVu Serif 15")
100 | framebox1.PackStart(label, false, true, 0)
101 |
102 | //--------------------------------------------------------
103 | // GtkEntry
104 | //--------------------------------------------------------
105 | entry := gtk.NewEntry()
106 | entry.SetText("Hello world")
107 | framebox1.Add(entry)
108 |
109 | image := gtk.NewImageFromFile(imagefile)
110 | framebox1.Add(image)
111 |
112 | //--------------------------------------------------------
113 | // GtkScale
114 | //--------------------------------------------------------
115 | scale := gtk.NewHScaleWithRange(0, 100, 1)
116 | scale.Connect("value-changed", func() {
117 | fmt.Println("scale:", int(scale.GetValue()))
118 | })
119 | framebox2.Add(scale)
120 |
121 | //--------------------------------------------------------
122 | // GtkHBox
123 | //--------------------------------------------------------
124 | buttons := gtk.NewHBox(false, 1)
125 |
126 | //--------------------------------------------------------
127 | // GtkButton
128 | //--------------------------------------------------------
129 | button := gtk.NewButtonWithLabel("Button with label")
130 | button.Clicked(func() {
131 | fmt.Println("button clicked:", button.GetLabel())
132 | messagedialog := gtk.NewMessageDialog(
133 | button.GetTopLevelAsWindow(),
134 | gtk.DIALOG_MODAL,
135 | gtk.MESSAGE_INFO,
136 | gtk.BUTTONS_OK,
137 | entry.GetText())
138 | messagedialog.Response(func() {
139 | fmt.Println("Dialog OK!")
140 |
141 | //--------------------------------------------------------
142 | // GtkFileChooserDialog
143 | //--------------------------------------------------------
144 | filechooserdialog := gtk.NewFileChooserDialog(
145 | "Choose File...",
146 | button.GetTopLevelAsWindow(),
147 | gtk.FILE_CHOOSER_ACTION_OPEN,
148 | gtk.STOCK_OK,
149 | gtk.RESPONSE_ACCEPT)
150 | filter := gtk.NewFileFilter()
151 | filter.AddPattern("*.go")
152 | filechooserdialog.AddFilter(filter)
153 | filechooserdialog.Response(func() {
154 | fmt.Println(filechooserdialog.GetFilename())
155 | filechooserdialog.Destroy()
156 | })
157 | filechooserdialog.Run()
158 | messagedialog.Destroy()
159 | })
160 | messagedialog.Run()
161 | })
162 | buttons.Add(button)
163 |
164 | //--------------------------------------------------------
165 | // GtkFontButton
166 | //--------------------------------------------------------
167 | fontbutton := gtk.NewFontButton()
168 | fontbutton.Connect("font-set", func() {
169 | fmt.Println("title:", fontbutton.GetTitle())
170 | fmt.Println("fontname:", fontbutton.GetFontName())
171 | fmt.Println("use_size:", fontbutton.GetUseSize())
172 | fmt.Println("show_size:", fontbutton.GetShowSize())
173 | })
174 | buttons.Add(fontbutton)
175 | framebox2.PackStart(buttons, false, false, 0)
176 |
177 | buttons = gtk.NewHBox(false, 1)
178 |
179 | //--------------------------------------------------------
180 | // GtkToggleButton
181 | //--------------------------------------------------------
182 | togglebutton := gtk.NewToggleButtonWithLabel("ToggleButton with label")
183 | togglebutton.Connect("toggled", func() {
184 | if togglebutton.GetActive() {
185 | togglebutton.SetLabel("ToggleButton ON!")
186 | } else {
187 | togglebutton.SetLabel("ToggleButton OFF!")
188 | }
189 | })
190 | buttons.Add(togglebutton)
191 |
192 | //--------------------------------------------------------
193 | // GtkCheckButton
194 | //--------------------------------------------------------
195 | checkbutton := gtk.NewCheckButtonWithLabel("CheckButton with label")
196 | checkbutton.Connect("toggled", func() {
197 | if checkbutton.GetActive() {
198 | checkbutton.SetLabel("CheckButton CHECKED!")
199 | } else {
200 | checkbutton.SetLabel("CheckButton UNCHECKED!")
201 | }
202 | })
203 | buttons.Add(checkbutton)
204 |
205 | //--------------------------------------------------------
206 | // GtkRadioButton
207 | //--------------------------------------------------------
208 | buttonbox := gtk.NewVBox(false, 1)
209 | radiofirst := gtk.NewRadioButtonWithLabel(nil, "Radio1")
210 | buttonbox.Add(radiofirst)
211 | buttonbox.Add(gtk.NewRadioButtonWithLabel(radiofirst.GetGroup(), "Radio2"))
212 | buttonbox.Add(gtk.NewRadioButtonWithLabel(radiofirst.GetGroup(), "Radio3"))
213 | buttons.Add(buttonbox)
214 | //radiobutton.SetMode(false);
215 | radiofirst.SetActive(true)
216 |
217 | framebox2.PackStart(buttons, false, false, 0)
218 |
219 | //--------------------------------------------------------
220 | // GtkVSeparator
221 | //--------------------------------------------------------
222 | vsep := gtk.NewVSeparator()
223 | framebox2.PackStart(vsep, false, false, 0)
224 |
225 | //--------------------------------------------------------
226 | // GtkComboBoxEntry
227 | //--------------------------------------------------------
228 | combos := gtk.NewHBox(false, 1)
229 | comboboxentry := gtk.NewComboBoxText()
230 | comboboxentry.AppendText("Monkey")
231 | comboboxentry.AppendText("Tiger")
232 | comboboxentry.AppendText("Elephant")
233 | comboboxentry.Connect("changed", func() {
234 | fmt.Println("value:", comboboxentry.GetActiveText())
235 | })
236 | combos.Add(comboboxentry)
237 |
238 | //--------------------------------------------------------
239 | // GtkComboBox
240 | //--------------------------------------------------------
241 | combobox := gtk.NewComboBoxText()
242 | combobox.AppendText("Peach")
243 | combobox.AppendText("Banana")
244 | combobox.AppendText("Apple")
245 | combobox.SetActive(1)
246 | combobox.Connect("changed", func() {
247 | fmt.Println("value:", combobox.GetActiveText())
248 | })
249 | combos.Add(combobox)
250 |
251 | framebox2.PackStart(combos, false, false, 0)
252 |
253 | //--------------------------------------------------------
254 | // GtkTextView
255 | //--------------------------------------------------------
256 | swin := gtk.NewScrolledWindow(nil, nil)
257 | swin.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
258 | swin.SetShadowType(gtk.SHADOW_IN)
259 | textview := gtk.NewTextView()
260 | var start, end gtk.TextIter
261 | buffer := textview.GetBuffer()
262 | buffer.GetStartIter(&start)
263 | buffer.Insert(&start, "Hello ")
264 | buffer.GetEndIter(&end)
265 | buffer.Insert(&end, "World!")
266 | tag := buffer.CreateTag("bold", map[string]interface{}{
267 | "background": "#FF0000", "weight": "700"})
268 | buffer.GetStartIter(&start)
269 | buffer.GetEndIter(&end)
270 | buffer.ApplyTag(tag, &start, &end)
271 | swin.Add(textview)
272 | framebox2.Add(swin)
273 |
274 | buffer.Connect("changed", func() {
275 | fmt.Println("changed")
276 | })
277 |
278 | //--------------------------------------------------------
279 | // GtkMenuItem
280 | //--------------------------------------------------------
281 | cascademenu := gtk.NewMenuItemWithMnemonic("_File")
282 | menubar.Append(cascademenu)
283 | submenu := gtk.NewMenu()
284 | cascademenu.SetSubmenu(submenu)
285 |
286 | var menuitem *gtk.MenuItem
287 | menuitem = gtk.NewMenuItemWithMnemonic("E_xit")
288 | menuitem.Connect("activate", func() {
289 | gtk.MainQuit()
290 | })
291 | submenu.Append(menuitem)
292 |
293 | cascademenu = gtk.NewMenuItemWithMnemonic("_View")
294 | menubar.Append(cascademenu)
295 | submenu = gtk.NewMenu()
296 | cascademenu.SetSubmenu(submenu)
297 |
298 | checkmenuitem := gtk.NewCheckMenuItemWithMnemonic("_Disable")
299 | checkmenuitem.Connect("activate", func() {
300 | vpaned.SetSensitive(!checkmenuitem.GetActive())
301 | })
302 | submenu.Append(checkmenuitem)
303 |
304 | menuitem = gtk.NewMenuItemWithMnemonic("_Font")
305 | menuitem.Connect("activate", func() {
306 | fsd := gtk.NewFontSelectionDialog("Font")
307 | fsd.SetFontName(fontbutton.GetFontName())
308 | fsd.Response(func() {
309 | fmt.Println(fsd.GetFontName())
310 | fontbutton.SetFontName(fsd.GetFontName())
311 | fsd.Destroy()
312 | })
313 | fsd.SetTransientFor(window)
314 | fsd.Run()
315 | })
316 | submenu.Append(menuitem)
317 |
318 | cascademenu = gtk.NewMenuItemWithMnemonic("_Help")
319 | menubar.Append(cascademenu)
320 | submenu = gtk.NewMenu()
321 | cascademenu.SetSubmenu(submenu)
322 |
323 | menuitem = gtk.NewMenuItemWithMnemonic("_About")
324 | menuitem.Connect("activate", func() {
325 | dialog := gtk.NewAboutDialog()
326 | dialog.SetName("Go-Gtk Demo!")
327 | dialog.SetProgramName("demo")
328 | dialog.SetAuthors(authors())
329 | dir, _ := filepath.Split(os.Args[0])
330 | imagefile := filepath.Join(dir, "../../data/mattn-logo.png")
331 | pixbuf, _ := gdkpixbuf.NewPixbufFromFile(imagefile)
332 | dialog.SetLogo(pixbuf)
333 | dialog.SetLicense("The library is available under the same terms and conditions as the Go, the BSD style license, and the LGPL (Lesser GNU Public License). The idea is that if you can use Go (and Gtk) in a project, you should also be able to use go-gtk.")
334 | dialog.SetWrapLicense(true)
335 | dialog.Run()
336 | dialog.Destroy()
337 | })
338 | submenu.Append(menuitem)
339 |
340 | //--------------------------------------------------------
341 | // GtkStatusbar
342 | //--------------------------------------------------------
343 | statusbar := gtk.NewStatusbar()
344 | context_id := statusbar.GetContextId("go-gtk")
345 | statusbar.Push(context_id, "GTK binding for Go!")
346 |
347 | framebox2.PackStart(statusbar, false, false, 0)
348 |
349 | //--------------------------------------------------------
350 | // Event
351 | //--------------------------------------------------------
352 | window.Add(vbox)
353 | window.SetSizeRequest(600, 600)
354 | window.ShowAll()
355 | gtk.Main()
356 | }
357 |
--------------------------------------------------------------------------------
/_example/dnd/dnd.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 | "strings"
6 | "unsafe"
7 |
8 | "github.com/mattn/go-gtk/gdk"
9 | "github.com/mattn/go-gtk/glib"
10 | "github.com/mattn/go-gtk/gtk"
11 | )
12 |
13 | func main() {
14 | gtk.Init(&os.Args)
15 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
16 | window.SetTitle("GTK DND")
17 | window.Connect("destroy", gtk.MainQuit)
18 |
19 | vbox := gtk.NewVBox(true, 0)
20 | vbox.SetBorderWidth(5)
21 |
22 | targets := []gtk.TargetEntry{
23 | {"text/uri-list", 0, 0},
24 | {"STRING", 0, 1},
25 | {"text/plain", 0, 2},
26 | }
27 | dest := gtk.NewLabel("drop me file")
28 | dest.DragDestSet(
29 | gtk.DEST_DEFAULT_MOTION|
30 | gtk.DEST_DEFAULT_HIGHLIGHT|
31 | gtk.DEST_DEFAULT_DROP,
32 | targets,
33 | gdk.ACTION_COPY)
34 | dest.DragDestAddUriTargets()
35 | dest.Connect("drag-data-received", func(ctx *glib.CallbackContext) {
36 | sdata := gtk.NewSelectionDataFromNative(unsafe.Pointer(ctx.Args(3)))
37 | if sdata != nil {
38 | a := (*[2000]uint8)(sdata.GetData())
39 | files := strings.Split(string(a[0:sdata.GetLength()-1]), "\n")
40 | for i := range files {
41 | filename, _, _ := glib.FilenameFromUri(files[i])
42 | files[i] = filename
43 | }
44 | dialog := gtk.NewMessageDialog(
45 | window,
46 | gtk.DIALOG_MODAL,
47 | gtk.MESSAGE_INFO,
48 | gtk.BUTTONS_OK,
49 | strings.Join(files, "\n"))
50 | dialog.SetTitle("D&D")
51 | dialog.Response(func() {
52 | dialog.Destroy()
53 | })
54 | dialog.Run()
55 | }
56 | })
57 | vbox.Add(dest)
58 |
59 | window.Add(vbox)
60 |
61 | window.SetSizeRequest(300, 100)
62 | window.ShowAll()
63 | gtk.Main()
64 | }
65 |
--------------------------------------------------------------------------------
/_example/drawable/drawable.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/mattn/go-gtk/gdk"
5 | "github.com/mattn/go-gtk/glib"
6 | "github.com/mattn/go-gtk/gtk"
7 | "os"
8 | "unsafe"
9 | )
10 |
11 | type point struct {
12 | x int
13 | y int
14 | }
15 |
16 | func main() {
17 | gtk.Init(&os.Args)
18 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
19 | window.SetTitle("GTK DrawingArea")
20 | window.Connect("destroy", gtk.MainQuit)
21 |
22 | vbox := gtk.NewVBox(true, 0)
23 | vbox.SetBorderWidth(5)
24 | drawingarea := gtk.NewDrawingArea()
25 |
26 | var p1, p2 point
27 | var gdkwin *gdk.Window
28 | var pixmap *gdk.Pixmap
29 | var gc *gdk.GC
30 | p1.x = -1
31 | p1.y = -1
32 | colors := []string{
33 | "black",
34 | "gray",
35 | "blue",
36 | "purple",
37 | "red",
38 | "orange",
39 | "yellow",
40 | "green",
41 | "darkgreen",
42 | }
43 |
44 | drawingarea.Connect("configure-event", func() {
45 | if pixmap != nil {
46 | pixmap.Unref()
47 | }
48 | allocation := drawingarea.GetAllocation()
49 | pixmap = gdk.NewPixmap(drawingarea.GetWindow().GetDrawable(), allocation.Width, allocation.Height, 24)
50 | gc = gdk.NewGC(pixmap.GetDrawable())
51 | gc.SetRgbFgColor(gdk.NewColor("white"))
52 | pixmap.GetDrawable().DrawRectangle(gc, true, 0, 0, -1, -1)
53 | gc.SetRgbFgColor(gdk.NewColor(colors[0]))
54 | gc.SetRgbBgColor(gdk.NewColor("white"))
55 | })
56 |
57 | drawingarea.Connect("motion-notify-event", func(ctx *glib.CallbackContext) {
58 | arg := ctx.Args(0)
59 | mev := *(**gdk.EventMotion)(unsafe.Pointer(&arg))
60 | var mt gdk.ModifierType
61 | if mev.IsHint != 0 {
62 | gdkwin.GetPointer(&p2.x, &p2.y, &mt)
63 | } else {
64 | p2.x, p2.y = int(mev.X), int(mev.Y)
65 | }
66 | if p1.x != -1 && p2.x != -1 && (gdk.EventMask(mt)&gdk.BUTTON_PRESS_MASK) != 0 {
67 | pixmap.GetDrawable().DrawLine(gc, p1.x, p1.y, p2.x, p2.y)
68 | gdkwin.Invalidate(nil, false)
69 | }
70 | colors = append(colors[1:], colors[0])
71 | gc.SetRgbFgColor(gdk.NewColor(colors[0]))
72 | p1 = p2
73 | })
74 |
75 | drawingarea.Connect("expose-event", func() {
76 | if pixmap == nil {
77 | return
78 | }
79 | gdkwin.GetDrawable().DrawDrawable(gc, pixmap.GetDrawable(), 0, 0, 0, 0, -1, -1)
80 | })
81 |
82 | drawingarea.SetEvents(int(gdk.POINTER_MOTION_MASK | gdk.POINTER_MOTION_HINT_MASK | gdk.BUTTON_PRESS_MASK))
83 | vbox.Add(drawingarea)
84 |
85 | window.Add(vbox)
86 | window.SetSizeRequest(400, 400)
87 | window.ShowAll()
88 |
89 | gdkwin = drawingarea.GetWindow()
90 |
91 | gtk.Main()
92 | }
93 |
--------------------------------------------------------------------------------
/_example/event/event.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/gdk"
6 | "github.com/mattn/go-gtk/glib"
7 | "github.com/mattn/go-gtk/gtk"
8 | "os"
9 | "unsafe"
10 | )
11 |
12 | func main() {
13 | gtk.Init(&os.Args)
14 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
15 | window.SetTitle("GTK Events")
16 | window.Connect("destroy", gtk.MainQuit)
17 |
18 | event := make(chan interface{})
19 |
20 | window.Connect("key-press-event", func(ctx *glib.CallbackContext) {
21 | arg := ctx.Args(0)
22 | event <- *(**gdk.EventKey)(unsafe.Pointer(&arg))
23 | })
24 | window.Connect("motion-notify-event", func(ctx *glib.CallbackContext) {
25 | arg := ctx.Args(0)
26 | event <- *(**gdk.EventMotion)(unsafe.Pointer(&arg))
27 | })
28 |
29 | go func() {
30 | for {
31 | e := <-event
32 | switch ev := e.(type) {
33 | case *gdk.EventKey:
34 | fmt.Println("key-press-event:", ev.Keyval)
35 | break
36 | case *gdk.EventMotion:
37 | fmt.Println("motion-notify-event:", int(ev.X), int(ev.Y))
38 | break
39 | }
40 | }
41 | }()
42 |
43 | window.SetEvents(int(gdk.POINTER_MOTION_MASK | gdk.POINTER_MOTION_HINT_MASK | gdk.BUTTON_PRESS_MASK))
44 | window.SetSizeRequest(400, 400)
45 | window.ShowAll()
46 |
47 | gtk.Main()
48 | }
49 |
--------------------------------------------------------------------------------
/_example/example.mk:
--------------------------------------------------------------------------------
1 | EXAMPLES := \
2 | _example/action/action \
3 | _example/alignment/alignment \
4 | _example/builder/builder \
5 | _example/clipboard/clipboard \
6 | _example/demo/demo \
7 | _example/arrow/arrow \
8 | _example/dnd/dnd \
9 | _example/drawable/drawable \
10 | _example/event/event \
11 | _example/expander/expander \
12 | _example/iconview/iconview \
13 | _example/listview/listview \
14 | _example/locale/locale \
15 | _example/notebook/notebook \
16 | _example/number/number \
17 | _example/sourceview/sourceview \
18 | _example/spinbutton/spinbutton \
19 | _example/statusicon/statusicon \
20 | _example/table/table \
21 | _example/thread/thread \
22 | _example/toolbar/toolbar \
23 | _example/treeview/treeview \
24 | _example/twitterstream/twitterstream
25 |
26 | .PHONY: example
27 | example: $(EXAMPLES)
28 | @true
29 |
30 | .PHONY: clean-example
31 | clean-example:
32 | rm -f $(EXAMPLES)
33 |
34 | %: %.go
35 | cd $(@D) && go build -x
36 |
37 | example/action/action: example/action/action.go
38 | example/alignment/alignment: example/alignment/alignment.go
39 | example/builder/builder: example/builder/builder.go
40 | example/clipboard/clipboard: example/clipboard/clipboard.go
41 | example/demo/demo: example/demo/demo.go
42 | example/arrow/arrow: example/arrow/arrow.go
43 | example/dnd/dnd: example/dnd/dnd.go
44 | example/drawable/drawable: example/drawable/drawable.go
45 | example/event/event: example/event/event.go
46 | example/expander/expander: example/expander/expander.go
47 | example/iconview/iconview: example/iconview/iconview.go
48 | example/listview/listview: example/listview/listview.go
49 | example/locale/locale: example/locale/locale.go
50 | example/notebook/notebook: example/notebook/notebook.go
51 | example/number/number: example/number/number.go
52 | example/sourceview/sourceview: example/sourceview/sourceview.go
53 | example/spinbutton/spinbutton: example/spinbutton/spinbutton.go
54 | example/statusicon/statusicon: example/statusicon/statusicon.go
55 | example/table/table: example/table/table.go
56 | example/thread/thread: example/thread/thread.go
57 | example/toolbar/toolbar: example/toolbar/toolbar.go
58 | example/treeview/treeview: example/treeview/treeview.go
59 | example/twitterstream/twitterstream: example/twitterstream/twitterstream.go
60 |
--------------------------------------------------------------------------------
/_example/expander/expander.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/mattn/go-gtk/gtk"
5 | "os"
6 | )
7 |
8 | func main() {
9 | gtk.Init(&os.Args)
10 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
11 | window.SetTitle("We love Expander")
12 | window.Connect("destroy", gtk.MainQuit)
13 |
14 | vbox := gtk.NewVBox(true, 0)
15 | vbox.SetBorderWidth(5)
16 | expander := gtk.NewExpander("dan the ...")
17 | expander.Add(gtk.NewLabel("404 contents not found"))
18 | vbox.PackStart(expander, false, false, 0)
19 |
20 | window.Add(vbox)
21 | window.ShowAll()
22 |
23 | gtk.Main()
24 | }
25 |
--------------------------------------------------------------------------------
/_example/iconview/iconview.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 | "unsafe"
6 |
7 | "github.com/mattn/go-gtk/gdkpixbuf"
8 | "github.com/mattn/go-gtk/glib"
9 | "github.com/mattn/go-gtk/gtk"
10 | )
11 |
12 | func main() {
13 | gtk.Init(&os.Args)
14 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
15 | window.SetTitle("GTK Icon View")
16 | window.Connect("destroy", gtk.MainQuit)
17 |
18 | swin := gtk.NewScrolledWindow(nil, nil)
19 |
20 | store := gtk.NewListStore(gdkpixbuf.GetType(), glib.G_TYPE_STRING)
21 | iconview := gtk.NewIconViewWithModel(store)
22 | iconview.SetPixbufColumn(0)
23 | iconview.SetTextColumn(1)
24 | swin.Add(iconview)
25 |
26 | gtk.StockListIDs().ForEach(func(d unsafe.Pointer, v interface{}) {
27 | id := glib.GPtrToString(d)
28 | var iter gtk.TreeIter
29 | store.Append(&iter)
30 | store.Set(&iter,
31 | 0, gtk.NewImage().RenderIcon(id, gtk.ICON_SIZE_SMALL_TOOLBAR, "").GPixbuf,
32 | 1, id)
33 | })
34 |
35 | window.Add(swin)
36 | window.SetSizeRequest(500, 200)
37 | window.ShowAll()
38 |
39 | gtk.Main()
40 | }
41 |
--------------------------------------------------------------------------------
/_example/idle/idle.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 |
7 | "github.com/mattn/go-gtk/glib"
8 | )
9 |
10 | func main() {
11 | glib.IdleAdd(func() bool {
12 | fmt.Println("start")
13 | return false
14 | })
15 | glib.TimeoutAdd(1000, func() bool {
16 | fmt.Println(fmt.Sprintf("%v", time.Now()))
17 | return true
18 | })
19 |
20 | glib.NewMainLoop(nil, false).Run()
21 | }
22 |
--------------------------------------------------------------------------------
/_example/listview/listview.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 | "unsafe"
6 |
7 | "github.com/mattn/go-gtk/gdkpixbuf"
8 | "github.com/mattn/go-gtk/glib"
9 | "github.com/mattn/go-gtk/gtk"
10 | )
11 |
12 | func main() {
13 | gtk.Init(&os.Args)
14 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
15 | window.SetTitle("GTK Stock Icons")
16 | window.Connect("destroy", gtk.MainQuit)
17 |
18 | swin := gtk.NewScrolledWindow(nil, nil)
19 |
20 | store := gtk.NewListStore(glib.G_TYPE_STRING, glib.G_TYPE_BOOL, gdkpixbuf.GetType())
21 | treeview := gtk.NewTreeView()
22 | swin.Add(treeview)
23 |
24 | treeview.SetModel(store)
25 | treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes("name", gtk.NewCellRendererText(), "text", 0))
26 | treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes("check", gtk.NewCellRendererToggle(), "active", 1))
27 | treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes("icon", gtk.NewCellRendererPixbuf(), "pixbuf", 2))
28 | n := 0
29 | gtk.StockListIDs().ForEach(func(d unsafe.Pointer, v interface{}) {
30 | id := glib.GPtrToString(d)
31 | var iter gtk.TreeIter
32 | store.Append(&iter)
33 | store.Set(&iter,
34 | 0, id,
35 | 1, (n == 1),
36 | 2, gtk.NewImage().RenderIcon(id, gtk.ICON_SIZE_SMALL_TOOLBAR, "").GPixbuf,
37 | )
38 | n = 1 - n
39 | })
40 |
41 | window.Add(swin)
42 | window.SetSizeRequest(400, 200)
43 | window.ShowAll()
44 |
45 | gtk.Main()
46 | }
47 |
--------------------------------------------------------------------------------
/_example/locale/locale.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "github.com/mattn/go-gtk/gtk"
4 | import "github.com/mattn/go-gtk/glib"
5 | import "fmt"
6 | import "syscall"
7 |
8 | func main() {
9 | gtk.SetLocale()
10 |
11 | bs, _, _, err := glib.LocaleFromUtf8("こんにちわ世界\n")
12 | if err == nil {
13 | syscall.Write(syscall.Stdout, bs)
14 | } else {
15 | fmt.Println(err.Message())
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/_example/notebook/notebook.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/mattn/go-gtk/gtk"
5 | "os"
6 | "strconv"
7 | )
8 |
9 | func main() {
10 | gtk.Init(&os.Args)
11 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
12 | window.SetTitle("GTK Notebook")
13 | window.Connect("destroy", gtk.MainQuit)
14 |
15 | notebook := gtk.NewNotebook()
16 | for n := 1; n <= 10; n++ {
17 | page := gtk.NewFrame("demo" + strconv.Itoa(n))
18 | notebook.AppendPage(page, gtk.NewLabel("demo"+strconv.Itoa(n)))
19 |
20 | vbox := gtk.NewHBox(false, 1)
21 |
22 | prev := gtk.NewButtonWithLabel("go prev")
23 | prev.Clicked(func() {
24 | notebook.PrevPage()
25 | })
26 | vbox.Add(prev)
27 |
28 | next := gtk.NewButtonWithLabel("go next")
29 | next.Clicked(func() {
30 | notebook.NextPage()
31 | })
32 | vbox.Add(next)
33 |
34 | page.Add(vbox)
35 | }
36 |
37 | window.Add(notebook)
38 | window.SetSizeRequest(400, 200)
39 | window.ShowAll()
40 |
41 | gtk.Main()
42 | }
43 |
--------------------------------------------------------------------------------
/_example/number/number.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/glib"
6 | "github.com/mattn/go-gtk/gtk"
7 | "os"
8 | "strconv"
9 | "unsafe"
10 | )
11 |
12 | func main() {
13 | gtk.Init(&os.Args)
14 |
15 | dialog := gtk.NewDialog()
16 | dialog.SetTitle("number input")
17 |
18 | vbox := dialog.GetVBox()
19 |
20 | label := gtk.NewLabel("Numnber:")
21 | vbox.Add(label)
22 |
23 | input := gtk.NewEntry()
24 | input.SetEditable(true)
25 | vbox.Add(input)
26 |
27 | input.Connect("insert-text", func(ctx *glib.CallbackContext) {
28 | a := (*[2000]uint8)(unsafe.Pointer(ctx.Args(0)))
29 | p := (*int)(unsafe.Pointer(ctx.Args(2)))
30 | i := 0
31 | for a[i] != 0 {
32 | i++
33 | }
34 | s := string(a[0:i])
35 | if s == "." {
36 | if *p == 0 {
37 | input.StopEmission("insert-text")
38 | }
39 | } else {
40 | _, err := strconv.ParseFloat(s, 64)
41 | if err != nil {
42 | input.StopEmission("insert-text")
43 | }
44 | }
45 | })
46 |
47 | button := gtk.NewButtonWithLabel("OK")
48 | button.Connect("clicked", func() {
49 | fmt.Println(input.GetText())
50 | gtk.MainQuit()
51 | })
52 | vbox.Add(button)
53 |
54 | dialog.ShowAll()
55 | gtk.Main()
56 | }
57 |
--------------------------------------------------------------------------------
/_example/sourceview/sourceview.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/mattn/go-gtk/gtk"
5 | gsv "github.com/mattn/go-gtk/gtksourceview"
6 | "os"
7 | )
8 |
9 | func main() {
10 | gtk.Init(&os.Args)
11 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
12 | window.SetTitle("SourceView")
13 | window.Connect("destroy", gtk.MainQuit)
14 |
15 | swin := gtk.NewScrolledWindow(nil, nil)
16 | swin.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
17 | swin.SetShadowType(gtk.SHADOW_IN)
18 | sourcebuffer := gsv.NewSourceBufferWithLanguage(gsv.SourceLanguageManagerGetDefault().GetLanguage("cpp"))
19 | sourceview := gsv.NewSourceViewWithBuffer(sourcebuffer)
20 |
21 | var start gtk.TextIter
22 | sourcebuffer.GetStartIter(&start)
23 | sourcebuffer.BeginNotUndoableAction()
24 | sourcebuffer.Insert(&start, `#include
25 | template
26 | struct foo_base {
27 | T operator+(T const &rhs) const {
28 | T tmp(static_cast(*this));
29 | tmp += rhs;
30 | return tmp;
31 | }
32 | };
33 |
34 | class foo : public foo_base {
35 | private:
36 | int v;
37 | public:
38 | foo(int v) : v(v) {}
39 | foo &operator+=(foo const &rhs){
40 | this->v += rhs.v;
41 | return *this;
42 | }
43 | operator int() { return v; }
44 | };
45 |
46 | int main(void) {
47 | foo a(1), b(2);
48 | a += b;
49 | std::cout << (int)a << std::endl;
50 | }
51 | `)
52 | sourcebuffer.EndNotUndoableAction()
53 |
54 | swin.Add(sourceview)
55 |
56 | window.Add(swin)
57 | window.SetSizeRequest(400, 300)
58 | window.ShowAll()
59 |
60 | gtk.Main()
61 | }
62 |
--------------------------------------------------------------------------------
/_example/spinbutton/spinbutton.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/glib"
6 | "github.com/mattn/go-gtk/gtk"
7 | "strconv"
8 | )
9 |
10 | func main() {
11 | gtk.Init(nil)
12 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
13 | window.SetPosition(gtk.WIN_POS_CENTER)
14 | window.SetTitle("GTK Go!")
15 | window.Connect("destroy", func(ctx *glib.CallbackContext) {
16 | fmt.Println("got destroy!", ctx.Data().(string))
17 | gtk.MainQuit()
18 | }, "foo")
19 |
20 | //--------------------------------------------------------
21 | // GtkHBox
22 | //--------------------------------------------------------
23 | fixed := gtk.NewFixed()
24 |
25 | //--------------------------------------------------------
26 | // GtkSpinButton
27 | //--------------------------------------------------------
28 | spinbutton1 := gtk.NewSpinButtonWithRange(1.0, 10.0, 1.0)
29 | spinbutton1.SetDigits(3)
30 | spinbutton1.Spin(gtk.SPIN_STEP_FORWARD, 7.0)
31 | fixed.Put(spinbutton1, 40, 50)
32 |
33 | spinbutton1.OnValueChanged(func() {
34 | val := spinbutton1.GetValueAsInt()
35 | fval := spinbutton1.GetValue()
36 | fmt.Println("SpinButton changed, new value: " + strconv.Itoa(val) + " | " + strconv.FormatFloat(fval, 'f', 2, 64))
37 | min, max := spinbutton1.GetRange()
38 | fmt.Println("Range: " + strconv.FormatFloat(min, 'f', 2, 64) + " " + strconv.FormatFloat(max, 'f', 2, 64))
39 | fmt.Println("Digits: " + strconv.Itoa(int(spinbutton1.GetDigits())))
40 | })
41 |
42 | adjustment := gtk.NewAdjustment(2.0, 1.0, 8.0, 2.0, 0.0, 0.0)
43 | spinbutton2 := gtk.NewSpinButton(adjustment, 1.0, 1)
44 | spinbutton2.SetRange(0.0, 20.0)
45 | spinbutton2.SetValue(18.0)
46 | spinbutton2.SetIncrements(2.0, 4.0)
47 | fixed.Put(spinbutton2, 150, 50)
48 |
49 | //--------------------------------------------------------
50 | // Event
51 | //--------------------------------------------------------
52 | window.Add(fixed)
53 | window.SetSizeRequest(600, 600)
54 | window.ShowAll()
55 | gtk.Main()
56 | }
57 |
--------------------------------------------------------------------------------
/_example/statusicon/statusicon.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/glib"
6 | "github.com/mattn/go-gtk/gtk"
7 | "os"
8 | )
9 |
10 | func main() {
11 | gtk.Init(&os.Args)
12 |
13 | glib.SetApplicationName("go-gtk-statusicon-example")
14 |
15 | mi := gtk.NewMenuItemWithLabel("Popup!")
16 | mi.Connect("activate", func() {
17 | gtk.MainQuit()
18 | })
19 | nm := gtk.NewMenu()
20 | nm.Append(mi)
21 | nm.ShowAll()
22 |
23 | si := gtk.NewStatusIconFromStock(gtk.STOCK_FILE)
24 | si.SetTitle("StatusIcon Example")
25 | si.SetTooltipMarkup("StatusIcon Example")
26 | si.Connect("popup-menu", func(cbx *glib.CallbackContext) {
27 | nm.Popup(nil, nil, gtk.StatusIconPositionMenu, si, uint(cbx.Args(0)), uint32(cbx.Args(1)))
28 | })
29 |
30 | fmt.Println(`
31 | Can you see statusicon in systray?
32 | If you don't see it and if you use 'unity', try following.
33 |
34 | # gsettings set com.canonical.Unity.Panel systray-whitelist \
35 | "$(gsettings get com.canonical.Unity.Panel systray-whitelist \|
36 | sed -e "s/]$/, 'go-gtk-statusicon-example']/")"
37 | `)
38 |
39 | gtk.Main()
40 | }
41 |
--------------------------------------------------------------------------------
/_example/table/table.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/gtk"
6 | "os"
7 | )
8 |
9 | func main() {
10 | gtk.Init(&os.Args)
11 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
12 | window.SetTitle("GTK Table")
13 | window.Connect("destroy", gtk.MainQuit)
14 |
15 | swin := gtk.NewScrolledWindow(nil, nil)
16 | swin.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
17 |
18 | table := gtk.NewTable(5, 5, false)
19 | for y := uint(0); y < 5; y++ {
20 | for x := uint(0); x < 5; x++ {
21 | table.Attach(gtk.NewButtonWithLabel(fmt.Sprintf("%02d:%02d", x, y)), x, x+1, y, y+1, gtk.FILL, gtk.FILL, 5, 5)
22 | }
23 | }
24 | swin.AddWithViewPort(table)
25 |
26 | window.Add(swin)
27 | window.SetDefaultSize(200, 200)
28 | window.ShowAll()
29 |
30 | gtk.Main()
31 | }
32 |
--------------------------------------------------------------------------------
/_example/textview/textview.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/gdk"
6 | "github.com/mattn/go-gtk/glib"
7 | "github.com/mattn/go-gtk/gtk"
8 | "unsafe"
9 | )
10 |
11 | func main() {
12 | gtk.Init(nil)
13 |
14 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
15 | window.SetPosition(gtk.WIN_POS_CENTER)
16 | window.SetTitle("GTK Go!")
17 | window.SetIconName("textview")
18 | window.Connect("destroy", gtk.MainQuit)
19 |
20 | textview := gtk.NewTextView()
21 | textview.SetEditable(true)
22 | textview.SetCursorVisible(true)
23 | var iter gtk.TextIter
24 | buffer := textview.GetBuffer()
25 |
26 | buffer.GetStartIter(&iter)
27 | buffer.Insert(&iter, "Hello ")
28 |
29 | tag := buffer.CreateTag("bold", map[string]string{"background": "#FF0000", "weight": "700"})
30 | buffer.InsertWithTag(&iter, "Google!", tag)
31 |
32 | u := "http://www.google.com"
33 | tag.SetData("tag-name", unsafe.Pointer(&u))
34 | textview.Connect("event-after", func(ctx *glib.CallbackContext) {
35 | arg := ctx.Args(0)
36 | if ev := *(**gdk.EventAny)(unsafe.Pointer(&arg)); ev.Type != gdk.BUTTON_RELEASE {
37 | return
38 | }
39 | ev := *(**gdk.EventButton)(unsafe.Pointer(&arg))
40 | var iter gtk.TextIter
41 | textview.GetIterAtLocation(&iter, int(ev.X), int(ev.Y))
42 | tags := iter.GetTags()
43 | for n := uint(0); n < tags.Length(); n++ {
44 | vv := tags.NthData(n)
45 | tag := gtk.NewTextTagFromPointer(vv)
46 | u := *(*string)(tag.GetData("tag-name"))
47 | fmt.Println(u)
48 | }
49 | })
50 |
51 | window.Add(textview)
52 | window.SetSizeRequest(600, 600)
53 | window.ShowAll()
54 | gtk.Main()
55 | }
56 |
--------------------------------------------------------------------------------
/_example/thread/thread.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "runtime"
5 | "strconv"
6 | "time"
7 |
8 | "github.com/mattn/go-gtk/gdk"
9 | "github.com/mattn/go-gtk/glib"
10 | "github.com/mattn/go-gtk/gtk"
11 | )
12 |
13 | func main() {
14 | runtime.GOMAXPROCS(10)
15 | glib.ThreadInit(nil)
16 | gdk.ThreadsInit()
17 | gdk.ThreadsEnter()
18 | gtk.Init(nil)
19 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
20 | window.Connect("destroy", gtk.MainQuit)
21 |
22 | vbox := gtk.NewVBox(false, 1)
23 |
24 | label1 := gtk.NewLabel("")
25 | vbox.Add(label1)
26 | label2 := gtk.NewLabel("")
27 | vbox.Add(label2)
28 |
29 | window.Add(vbox)
30 |
31 | window.SetSizeRequest(100, 100)
32 | window.ShowAll()
33 | time.Sleep(1000 * 1000 * 100)
34 | go (func() {
35 | for i := 0; i < 300000; i++ {
36 | gdk.ThreadsEnter()
37 | label1.SetLabel(strconv.Itoa(i))
38 | gdk.ThreadsLeave()
39 | }
40 | gtk.MainQuit()
41 | })()
42 | go (func() {
43 | for i := 300000; i >= 0; i-- {
44 | gdk.ThreadsEnter()
45 | label2.SetLabel(strconv.Itoa(i))
46 | gdk.ThreadsLeave()
47 | }
48 | gtk.MainQuit()
49 | })()
50 | gtk.Main()
51 | }
52 |
--------------------------------------------------------------------------------
/_example/toolbar/toolbar.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/glib"
6 | "github.com/mattn/go-gtk/gtk"
7 | )
8 |
9 | func main() {
10 | gtk.Init(nil)
11 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
12 | window.SetPosition(gtk.WIN_POS_CENTER)
13 | window.SetTitle("GTK Go!")
14 | window.Connect("destroy", func(ctx *glib.CallbackContext) {
15 | gtk.MainQuit()
16 | }, "")
17 |
18 | vbox := gtk.NewVBox(false, 0)
19 |
20 | toolbar := gtk.NewToolbar()
21 | toolbar.SetStyle(gtk.TOOLBAR_ICONS)
22 | vbox.PackStart(toolbar, false, false, 5)
23 |
24 | btnnew := gtk.NewToolButtonFromStock(gtk.STOCK_NEW)
25 | btnclose := gtk.NewToolButtonFromStock(gtk.STOCK_CLOSE)
26 | separator := gtk.NewSeparatorToolItem()
27 | btncustom := gtk.NewToolButton(nil, "Custom")
28 | btnmenu := gtk.NewMenuToolButtonFromStock("gtk.STOCK_CLOSE")
29 | btnmenu.SetArrowTooltipText("This is a tool tip")
30 |
31 | btnnew.OnClicked(onToolButtonClicked)
32 | btnclose.OnClicked(onToolButtonClicked)
33 | btncustom.OnClicked(onToolButtonClicked)
34 |
35 | toolmenu := gtk.NewMenu()
36 | menuitem := gtk.NewMenuItemWithMnemonic("8")
37 | menuitem.Show()
38 | toolmenu.Append(menuitem)
39 | menuitem = gtk.NewMenuItemWithMnemonic("16")
40 | menuitem.Show()
41 | toolmenu.Append(menuitem)
42 | menuitem = gtk.NewMenuItemWithMnemonic("32")
43 | menuitem.Show()
44 | toolmenu.Append(menuitem)
45 | btnmenu.SetMenu(toolmenu)
46 |
47 | toolbar.Insert(btnnew, -1)
48 | toolbar.Insert(btnclose, -1)
49 | toolbar.Insert(separator, -1)
50 | toolbar.Insert(btncustom, -1)
51 | toolbar.Insert(btnmenu, -1)
52 |
53 | hbox := gtk.NewHBox(false, 0)
54 | vbox.PackStart(hbox, true, true, 0)
55 |
56 | toolbar2 := gtk.NewToolbar()
57 | toolbar2.SetOrientation(gtk.ORIENTATION_VERTICAL)
58 | hbox.PackStart(toolbar2, false, false, 5)
59 | btnhelp := gtk.NewToolButtonFromStock(gtk.STOCK_HELP)
60 | btnhelp.OnClicked(onToolButtonClicked)
61 | toolbar2.Insert(btnhelp, -1)
62 |
63 | btntoggle := gtk.NewToggleToolButton()
64 | btntoggle2 := gtk.NewToggleToolButtonFromStock(gtk.STOCK_ITALIC)
65 | toolbar2.Insert(btntoggle, -1)
66 | toolbar2.Insert(btntoggle2, -1)
67 |
68 | for i := 0; i < toolbar.GetNItems(); i++ {
69 | gti := toolbar.GetNthItem(i)
70 | switch gti.(type) {
71 | case *gtk.ToolButton:
72 | fmt.Printf("toolbar[%d] is a *gtk.ToolButton\n", i)
73 | w := gti.(*gtk.ToolButton).GetIconWidget()
74 | gti.(*gtk.ToolButton).SetIconWidget(w)
75 | case *gtk.ToggleToolButton:
76 | fmt.Printf("toolbar[%d] is a *gtk.ToggleToolButton\n", i)
77 | gti.(*gtk.ToggleToolButton).SetActive(true)
78 | case *gtk.SeparatorToolItem:
79 | fmt.Printf("toolbar[%d] is a *gtk.SeparatorToolItem\n", i)
80 | default:
81 | fmt.Printf("toolbar: Item is of unknown type\n")
82 | }
83 | }
84 |
85 | for i := 0; i < toolbar2.GetNItems(); i++ {
86 | gti := toolbar2.GetNthItem(i)
87 | switch gti.(type) {
88 | case *gtk.ToolButton:
89 | fmt.Printf("toolbar2[%d] is a *gtk.ToolButton\n", i)
90 | case *gtk.ToggleToolButton:
91 | fmt.Printf("toolbar2[%d] is a *gtk.ToggleToolButton\n", i)
92 | gti.(*gtk.ToggleToolButton).SetActive(true)
93 | case *gtk.SeparatorToolItem:
94 | fmt.Printf("toolbar2[%d] is a *gtk.SeparatorToolItem\n", i)
95 | default:
96 | fmt.Printf("toolbar2: Item is of unknown type\n")
97 | }
98 | }
99 |
100 | window.Add(vbox)
101 | window.SetSizeRequest(600, 600)
102 | window.ShowAll()
103 | gtk.Main()
104 | }
105 |
106 | func onToolButtonClicked() {
107 | fmt.Println("ToolButton clicked")
108 | }
109 |
--------------------------------------------------------------------------------
/_example/toolpalette/toolpalette.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/mattn/go-gtk/glib"
6 | "github.com/mattn/go-gtk/gtk"
7 | )
8 |
9 | func main() {
10 | gtk.Init(nil)
11 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
12 | window.SetPosition(gtk.WIN_POS_CENTER)
13 | window.SetTitle("GTK Go!")
14 | window.Connect("destroy", func(ctx *glib.CallbackContext) {
15 | gtk.MainQuit()
16 | }, "")
17 |
18 | box := gtk.NewHPaned()
19 |
20 | palette := gtk.NewToolPalette()
21 | group := gtk.NewToolItemGroup("Tools")
22 | b := gtk.NewToolButtonFromStock(gtk.STOCK_NEW)
23 | b.OnClicked(func() { fmt.Println("You clicked new!") })
24 | group.Insert(b, -1)
25 | b = gtk.NewToolButtonFromStock(gtk.STOCK_CLOSE)
26 | group.Insert(b, -1)
27 | b = gtk.NewToolButtonFromStock(gtk.STOCK_REDO)
28 | group.Insert(b, -1)
29 | b = gtk.NewToolButtonFromStock(gtk.STOCK_REFRESH)
30 | group.Insert(b, -1)
31 | b = gtk.NewToolButtonFromStock(gtk.STOCK_QUIT)
32 | group.Insert(b, -1)
33 | b = gtk.NewToolButtonFromStock(gtk.STOCK_YES)
34 | group.Insert(b, -1)
35 | b = gtk.NewToolButtonFromStock(gtk.STOCK_NO)
36 | group.Insert(b, -1)
37 | b = gtk.NewToolButtonFromStock(gtk.STOCK_PRINT)
38 | group.Insert(b, -1)
39 | b = gtk.NewToolButtonFromStock(gtk.STOCK_NETWORK)
40 | group.Insert(b, -1)
41 | b = gtk.NewToolButtonFromStock(gtk.STOCK_INFO)
42 | group.Insert(b, -1)
43 | b = gtk.NewToolButtonFromStock(gtk.STOCK_HOME)
44 | group.Insert(b, -1)
45 | b = gtk.NewToolButtonFromStock(gtk.STOCK_INDEX)
46 | group.Insert(b, -1)
47 | b = gtk.NewToolButtonFromStock(gtk.STOCK_FIND)
48 | group.Insert(b, -1)
49 | b = gtk.NewToolButtonFromStock(gtk.STOCK_FILE)
50 | group.Insert(b, -1)
51 | b = gtk.NewToolButtonFromStock(gtk.STOCK_EXECUTE)
52 | group.Insert(b, -1)
53 | palette.Add(group)
54 |
55 | bcopy := gtk.NewToolButtonFromStock(gtk.STOCK_COPY)
56 | bcut := gtk.NewToolButtonFromStock(gtk.STOCK_CUT)
57 | bdelete := gtk.NewToolButtonFromStock(gtk.STOCK_DELETE)
58 |
59 | group = gtk.NewToolItemGroup("Stuff")
60 | group.Insert(bcopy, -1)
61 | group.Insert(bcut, -1)
62 | group.Insert(bdelete, -1)
63 | palette.Add(group)
64 |
65 | frame := gtk.NewVBox(false, 1)
66 | align := gtk.NewAlignment(0, 0, 0, 0)
67 | image := gtk.NewImageFromFile("./turkey.jpg")
68 | align.Add(image)
69 | frame.Add(align)
70 |
71 | box.Pack1(palette, true, false)
72 | box.Pack2(frame, false, false)
73 |
74 | window.Add(box)
75 | window.SetSizeRequest(600, 600)
76 | window.ShowAll()
77 | gtk.Main()
78 | }
79 |
--------------------------------------------------------------------------------
/_example/toolpalette/turkey.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattn/go-gtk/48574e312fac321db5119d8f2e7c8349cf44b92f/_example/toolpalette/turkey.jpg
--------------------------------------------------------------------------------
/_example/treeview/treeview.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/mattn/go-gtk/gdkpixbuf"
5 | "github.com/mattn/go-gtk/glib"
6 | "github.com/mattn/go-gtk/gtk"
7 | "os"
8 | "strconv"
9 | )
10 |
11 | func main() {
12 | gtk.Init(&os.Args)
13 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
14 | window.SetTitle("GTK Folder View")
15 | window.Connect("destroy", gtk.MainQuit)
16 |
17 | swin := gtk.NewScrolledWindow(nil, nil)
18 |
19 | store := gtk.NewTreeStore(gdkpixbuf.GetType(), glib.G_TYPE_STRING)
20 | treeview := gtk.NewTreeView()
21 | swin.Add(treeview)
22 |
23 | treeview.SetModel(store.ToTreeModel())
24 | treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes("pixbuf", gtk.NewCellRendererPixbuf(), "pixbuf", 0))
25 | treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes("text", gtk.NewCellRendererText(), "text", 1))
26 |
27 | for n := 1; n <= 10; n++ {
28 | var iter1, iter2, iter3 gtk.TreeIter
29 | store.Append(&iter1, nil)
30 | store.Set(&iter1, gtk.NewImage().RenderIcon(gtk.STOCK_DIRECTORY, gtk.ICON_SIZE_SMALL_TOOLBAR, "").GPixbuf, "Folder"+strconv.Itoa(n))
31 | store.Append(&iter2, &iter1)
32 | store.Set(&iter2, gtk.NewImage().RenderIcon(gtk.STOCK_DIRECTORY, gtk.ICON_SIZE_SMALL_TOOLBAR, "").GPixbuf, "SubFolder"+strconv.Itoa(n))
33 | store.Append(&iter3, &iter2)
34 | store.Set(&iter3, gtk.NewImage().RenderIcon(gtk.STOCK_FILE, gtk.ICON_SIZE_SMALL_TOOLBAR, "").GPixbuf, "File"+strconv.Itoa(n))
35 | }
36 |
37 | treeview.Connect("row_activated", func() {
38 | var path *gtk.TreePath
39 | var column *gtk.TreeViewColumn
40 | treeview.GetCursor(&path, &column)
41 | mes := "TreePath is: " + path.String()
42 | dialog := gtk.NewMessageDialog(
43 | treeview.GetTopLevelAsWindow(),
44 | gtk.DIALOG_MODAL,
45 | gtk.MESSAGE_INFO,
46 | gtk.BUTTONS_OK,
47 | mes)
48 | dialog.SetTitle("TreePath")
49 | dialog.Response(func() {
50 | dialog.Destroy()
51 | })
52 | dialog.Run()
53 | })
54 |
55 | window.Add(swin)
56 | window.SetSizeRequest(400, 200)
57 | window.ShowAll()
58 |
59 | gtk.Main()
60 | }
61 |
--------------------------------------------------------------------------------
/_example/twitterstream/settings.json.example:
--------------------------------------------------------------------------------
1 | {
2 | "AccessSecret": "ACCCESS_TOKEN_SECRET",
3 | "AccessToken": "ACCESS_TOKEN",
4 | "ClientSecret": "CLIENT_SECRET",
5 | "ClientToken": "CLIENT_TOKEN"
6 | }
7 |
--------------------------------------------------------------------------------
/_example/twitterstream/twitterstream.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "compress/gzip"
6 | "encoding/json"
7 | "fmt"
8 | "io/ioutil"
9 | "log"
10 | "net/http"
11 | "net/url"
12 | "os"
13 | "runtime"
14 | "strings"
15 | "sync"
16 |
17 | "github.com/garyburd/go-oauth/oauth"
18 | "github.com/mattn/go-gtk/gdkpixbuf"
19 | "github.com/mattn/go-gtk/gtk"
20 | )
21 |
22 | var (
23 | alive = true
24 | )
25 |
26 | func readURL(url string) ([]byte, *http.Response) {
27 | r, err := http.Get(url)
28 | if err != nil {
29 | return nil, nil
30 | }
31 | var b []byte
32 | if b, err = ioutil.ReadAll(r.Body); err != nil {
33 | return nil, nil
34 | }
35 | return b, r
36 | }
37 |
38 | func bytes2pixbuf(data []byte, typ string) *gdkpixbuf.Pixbuf {
39 | var loader *gdkpixbuf.Loader
40 | if strings.Index(typ, "jpeg") >= 0 {
41 | loader, _ = gdkpixbuf.NewLoaderWithMimeType("image/jpeg")
42 | } else {
43 | loader, _ = gdkpixbuf.NewLoaderWithMimeType("image/png")
44 | }
45 | loader.SetSize(24, 24)
46 | loader.Write(data)
47 | loader.Close()
48 | return loader.GetPixbuf()
49 | }
50 |
51 | type tweet struct {
52 | Text string
53 | Identifier string `json:"id_str"`
54 | Source string
55 | User struct {
56 | Name string
57 | ScreenName string `json:"screen_name"`
58 | FollowersCount int `json:"followers_count"`
59 | ProfileImageUrl string `json:"profile_image_url"`
60 | }
61 | Place *struct {
62 | Id string
63 | FullName string `json:"full_name"`
64 | }
65 | Entities struct {
66 | HashTags []struct {
67 | Indices [2]int
68 | Text string
69 | }
70 | UserMentions []struct {
71 | Indices [2]int
72 | ScreenName string `json:"screen_name"`
73 | } `json:"user_mentions"`
74 | Urls []struct {
75 | Indices [2]int
76 | Url string
77 | DisplayUrl string `json:"display_url"`
78 | ExpandedUrl *string `json:"expanded_url"`
79 | }
80 | }
81 | }
82 |
83 | func stream(client *oauth.Client, cred *oauth.Credentials, f func(*tweet)) {
84 | param := make(url.Values)
85 | uri := "https://userstream.twitter.com/1.1/user.json"
86 | client.SignParam(cred, "GET", uri, param)
87 | uri = uri + "?" + param.Encode()
88 | res, err := http.Get(uri)
89 | if err != nil {
90 | log.Fatal("failed to get tweets:", err)
91 | }
92 | defer res.Body.Close()
93 | if res.StatusCode != 200 {
94 | log.Fatal("failed to get tweets:", err)
95 | }
96 | var buf *bufio.Reader
97 | if res.Header.Get("Content-Encoding") == "gzip" {
98 | gr, err := gzip.NewReader(res.Body)
99 | if err != nil {
100 | log.Fatal("failed to make gzip decoder:", err)
101 | }
102 | buf = bufio.NewReader(gr)
103 | } else {
104 | buf = bufio.NewReader(res.Body)
105 | }
106 | var last []byte
107 | for alive {
108 | b, _, err := buf.ReadLine()
109 | last = append(last, b...)
110 | var t tweet
111 | err = json.Unmarshal(last, &t)
112 | if err != nil {
113 | continue
114 | }
115 | last = []byte{}
116 | if t.Text == "" {
117 | continue
118 | }
119 | f(&t)
120 | }
121 | }
122 |
123 | func post(client *oauth.Client, cred *oauth.Credentials, s string) {
124 | param := make(url.Values)
125 | param.Set("status", s)
126 | uri := "https://api.twitter.com/1.1/statuses/update.json"
127 | client.SignParam(cred, "POST", uri, param)
128 | res, err := http.PostForm(uri, url.Values(param))
129 | if err != nil {
130 | log.Println("failed to post tweet:", err)
131 | return
132 | }
133 | defer res.Body.Close()
134 | if res.StatusCode != 200 {
135 | log.Println("failed to get timeline:", err)
136 | return
137 | }
138 | }
139 |
140 | func display(t *tweet, buffer *gtk.TextBuffer, tag *gtk.TextTag) {
141 | var iter gtk.TextIter
142 | pixbufbytes, resp := readURL(t.User.ProfileImageUrl)
143 | buffer.GetStartIter(&iter)
144 | if resp != nil {
145 | buffer.InsertPixbuf(&iter, bytes2pixbuf(pixbufbytes, resp.Header.Get("Content-Type")))
146 | }
147 | buffer.Insert(&iter, " ")
148 | buffer.InsertWithTag(&iter, t.User.ScreenName, tag)
149 | buffer.Insert(&iter, ":"+t.Text+"\n")
150 | gtk.MainIterationDo(false)
151 | }
152 |
153 | func show(client *oauth.Client, cred *oauth.Credentials, f func(t *tweet)) {
154 | param := make(url.Values)
155 | uri := "https://api.twitter.com/1.1/statuses/home_timeline.json"
156 | client.SignParam(cred, "GET", uri, param)
157 | uri = uri + "?" + param.Encode()
158 | res, err := http.Get(uri)
159 | if err != nil {
160 | return
161 | }
162 | defer res.Body.Close()
163 | if res.StatusCode != 200 {
164 | return
165 | }
166 | var tweets []tweet
167 | json.NewDecoder(res.Body).Decode(&tweets)
168 | for _, t := range tweets {
169 | f(&t)
170 | }
171 | }
172 |
173 | func main() {
174 | b, err := ioutil.ReadFile("settings.json")
175 | if err != nil {
176 | fmt.Println(`"settings.json" not found: `, err)
177 | return
178 | }
179 | var config map[string]string
180 | err = json.Unmarshal(b, &config)
181 | if err != nil {
182 | fmt.Println(`can't read "settings.json": `, err)
183 | return
184 | }
185 | client := &oauth.Client{Credentials: oauth.Credentials{config["ClientToken"], config["ClientSecret"]}}
186 | cred := &oauth.Credentials{config["AccessToken"], config["AccessSecret"]}
187 |
188 | runtime.LockOSThread()
189 | gtk.Init(&os.Args)
190 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
191 | window.SetTitle("Twitter!")
192 | window.Connect("destroy", gtk.MainQuit)
193 |
194 | vbox := gtk.NewVBox(false, 1)
195 |
196 | scrolledwin := gtk.NewScrolledWindow(nil, nil)
197 | textview := gtk.NewTextView()
198 | textview.SetEditable(false)
199 | textview.SetCursorVisible(false)
200 | scrolledwin.Add(textview)
201 | vbox.Add(scrolledwin)
202 |
203 | buffer := textview.GetBuffer()
204 | tag := buffer.CreateTag("blue", map[string]string{"foreground": "#0000FF", "weight": "700"})
205 |
206 | hbox := gtk.NewHBox(false, 1)
207 | vbox.PackEnd(hbox, false, true, 5)
208 |
209 | label := gtk.NewLabel("Tweet")
210 | hbox.PackStart(label, false, false, 5)
211 | text := gtk.NewEntry()
212 | hbox.PackEnd(text, true, true, 5)
213 |
214 | text.Connect("activate", func() {
215 | t := text.GetText()
216 | text.SetText("")
217 | post(client, cred, t)
218 | })
219 |
220 | window.Add(vbox)
221 | window.SetSizeRequest(800, 500)
222 | window.ShowAll()
223 |
224 | var mutex sync.Mutex
225 |
226 | go func() {
227 | show(client, cred, func(t *tweet) {
228 | mutex.Lock()
229 | display(t, buffer, tag)
230 | mutex.Unlock()
231 | })
232 |
233 | stream(client, cred, func(t *tweet) {
234 | mutex.Lock()
235 | display(t, buffer, tag)
236 | var start, end gtk.TextIter
237 | buffer.GetIterAtLine(&start, buffer.GetLineCount()-2)
238 | buffer.GetEndIter(&end)
239 | buffer.Delete(&start, &end)
240 | mutex.Unlock()
241 | })
242 | }()
243 |
244 | for alive {
245 | mutex.Lock()
246 | alive = gtk.MainIterationDo(false)
247 | mutex.Unlock()
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/data/go-gtk-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattn/go-gtk/48574e312fac321db5119d8f2e7c8349cf44b92f/data/go-gtk-logo.png
--------------------------------------------------------------------------------
/data/mattn-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattn/go-gtk/48574e312fac321db5119d8f2e7c8349cf44b92f/data/mattn-logo.png
--------------------------------------------------------------------------------
/data/win32-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattn/go-gtk/48574e312fac321db5119d8f2e7c8349cf44b92f/data/win32-demo.png
--------------------------------------------------------------------------------
/data/win32-twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattn/go-gtk/48574e312fac321db5119d8f2e7c8349cf44b92f/data/win32-twitter.png
--------------------------------------------------------------------------------
/gdk/gdk.go.h:
--------------------------------------------------------------------------------
1 | #ifndef GO_GDK_H
2 | #define GO_GDK_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | static gchar* toGstr(char* s) { return (gchar*)s; }
12 |
13 | static void freeCstr(char* s) { free(s); }
14 |
15 | static GdkWindow* toGdkWindow(void* w) { return GDK_WINDOW(w); }
16 | static GdkDragContext* toGdkDragContext(void* l) { return (GdkDragContext*)l; }
17 | static GdkFont* toGdkFont(void* l) { return (GdkFont*)l; }
18 |
19 | static void* _gdk_display_get_default() {
20 | return (void*) gdk_display_get_default();
21 | }
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/gdk/gdk_freebsd.go:
--------------------------------------------------------------------------------
1 | gdk_linux.go
--------------------------------------------------------------------------------
/gdk/gdk_linux.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package gdk
4 |
5 | /*
6 | #include
7 | #include
8 | // #cgo pkg-config: gdk-2.0 gthread-2.0
9 | */
10 | import "C"
11 | import "unsafe"
12 |
13 | func (v *Window) GetNativeWindowID() int32 {
14 | return int32(C.gdk_x11_drawable_get_xid((*C.GdkDrawable)(unsafe.Pointer(v.GWindow))))
15 | }
16 |
--------------------------------------------------------------------------------
/gdk/gdk_quartz_darwin.go:
--------------------------------------------------------------------------------
1 | // +build !with-x11
2 |
3 | package gdk
4 |
5 | /*
6 | #cgo pkg-config: gdk-2.0 gthread-2.0
7 | #cgo CFLAGS: -x objective-c
8 |
9 | #include
10 | #include
11 |
12 | // Must return void* to avoid "struct size calculation error off=8 bytesize=0"
13 | // See:
14 | // - https://github.com/golang/go/issues/12065
15 | // - http://thread0.me/2015/07/gogoa-cocoa-bindings-for-go/
16 | void* getNsWindow(GdkWindow *w) {
17 | return (void*) gdk_quartz_window_get_nswindow(w);
18 | }
19 |
20 | */
21 | import "C"
22 |
23 | import "unsafe"
24 |
25 | type NSWindow struct {
26 | ID unsafe.Pointer
27 | }
28 |
29 | func (v *Window) GetNativeWindow() *NSWindow {
30 | return &NSWindow{
31 | unsafe.Pointer(C.getNsWindow(v.GWindow)),
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/gdk/gdk_windows.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package gdk
4 |
5 | /*
6 | #include
7 | #include
8 | // #cgo pkg-config: gdk-2.0 gthread-2.0
9 | */
10 | import "C"
11 | import "unsafe"
12 |
13 | func (v *Window) GetNativeWindowID() int32 {
14 | return int32(uintptr(unsafe.Pointer(C.gdk_win32_drawable_get_handle((*C.GdkDrawable)(unsafe.Pointer(v.GWindow))))))
15 | }
16 |
--------------------------------------------------------------------------------
/gdk/gdk_x11_darwin.go:
--------------------------------------------------------------------------------
1 | // +build with-x11
2 |
3 | package gdk
4 |
5 | /*
6 | #cgo pkg-config: gdk-2.0 gthread-2.0
7 |
8 | #include
9 | #include
10 | */
11 | import "C"
12 | import "unsafe"
13 |
14 | func (v *Window) GetNativeWindowID() int32 {
15 | return int32(C.gdk_x11_drawable_get_xid((*C.GdkDrawable)(unsafe.Pointer(v.GWindow))))
16 | }
17 |
--------------------------------------------------------------------------------
/gdkpixbuf/gdkpixbuf.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package gdkpixbuf
4 |
5 | // #include "gdkpixbuf.go.h"
6 | // #cgo pkg-config: gdk-pixbuf-2.0
7 | import "C"
8 | import (
9 | "log"
10 | "runtime"
11 | "unsafe"
12 |
13 | "github.com/mattn/go-gtk/gio"
14 | "github.com/mattn/go-gtk/glib"
15 | )
16 |
17 | // PixbufData is an inline/embedded image data object for usage with NewPixbufFromData.
18 | type PixbufData struct {
19 | Data []byte
20 | Colorspace Colorspace
21 | HasAlpha bool
22 | BitsPerSample, Width, Height, RowStride int
23 | }
24 |
25 | func gstring(s *C.char) *C.gchar { return C.toGstr(s) }
26 | func cstring(s *C.gchar) *C.char { return C.toCstr(s) }
27 | func gostring(s *C.gchar) string { return C.GoString(cstring(s)) }
28 |
29 | func gbool(b bool) C.gboolean {
30 | if b {
31 | return C.gboolean(1)
32 | }
33 | return C.gboolean(0)
34 | }
35 |
36 | func gobool(b C.gboolean) bool {
37 | if b != 0 {
38 | return true
39 | }
40 | return false
41 | }
42 |
43 | func cfree(s *C.char) { C.freeCstr(s) }
44 |
45 | func panic_if_version_older(major int, minor int, micro int, function string) {
46 | if C._check_version(C.int(major), C.int(minor), C.int(micro)) == 0 {
47 | log.Panicf("%s is not provided on your Glib, version %d.%d is required\n", function, major, minor)
48 | }
49 | }
50 |
51 | func panic_if_version_older_auto(major, minor, micro int) {
52 | if C._check_version(C.int(major), C.int(minor), C.int(micro)) != 0 {
53 | return
54 | }
55 | formatStr := "%s is not provided on your Glib, version %d.%d is required\n"
56 | if pc, _, _, ok := runtime.Caller(1); ok {
57 | log.Panicf(formatStr, runtime.FuncForPC(pc).Name(), major, minor)
58 | } else {
59 | log.Panicf("Glib version %d.%d is required (unknown caller, see stack)\n",
60 | major, minor)
61 | }
62 | }
63 |
64 | func deprecated_since(major int, minor int, micro int, function string) {
65 | if C._check_version(C.int(major), C.int(minor), C.int(micro)) != 0 {
66 | log.Printf("\nWarning: %s is deprecated since glib %d.%d\n", function, major, minor)
67 | }
68 | }
69 |
70 | func argumentPanic(message string) {
71 | if pc, _, _, ok := runtime.Caller(2); ok {
72 | log.Panicf("Arguments error: %s : %s\n",
73 | runtime.FuncForPC(pc).Name(), message)
74 | } else {
75 | log.Panicln("Arguments error: (unknown caller, see stack):", message)
76 | }
77 | }
78 |
79 | //-----------------------------------------------------------------------
80 | // Pixbuf
81 | //-----------------------------------------------------------------------
82 | type Pixbuf struct {
83 | *GdkPixbuf
84 | *glib.GObject
85 | }
86 |
87 | type GdkPixbuf struct {
88 | GPixbuf *C.GdkPixbuf
89 | }
90 |
91 | func NewGdkPixbuf(p unsafe.Pointer) *GdkPixbuf {
92 | return &GdkPixbuf{(*C.GdkPixbuf)(p)}
93 | }
94 |
95 | // File Loading
96 | // GdkPixbuf * gdk_pixbuf_new (GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height);
97 | func NewPixbuf(colorspace Colorspace, hasAlpha bool, bitsPerSample, width, height int) *Pixbuf {
98 | gpixbuf := C.gdk_pixbuf_new(
99 | C.GdkColorspace(colorspace),
100 | gbool(hasAlpha),
101 | C.int(bitsPerSample),
102 | C.int(width),
103 | C.int(height),
104 | )
105 |
106 | return &Pixbuf{
107 | GdkPixbuf: &GdkPixbuf{gpixbuf},
108 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
109 | }
110 | }
111 |
112 | func NewPixbufFromFile(filename string) (*Pixbuf, *glib.Error) {
113 | var err *C.GError
114 | ptr := C.CString(filename)
115 | defer cfree(ptr)
116 | gpixbuf := C.gdk_pixbuf_new_from_file(ptr, &err)
117 | if err != nil {
118 | return nil, glib.ErrorFromNative(unsafe.Pointer(err))
119 | }
120 | return &Pixbuf{
121 | GdkPixbuf: &GdkPixbuf{gpixbuf},
122 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
123 | }, nil
124 | }
125 |
126 | func NewPixbufFromFileAtSize(filename string, width, heigth int) (*Pixbuf, *glib.Error) {
127 | var err *C.GError
128 | ptr := C.CString(filename)
129 | defer cfree(ptr)
130 | gpixbuf := C.gdk_pixbuf_new_from_file_at_size(ptr, C.int(width), C.int(heigth), &err)
131 | if err != nil {
132 | return nil, glib.ErrorFromNative(unsafe.Pointer(err))
133 | }
134 | return &Pixbuf{
135 | GdkPixbuf: &GdkPixbuf{gpixbuf},
136 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
137 | }, nil
138 | }
139 |
140 | func NewPixbufFromFileAtScale(filename string, width, height int, preserve_aspect_ratio bool) (*Pixbuf, *glib.Error) {
141 | var err *C.GError
142 | ptr := C.CString(filename)
143 | defer cfree(ptr)
144 | gpixbuf := C.gdk_pixbuf_new_from_file_at_scale(ptr, C.int(width), C.int(height), gbool(preserve_aspect_ratio), &err)
145 | if err != nil {
146 | return nil, glib.ErrorFromNative(unsafe.Pointer(err))
147 | }
148 | return &Pixbuf{
149 | GdkPixbuf: &GdkPixbuf{gpixbuf},
150 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
151 | }, nil
152 | }
153 |
154 | // NewPixbufFromData creates a Pixbuf from image data in a byte array
155 | func NewPixbufFromData(pbd PixbufData) *Pixbuf {
156 | gpixbuf := C.gdk_pixbuf_new_from_data(
157 | C.to_gucharptr(unsafe.Pointer(&pbd.Data[0])),
158 | C.GdkColorspace(pbd.Colorspace),
159 | gbool(pbd.HasAlpha),
160 | C.int(pbd.BitsPerSample),
161 | C.int(pbd.Width),
162 | C.int(pbd.Height),
163 | C.int(pbd.RowStride),
164 | nil, nil)
165 | return &Pixbuf{
166 | GdkPixbuf: &GdkPixbuf{gpixbuf},
167 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
168 | }
169 | }
170 |
171 | // NewPixbufFromBytes creates a Pixbuf from image data in a byte array
172 | //
173 | // Can be used for reading Base64 encoded images easily with the output from base64.StdEncoding.DecodeString("...")
174 | func NewPixbufFromBytes(buffer []byte) (*Pixbuf, *glib.Error) {
175 | var err *C.GError
176 | loader := C.gdk_pixbuf_loader_new()
177 | C.gdk_pixbuf_loader_write(loader, C.to_gucharptr(unsafe.Pointer(&buffer[0])), C.gsize(len(buffer)), &err)
178 | gpixbuf := C.gdk_pixbuf_loader_get_pixbuf(loader)
179 |
180 | if err != nil {
181 | return nil, glib.ErrorFromNative(unsafe.Pointer(err))
182 | }
183 | return &Pixbuf{
184 | GdkPixbuf: &GdkPixbuf{gpixbuf},
185 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
186 | }, nil
187 | }
188 |
189 | func NewPixbufFromStream(stream *gio.GInputStream) (*Pixbuf, *glib.Error) {
190 | ptr := (*C.GInputStream)(unsafe.Pointer(stream.GInputStream))
191 |
192 | var err *C.GError
193 | gpixbuf := C.gdk_pixbuf_new_from_stream(ptr, nil, &err)
194 | if err != nil {
195 | return nil, glib.ErrorFromNative(unsafe.Pointer(err))
196 | }
197 | return &Pixbuf{
198 | GdkPixbuf: &GdkPixbuf{gpixbuf},
199 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
200 | }, nil
201 | }
202 |
203 | func NewPixbufFromXpmData(data **byte) (*Pixbuf, *glib.Error) {
204 | var err *C.GError
205 | gpixbuf := C.gdk_pixbuf_new_from_xpm_data(
206 | (**C.char)(unsafe.Pointer(data)),
207 | )
208 | if err != nil {
209 | return nil, glib.ErrorFromNative(unsafe.Pointer(err))
210 | }
211 | return &Pixbuf{
212 | GdkPixbuf: &GdkPixbuf{gpixbuf},
213 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
214 | }, nil
215 | }
216 |
217 | func GetType() int {
218 | return int(C.gdk_pixbuf_get_type())
219 | }
220 |
221 | func GetFileInfo(filename string, width, height *int) *Format {
222 | ptr := C.CString(filename)
223 | defer cfree(ptr)
224 |
225 | var w, h C.gint
226 | format := &Format{C.gdk_pixbuf_get_file_info(gstring(ptr), &w, &h)}
227 | *width = int(w)
228 | *height = int(h)
229 | return format
230 | }
231 |
232 | // Scaling
233 |
234 | type InterpType int
235 |
236 | const (
237 | INTERP_NEAREST InterpType = iota
238 | INTERP_TILES
239 | INTERP_BILINEAR
240 | INTERP_HYPER
241 | )
242 |
243 | func (p *Pixbuf) ScaleSimple(width, height int, interp InterpType) *Pixbuf {
244 | gpixbuf := C.gdk_pixbuf_scale_simple(p.GPixbuf, C.int(width), C.int(height), C.GdkInterpType(interp))
245 | return &Pixbuf{
246 | GdkPixbuf: &GdkPixbuf{gpixbuf},
247 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
248 | }
249 | }
250 |
251 | func (p *Pixbuf) Scale(x, y, width, height int, offsetX, offsetY, scaleX, scaleY float64, interp InterpType) *Pixbuf {
252 | var gpixbuf *C.GdkPixbuf
253 | C.gdk_pixbuf_scale(
254 | p.GPixbuf,
255 | gpixbuf,
256 | C.int(x), C.int(y),
257 | C.int(width), C.int(height),
258 | C.double(offsetX), C.double(offsetY),
259 | C.double(scaleX), C.double(scaleY),
260 | C.GdkInterpType(interp))
261 | return &Pixbuf{
262 | GdkPixbuf: &GdkPixbuf{gpixbuf},
263 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
264 | }
265 | }
266 |
267 | // gdk_pixbuf_composite_color_simple
268 | // gdk_pixbuf_composite
269 | // gdk_pixbuf_composite_color
270 |
271 | type PixbufRotation int
272 |
273 | const (
274 | PIXBUF_ROTATE_NONE PixbufRotation = 0
275 | PIXBUF_ROTATE_COUNTERCLOCKWISE PixbufRotation = 90
276 | PIXBUF_ROTATE_UPSIDEDOWN PixbufRotation = 180
277 | PIXBUF_ROTATE_CLOCKWISE PixbufRotation = 270
278 | )
279 |
280 | func (p *Pixbuf) RotateSimple(angle PixbufRotation) *Pixbuf {
281 | gpixbuf := C.gdk_pixbuf_rotate_simple(p.GPixbuf, C.GdkPixbufRotation(angle))
282 | return &Pixbuf{
283 | GdkPixbuf: &GdkPixbuf{gpixbuf},
284 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
285 | }
286 | }
287 |
288 | func (p *Pixbuf) Flip(horizontal bool) *Pixbuf {
289 | gpixbuf := C.gdk_pixbuf_flip(p.GPixbuf, gbool(horizontal))
290 | return &Pixbuf{
291 | GdkPixbuf: &GdkPixbuf{gpixbuf},
292 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
293 | }
294 | }
295 |
296 | func (p *Pixbuf) Fill(pixel uint32) {
297 | C.gdk_pixbuf_fill(p.GPixbuf, C.guint32(pixel))
298 | }
299 |
300 | // The GdkPixbuf Structure
301 |
302 | type Colorspace int
303 |
304 | const (
305 | GDK_COLORSPACE_RGB Colorspace = iota
306 | )
307 |
308 | type PixbufAlphaMode int
309 |
310 | const (
311 | GDK_PIXBUF_ALPHA_BILEVEL PixbufAlphaMode = iota
312 | GDK_PIXBUF_ALPHA_FULL
313 | )
314 |
315 | func (p *Pixbuf) GetColorspace() Colorspace {
316 | return Colorspace(C.gdk_pixbuf_get_colorspace(p.GPixbuf))
317 | }
318 |
319 | func (p *Pixbuf) GetNChannels() int {
320 | return int(C.gdk_pixbuf_get_n_channels(p.GPixbuf))
321 | }
322 |
323 | func (p *Pixbuf) GetHasAlpha() bool {
324 | return gobool(C.gdk_pixbuf_get_has_alpha(p.GPixbuf))
325 | }
326 |
327 | func (p *Pixbuf) GetBitsPerSample() int {
328 | return int(C.gdk_pixbuf_get_bits_per_sample(p.GPixbuf))
329 | }
330 |
331 | func (p *Pixbuf) GetPixels() []byte {
332 | ptr := C.gdk_pixbuf_get_pixels(
333 | p.GPixbuf,
334 | )
335 | return (*[1 << 30]byte)(unsafe.Pointer(ptr))[:]
336 | }
337 |
338 | // guchar * gdk_pixbuf_get_pixels_with_length (const GdkPixbuf *pixbuf, guint *length);
339 | //
340 | // Retuns a slice of byte backed by a C array of pixbuf data.
341 | func (p *Pixbuf) GetPixelsWithLength() []byte {
342 | panic_if_version_older(2, 26, 0, "gdk_pixbuf_get_pixels_with_length()")
343 | length := C.guint(0)
344 | ptr := C._gdk_pixbuf_get_pixels_with_length(
345 | p.GPixbuf,
346 | &length,
347 | )
348 | return (*[1 << 30]byte)(unsafe.Pointer(ptr))[:length]
349 | }
350 |
351 | func (p *Pixbuf) GetWidth() int {
352 | return int(C.gdk_pixbuf_get_width(p.GPixbuf))
353 | }
354 |
355 | func (p *Pixbuf) GetHeight() int {
356 | return int(C.gdk_pixbuf_get_height(p.GPixbuf))
357 | }
358 |
359 | func (p *Pixbuf) GetRowstride() int {
360 | return int(C.gdk_pixbuf_get_rowstride(p.GPixbuf))
361 | }
362 |
363 | // gdk_pixbuf_get_byte_length
364 | // gdk_pixbuf_get_option
365 |
366 | // File saving
367 |
368 | func (p *Pixbuf) Save(filename, savetype string, options ...string) *glib.Error {
369 | if len(options)%2 != 0 {
370 | argumentPanic("Save options must be even (key and value)")
371 | }
372 |
373 | pfilename := C.CString(filename)
374 | defer cfree(pfilename)
375 | psavetype := C.CString(savetype)
376 | defer cfree(psavetype)
377 |
378 | klen := len(options) / 2
379 | keys := C.makeCstrv(C.int(klen + 1))
380 | vals := C.makeCstrv(C.int(klen + 1))
381 | for i := 0; i < klen; i++ {
382 | C.setCstr(keys, C.int(i), C.CString(options[2*i]))
383 | C.setCstr(vals, C.int(i), C.CString(options[2*i+1]))
384 | }
385 | C.setCstr(keys, C.int(klen), nil)
386 | C.setCstr(vals, C.int(klen), nil)
387 | defer func() {
388 | for i := 0; i < klen; i++ {
389 | cfree(C.getCstr(keys, C.int(i)))
390 | cfree(C.getCstr(vals, C.int(i)))
391 | }
392 | C.freeCstrv(keys)
393 | C.freeCstrv(vals)
394 | }()
395 |
396 | var err *C.GError
397 | C.gdk_pixbuf_savev(p.GPixbuf, pfilename, psavetype, keys, vals, &err)
398 | if err != nil {
399 | return glib.ErrorFromNative(unsafe.Pointer(err))
400 | }
401 | return nil
402 | }
403 |
404 | //-----------------------------------------------------------------------
405 | // Animation
406 | //-----------------------------------------------------------------------
407 | type Animation struct {
408 | GPixbufAnimation *C.GdkPixbufAnimation
409 | }
410 |
411 | //-----------------------------------------------------------------------
412 | // Format
413 | //-----------------------------------------------------------------------
414 | type Format struct {
415 | GPixbufFormat *C.GdkPixbufFormat
416 | }
417 |
418 | // gdk_pixbuf_get_formats
419 |
420 | func (v *Format) GetName() string {
421 | return gostring(C.gdk_pixbuf_format_get_name(v.GPixbufFormat))
422 | }
423 |
424 | func (v *Format) GetDescription() string {
425 | return gostring(C.gdk_pixbuf_format_get_description(v.GPixbufFormat))
426 | }
427 |
428 | func (v *Format) GetMimeTypes() []string {
429 | gstrv := C.gdk_pixbuf_format_get_mime_types(v.GPixbufFormat)
430 | defer C.g_strfreev(gstrv)
431 | s := make([]string, 0)
432 | for i := 0; C.getGstr(gstrv, C.int(i)) != nil; i++ {
433 | s = append(s, gostring(C.getGstr(gstrv, C.int(i))))
434 | }
435 | return s
436 | }
437 |
438 | func (v *Format) GetExtensions() []string {
439 | gstrv := C.gdk_pixbuf_format_get_extensions(v.GPixbufFormat)
440 | defer C.g_strfreev(gstrv)
441 | s := make([]string, 0)
442 | for i := 0; C.getGstr(gstrv, C.int(i)) != nil; i++ {
443 | s = append(s, gostring(C.getGstr(gstrv, C.int(i))))
444 | }
445 | return s
446 | }
447 |
448 | func (v *Format) IsWritable() bool {
449 | return gobool(C.gdk_pixbuf_format_is_writable(v.GPixbufFormat))
450 | }
451 |
452 | func (v *Format) IsScalable() bool {
453 | return gobool(C.gdk_pixbuf_format_is_scalable(v.GPixbufFormat))
454 | }
455 |
456 | func (v *Format) IsDisabled() bool {
457 | return gobool(C.gdk_pixbuf_format_is_disabled(v.GPixbufFormat))
458 | }
459 |
460 | func (v *Format) SetDisabled(disabled bool) {
461 | C.gdk_pixbuf_format_set_disabled(v.GPixbufFormat, gbool(disabled))
462 | }
463 |
464 | func (v *Format) GetLicense() string {
465 | return gostring(C.gdk_pixbuf_format_get_license(v.GPixbufFormat))
466 | }
467 |
468 | //-----------------------------------------------------------------------
469 | // Loader
470 | //-----------------------------------------------------------------------
471 | type Loader struct {
472 | GPixbufLoader *C.GdkPixbufLoader
473 | }
474 |
475 | func NewLoader() *Loader {
476 | return &Loader{
477 | C.gdk_pixbuf_loader_new()}
478 | }
479 |
480 | func NewLoaderWithType(image_type string) (loader *Loader, err *glib.Error) {
481 | var gerr *C.GError
482 | ptr := C.CString(image_type)
483 | defer cfree(ptr)
484 | loader = &Loader{
485 | C.gdk_pixbuf_loader_new_with_type(ptr, &gerr)}
486 | if gerr != nil {
487 | err = glib.ErrorFromNative(unsafe.Pointer(gerr))
488 | }
489 | return
490 | }
491 |
492 | func NewLoaderWithMimeType(mime_type string) (loader *Loader, err *glib.Error) {
493 | var error *C.GError
494 | ptr := C.CString(mime_type)
495 | defer cfree(ptr)
496 | loader = &Loader{
497 | C.gdk_pixbuf_loader_new_with_mime_type(ptr, &error)}
498 | err = glib.ErrorFromNative(unsafe.Pointer(error))
499 | return
500 | }
501 |
502 | func (v Loader) GetPixbuf() *Pixbuf {
503 | gpixbuf := C.gdk_pixbuf_loader_get_pixbuf(v.GPixbufLoader)
504 | return &Pixbuf{
505 | GdkPixbuf: &GdkPixbuf{gpixbuf},
506 | GObject: glib.ObjectFromNative(unsafe.Pointer(gpixbuf)),
507 | }
508 | }
509 |
510 | func (v Loader) Write(buf []byte) (bool, *glib.Error) {
511 | var err *C.GError
512 | var pbuf *byte
513 | pbuf = &buf[0]
514 | ret := gobool(C.gdk_pixbuf_loader_write(v.GPixbufLoader, C.to_gucharptr(unsafe.Pointer(pbuf)), C.gsize(len(buf)), &err))
515 | if err != nil {
516 | return ret, glib.ErrorFromNative(unsafe.Pointer(err))
517 | }
518 | return ret, nil
519 | }
520 |
521 | func (v Loader) Close() (bool, *glib.Error) {
522 | var err *C.GError
523 | ret := gobool(C.gdk_pixbuf_loader_close(v.GPixbufLoader, &err))
524 | if err != nil {
525 | return ret, glib.ErrorFromNative(unsafe.Pointer(err))
526 | }
527 | return ret, nil
528 | }
529 |
530 | //func (v Loader) GetPixbufAnimation() *Animation {
531 | // return &Animation {
532 | // C.gdk_pixbuf_loader_get_animation(v.GPixbufLoader) };
533 | //}
534 | func (v Loader) SetSize(width int, height int) {
535 | C.gdk_pixbuf_loader_set_size(v.GPixbufLoader, C.int(width), C.int(height))
536 | }
537 |
538 | func (v Loader) GetFormat() *Format {
539 | return &Format{
540 | C.gdk_pixbuf_loader_get_format(v.GPixbufLoader)}
541 | }
542 |
543 | // FINISH
544 |
--------------------------------------------------------------------------------
/gdkpixbuf/gdkpixbuf.go.h:
--------------------------------------------------------------------------------
1 | #ifndef GO_GDK_PIXBUF_H
2 | #define GO_GDK_PIXBUF_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | //static const gchar* to_gcharptr(const char* s) { return (const gchar*)s; }
12 | static guchar* to_gucharptr(void* s) { return (guchar*)s; }
13 |
14 | static inline GdkPixbuf* toGdkPixbuf(void* p) { return GDK_PIXBUF(p); }
15 |
16 | static inline gchar* toGstr(const char* s) { return (gchar*)s; }
17 | static inline char* toCstr(const gchar* s) { return (char*)s; }
18 |
19 | static inline void freeCstr(char* s) { free(s); }
20 |
21 | static inline char** makeCstrv(int count) {
22 | return (char**)malloc(sizeof(char*) * count);
23 | }
24 |
25 | static guchar* _gdk_pixbuf_get_pixels_with_length(const GdkPixbuf *pixbuf, guint *length) {
26 | #if GDK_PIXBUF_MAJOR >= 2 && GDK_PIXBUF_MINOR >= 26
27 | return gdk_pixbuf_get_pixels_with_length(pixbuf, length);
28 | #else
29 | return NULL;
30 | #endif
31 | }
32 |
33 | //
34 | static inline void freeCstrv(char** cstrv) { free(cstrv); }
35 | static inline char* getCstr(char** cstrv, int n) { return cstrv[n]; }
36 | static inline void setCstr(char** cstrv, int n, char* str) { cstrv[n] = str; }
37 | static inline gchar* getGstr(gchar** gstrv, int n) { return gstrv[n]; }
38 |
39 | static int _check_version(int major, int minor, int micro) {
40 | if (GDK_PIXBUF_MAJOR > major) return 1;
41 | if (GDK_PIXBUF_MAJOR < major) return 0;
42 | if (GDK_PIXBUF_MINOR > minor) return 1;
43 | if (GDK_PIXBUF_MINOR < minor) return 0;
44 | if (GDK_PIXBUF_MICRO > micro) return 1;
45 | return 0;
46 | }
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/gio/gio.go:
--------------------------------------------------------------------------------
1 | package gio
2 |
3 | // #include "gio.go.h"
4 | // #cgo pkg-config: gio-2.0
5 | import "C"
6 | import (
7 | "unsafe"
8 |
9 | "github.com/mattn/go-gtk/glib"
10 | )
11 |
12 | func cfree(s *C.char) { C.freeCstr(s) }
13 | func gstring(s *C.char) *C.gchar { return C.toGstr(s) }
14 | func cstring(s *C.gchar) *C.char { return C.toCstr(s) }
15 | func gostring(s *C.gchar) string { return C.GoString(cstring(s)) }
16 |
17 | //-----------------------------------------------------------------------
18 | // GFile
19 | //-----------------------------------------------------------------------
20 | type GFile struct {
21 | GFile *C.GFile
22 | }
23 |
24 | // NewGFileForPath is g_file_new_for_path
25 | func NewGFileForPath(filename string) *GFile {
26 | ptrFilename := C.CString(filename)
27 | defer cfree(ptrFilename)
28 |
29 | return &GFile{C.g_file_new_for_path(ptrFilename)}
30 | }
31 |
32 | // NewGFileForURI is g_file_new_for_uri
33 | func NewGFileForURI(uriFilename string) *GFile {
34 | ptrFilename := C.CString(uriFilename)
35 | defer cfree(ptrFilename)
36 |
37 | return &GFile{C.g_file_new_for_uri(ptrFilename)}
38 | }
39 |
40 | type GFileQueryInfoFlags C.GFileQueryInfoFlags
41 |
42 | var (
43 | GFileQueryInfoNone GFileQueryInfoFlags = C.G_FILE_QUERY_INFO_NONE
44 | GFileQueryInfoNoFollowSymlinks GFileQueryInfoFlags = C.G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS
45 | )
46 |
47 | // QueryInfo is g_file_query_info
48 | func (f *GFile) QueryInfo(attributes string, flags GFileQueryInfoFlags) (*GFileInfo, error) {
49 | ptr := C.CString(attributes)
50 | defer cfree(ptr)
51 |
52 | var gerror *C.GError
53 |
54 | gfileinfo := C.g_file_query_info(
55 | f.GFile,
56 | ptr,
57 | C.GFileQueryInfoFlags(flags),
58 | nil, // nil is GCancellable, not yet implemented
59 | &gerror,
60 | )
61 | if gerror != nil {
62 | return nil, glib.ErrorFromNative(unsafe.Pointer(gerror))
63 | }
64 |
65 | return &GFileInfo{gfileinfo}, nil
66 | }
67 |
68 | // GetPath is `g_file_get_path`, return real, absolute, canonical path. It might contain symlinks.
69 | func (f *GFile) GetPath() string {
70 | return gostring(gstring(C.g_file_get_path(f.GFile)))
71 | }
72 |
73 | //-----------------------------------------------------------------------
74 | // GFileInfo
75 | //-----------------------------------------------------------------------
76 | type GFileInfo struct {
77 | GFileInfo *C.GFileInfo
78 | }
79 |
80 | // GetSymbolicIcon is g_file_info_get_symbolic_icon
81 | func (fi *GFileInfo) GetSymbolicIcon() *GIcon {
82 | return &GIcon{C.g_file_info_get_symbolic_icon(fi.GFileInfo)}
83 | }
84 |
85 | // GetIcon is g_file_info_get_icon
86 | func (fi *GFileInfo) GetIcon() *GIcon {
87 | return &GIcon{C.g_file_info_get_icon(fi.GFileInfo)}
88 | }
89 |
90 | //-----------------------------------------------------------------------
91 | // GIcon
92 | //-----------------------------------------------------------------------
93 | type GIcon struct {
94 | GIcon *C.GIcon
95 | }
96 |
97 | //ToString is g_icon_to_string
98 | func (icon *GIcon) ToString() string {
99 | return gostring(C.g_icon_to_string(icon.GIcon))
100 | }
101 |
102 | type GInputStream struct {
103 | GInputStream *C.GInputStream
104 | }
105 |
106 | func NewMemoryInputStreamFromBytes(buffer []byte) *GInputStream {
107 | pbyt := &buffer[0]
108 | gbytes := C.g_bytes_new_take(C.gpointer(unsafe.Pointer(pbyt)), C.gsize(len(buffer)))
109 |
110 | stream := C.g_memory_input_stream_new_from_bytes(gbytes)
111 | return &GInputStream{stream}
112 | }
113 |
114 | func NewCancellable() *C.GCancellable {
115 | return C.g_cancellable_new()
116 | }
117 |
--------------------------------------------------------------------------------
/gio/gio.go.h:
--------------------------------------------------------------------------------
1 | #ifndef GO_GIO_H
2 | #define GO_GIO_H
3 |
4 | #include
5 |
6 | #endif
7 |
8 | #include
9 |
10 | static inline void freeCstr(char* s) { free(s); }
11 | static inline gchar* toGstr(const char* s) { return (gchar*)s; }
12 | static inline char* toCstr(const gchar* s) { return (char*)s; }
13 |
--------------------------------------------------------------------------------
/glib/glib.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package glib
4 |
5 | // #include "glib.go.h"
6 | // #cgo pkg-config: glib-2.0 gobject-2.0
7 | import "C"
8 | import (
9 | "reflect"
10 | "sync"
11 | "unsafe"
12 | )
13 |
14 | type ContextStorage struct {
15 | lastId int
16 | m sync.Mutex
17 | values map[int]interface{}
18 | }
19 |
20 | func NewContextStorage() *ContextStorage {
21 | return &ContextStorage{values: make(map[int]interface{})}
22 | }
23 |
24 | func (c *ContextStorage) Add(value interface{}) int {
25 | c.m.Lock()
26 | newId := c.lastId
27 | c.values[newId] = value
28 | c.lastId++
29 | c.m.Unlock()
30 | return newId
31 | }
32 |
33 | func (c *ContextStorage) Get(id int) (value interface{}, found bool) {
34 | c.m.Lock()
35 | value, found = c.values[id]
36 | c.m.Unlock()
37 | return
38 | }
39 |
40 | func (c *ContextStorage) Remove(id int) {
41 | c.m.Lock()
42 | delete(c.values, id)
43 | c.m.Unlock()
44 | }
45 |
46 | func (c *ContextStorage) Len() int {
47 | c.m.Lock()
48 | result := len(c.values)
49 | c.m.Unlock()
50 | return result
51 | }
52 |
53 | var (
54 | sourcefunc_contexts = NewContextStorage()
55 | callback_contexts = NewContextStorage()
56 | )
57 |
58 | func gbool(b bool) C.gboolean {
59 | if b {
60 | return C.gboolean(1)
61 | }
62 | return C.gboolean(0)
63 | }
64 |
65 | func gobool(b C.gboolean) bool {
66 | if b != 0 {
67 | return true
68 | }
69 | return false
70 | }
71 |
72 | // converts a C string array to a Go string slice
73 | func toSlice(ar **C.gchar) []string {
74 | result := make([]string, 0)
75 | for i := 0; ; i++ {
76 | str := C.GoString(C.to_charptr(*ar))
77 | if str == "" {
78 | break
79 | }
80 | result = append(result, str)
81 | *ar = C.next_string(*ar)
82 | }
83 | return result
84 | }
85 |
86 | func GPtrToString(p interface{}) string {
87 | pp := (C.gpointer)(p.(unsafe.Pointer))
88 | return C.GoString(C.to_charptr_from_gpointer(pp))
89 | }
90 |
91 | //-----------------------------------------------------------------------
92 | // Application
93 | //-----------------------------------------------------------------------
94 | func GetApplicationName() string {
95 | return C.GoString(C.to_charptr(C.g_get_application_name()))
96 | }
97 |
98 | func SetApplicationName(name string) {
99 | str := C.CString(name)
100 | defer C.free_string(str)
101 | C.g_set_application_name(C.to_gcharptr(str))
102 | }
103 |
104 | func GetPrgName() string {
105 | return C.GoString(C.to_charptr(C.g_get_prgname()))
106 | }
107 |
108 | func SetPrgname(name string) {
109 | str := C.CString(name)
110 | defer C.free_string(str)
111 | C.g_set_prgname(C.to_gcharptr(str))
112 | }
113 |
114 | //-----------------------------------------------------------------------
115 | // User Information
116 | //-----------------------------------------------------------------------
117 | func GetUserName() string {
118 | return C.GoString(C.to_charptr(C.g_get_user_name()))
119 | }
120 |
121 | func GetRealName() string {
122 | return C.GoString(C.to_charptr(C.g_get_real_name()))
123 | }
124 |
125 | func GetUserCacheDir() string {
126 | return C.GoString(C.to_charptr(C.g_get_user_cache_dir()))
127 | }
128 |
129 | func GetUserDataDir() string {
130 | return C.GoString(C.to_charptr(C.g_get_user_data_dir()))
131 | }
132 |
133 | func GetUserConfigDir() string {
134 | return C.GoString(C.to_charptr(C.g_get_user_config_dir()))
135 | }
136 |
137 | func GetUserRuntimeDir() string {
138 | return C.GoString(C.to_charptr(C.g_get_user_runtime_dir()))
139 | }
140 |
141 | type ConnectFlags C.GConnectFlags
142 |
143 | const (
144 | ConnectAfter ConnectFlags = C.G_CONNECT_AFTER
145 | ConnectSwapped ConnectFlags = C.G_CONNECT_SWAPPED
146 | )
147 |
148 | type UserDirectory C.GUserDirectory
149 |
150 | const (
151 | UserDirectoryDesktop UserDirectory = C.G_USER_DIRECTORY_DESKTOP
152 | UserDirectoryDocuments UserDirectory = C.G_USER_DIRECTORY_DOCUMENTS
153 | UserDirectoryDownload UserDirectory = C.G_USER_DIRECTORY_DOWNLOAD
154 | UserDirectoryMusic UserDirectory = C.G_USER_DIRECTORY_MUSIC
155 | UserDirectoryPictures UserDirectory = C.G_USER_DIRECTORY_PICTURES
156 | UserDirectoryPublicShare UserDirectory = C.G_USER_DIRECTORY_PUBLIC_SHARE
157 | UserDirectoryTemplates UserDirectory = C.G_USER_DIRECTORY_TEMPLATES
158 | UserDirectoryVideos UserDirectory = C.G_USER_DIRECTORY_VIDEOS
159 | )
160 |
161 | func GetUserSpecialDir(directory UserDirectory) string {
162 | result := C.g_get_user_special_dir(C.GUserDirectory(directory))
163 | return C.GoString(C.to_charptr(result))
164 | }
165 |
166 | func ReloadUserSpecialDirsCache() {
167 | C.g_reload_user_special_dirs_cache()
168 | }
169 |
170 | //-----------------------------------------------------------------------
171 | // System Information
172 | //-----------------------------------------------------------------------
173 | func GetSystemDataDirs() []string {
174 | return toSlice(C.g_get_system_data_dirs())
175 | }
176 |
177 | func GetSystemConfigDirs() []string {
178 | return toSlice(C.g_get_system_config_dirs())
179 | }
180 |
181 | func GetHostName() string {
182 | return C.GoString(C.to_charptr(C.g_get_host_name()))
183 | }
184 |
185 | func GetHomeDir() string {
186 | return C.GoString(C.to_charptr(C.g_get_home_dir()))
187 | }
188 |
189 | func GetTmpDir() string {
190 | return C.GoString(C.to_charptr(C.g_get_tmp_dir()))
191 | }
192 |
193 | func GetCurrentDir() string {
194 | return C.GoString(C.to_charptr(C.g_get_current_dir()))
195 | }
196 |
197 | //-----------------------------------------------------------------------
198 | // String Convert
199 | //-----------------------------------------------------------------------
200 | func Utf8Validate(str []byte, len int, bar **byte) bool {
201 | return gobool(C._g_utf8_validate(unsafe.Pointer(&str[0]),
202 | C.int(len), unsafe.Pointer(bar)))
203 | }
204 |
205 | func FilenameFromUri(uri string) (filename string, hostname string, err error) {
206 | str := C.CString(uri)
207 | defer C.free_string(str)
208 | var gerror *C.GError
209 | var ptr *C.gchar
210 | filename = C.GoString(C.to_charptr(C.g_filename_from_uri(C.to_gcharptr(str), &ptr, &gerror)))
211 | if unsafe.Pointer(gerror) != nil {
212 | err = ErrorFromNative(unsafe.Pointer(gerror))
213 | } else {
214 | err = nil
215 | }
216 | hostname = ""
217 | if ptr != nil {
218 | hostname = C.GoString(C.to_charptr(ptr))
219 | }
220 | return
221 | }
222 |
223 | func FilenameToUri(filename string, hostname string) (uri string, err error) {
224 | pfilename := C.CString(filename)
225 | defer C.free_string(pfilename)
226 | phostname := C.CString(hostname)
227 | defer C.free_string(phostname)
228 | var gerror *C.GError
229 | uri = C.GoString(C.to_charptr(C.g_filename_to_uri(C.to_gcharptr(pfilename), C.to_gcharptr(phostname), &gerror)))
230 | if unsafe.Pointer(gerror) != nil {
231 | err = ErrorFromNative(unsafe.Pointer(gerror))
232 | } else {
233 | err = nil
234 | }
235 | return
236 | }
237 |
238 | func LocaleToUtf8(opsysstring []byte) (ret string, bytes_read int, bytes_written int, err *Error) {
239 | var gerror *C.GError
240 | var cbytes_read, cbytes_written C.int
241 | str := C._g_locale_to_utf8(unsafe.Pointer(&opsysstring[0]), C.int(len(opsysstring)), &cbytes_read, &cbytes_written, &gerror)
242 | if unsafe.Pointer(str) != nil {
243 | defer C.free_string(C.to_charptr(str))
244 | ret = C.GoString(C.to_charptr(str))
245 | } else {
246 | ret = ""
247 | }
248 | bytes_read = int(cbytes_read)
249 | bytes_written = int(cbytes_written)
250 | if unsafe.Pointer(gerror) != nil {
251 | err = ErrorFromNative(unsafe.Pointer(gerror))
252 | } else {
253 | err = nil
254 | }
255 | return
256 | }
257 |
258 | func LocaleFromUtf8(utf8string string) (ret []byte, bytes_read int, bytes_written int, err *Error) {
259 | var gerror *C.GError
260 | var cbytes_read, cbytes_written C.int
261 | src := C.CString(utf8string)
262 | defer C.free_string(src)
263 | str := C._g_locale_from_utf8(src, C.int(C.strlen(src)), &cbytes_read, &cbytes_written, &gerror)
264 | if unsafe.Pointer(str) != nil {
265 | defer C.free_string(C.to_charptr(str))
266 | ret = ([]byte)(C.GoString(C.to_charptr(str)))
267 | } else {
268 | ret = ([]byte)("")
269 | }
270 | bytes_read = int(cbytes_read)
271 | bytes_written = int(cbytes_written)
272 | if unsafe.Pointer(gerror) != nil {
273 | err = ErrorFromNative(unsafe.Pointer(gerror))
274 | } else {
275 | err = nil
276 | }
277 | return
278 | }
279 |
280 | //-----------------------------------------------------------------------
281 | // List
282 | //-----------------------------------------------------------------------
283 | type List struct {
284 | GList *C.GList
285 | }
286 |
287 | func ListFromNative(l unsafe.Pointer) *List {
288 | return &List{
289 | C.to_list(l)}
290 | }
291 |
292 | func (v List) Data() interface{} {
293 | return v.GList.data
294 | }
295 |
296 | func (v List) Append(data unsafe.Pointer) *List {
297 | return &List{C.g_list_append(v.GList, C.gpointer(data))}
298 | }
299 |
300 | func (v List) Prepend(data unsafe.Pointer) *List {
301 | return &List{C.g_list_prepend(v.GList, C.gpointer(data))}
302 | }
303 |
304 | func (v List) Insert(data unsafe.Pointer, pos int) *List {
305 | return &List{C.g_list_insert(v.GList, C.gpointer(data), C.gint(pos))}
306 | }
307 |
308 | func (v List) InsertBefore(sib List, data unsafe.Pointer) *List {
309 | return &List{C.g_list_insert_before(v.GList, sib.GList, C.gpointer(data))}
310 | }
311 |
312 | //GList* g_list_insert_sorted (GList *list,
313 | // gpointer data,
314 | // GCompareFunc func);
315 | func (v List) Remove(data unsafe.Pointer) *List {
316 | return &List{C.g_list_remove(v.GList, C.gconstpointer(data))}
317 | }
318 |
319 | func (v List) RemoveLink(link List) *List {
320 | return &List{C.g_list_remove_link(v.GList, link.GList)}
321 | }
322 |
323 | func (v List) DeleteLink(link List) *List {
324 | return &List{C.g_list_delete_link(v.GList, link.GList)}
325 | }
326 |
327 | func (v List) RemoveAll(data unsafe.Pointer) *List {
328 | return &List{C.g_list_remove_all(v.GList, C.gconstpointer(data))}
329 | }
330 |
331 | func (v List) Free() {
332 | C.g_list_free(v.GList)
333 | }
334 |
335 | func GListAlloc() *List {
336 | return &List{C.g_list_alloc()}
337 | }
338 |
339 | func (v List) Free1() {
340 | C.g_list_free_1(v.GList)
341 | }
342 |
343 | func (v List) Length() uint {
344 | return uint(C.g_list_length(v.GList))
345 | }
346 |
347 | func (v List) Copy() *List {
348 | return &List{C.g_list_copy(v.GList)}
349 | }
350 |
351 | func (v List) Reverse() *List {
352 | return &List{C.g_list_reverse(v.GList)}
353 | }
354 |
355 | //GList* g_list_sort (GList *list,
356 | // GCompareFunc compare_func);
357 | //gint (*GCompareFunc) (gconstpointer a,
358 | // gconstpointer b);
359 | //GList* g_list_insert_sorted_with_data (GList *list,
360 | // gpointer data,
361 | // GCompareDataFunc func,
362 | // gpointer user_data);
363 | //GList* g_list_sort_with_data (GList *list,
364 | // GCompareDataFunc compare_func,
365 | // gpointer user_data);
366 | //gint (*GCompareDataFunc) (gconstpointer a,
367 | // gconstpointer b,
368 | // gpointer user_data);
369 | func (v List) Concat(link List) *List {
370 | return &List{C.g_list_concat(v.GList, link.GList)}
371 | }
372 |
373 | func (v List) ForEach(callback func(unsafe.Pointer, interface{}), user_datas ...interface{}) {
374 | var user_data interface{}
375 | if len(user_datas) > 0 {
376 | user_data = user_datas[0]
377 | }
378 | l := v.First()
379 | for n := uint(0); n < l.Length(); n++ {
380 | callback(l.NthData(n), user_data)
381 | }
382 | }
383 |
384 | func (v List) First() *List {
385 | return &List{C.g_list_first(v.GList)}
386 | }
387 |
388 | func (v List) Last() *List {
389 | return &List{C.g_list_last(v.GList)}
390 | }
391 |
392 | func (v List) Nth(n uint) *List {
393 | return &List{C.g_list_nth(v.GList, C.guint(n))}
394 | }
395 |
396 | func (v List) NthData(n uint) unsafe.Pointer {
397 | return unsafe.Pointer(C.g_list_nth_data(v.GList, C.guint(n)))
398 | }
399 |
400 | func (v List) NthPrev(n uint) *List {
401 | return &List{C.g_list_nth_prev(v.GList, C.guint(n))}
402 | }
403 |
404 | func (v List) Find(data unsafe.Pointer) *List {
405 | return &List{C.g_list_find(v.GList, C.gconstpointer(data))}
406 | }
407 |
408 | //GList* g_list_find_custom (GList *list,
409 | // gconstpointer data,
410 | // GCompareFunc func);
411 | func (v List) Position(link List) int {
412 | return int(C.g_list_position(v.GList, link.GList))
413 | }
414 |
415 | func (v List) Index(data unsafe.Pointer) int {
416 | return int(C.g_list_index(v.GList, C.gconstpointer(data)))
417 | }
418 |
419 | //-----------------------------------------------------------------------
420 | // g_slist
421 | //-----------------------------------------------------------------------
422 | type SList struct {
423 | GSList *C.GSList
424 | }
425 |
426 | func SListFromNative(sl unsafe.Pointer) *SList {
427 | return &SList{
428 | C.to_slist(sl)}
429 | }
430 |
431 | func (v SList) ToSList() *C.GSList {
432 | return v.GSList
433 | }
434 |
435 | func (v SList) Data() unsafe.Pointer {
436 | return unsafe.Pointer(v.GSList.data)
437 | }
438 |
439 | func GSListAlloc() *SList {
440 | return &SList{C.g_slist_alloc()}
441 | }
442 |
443 | func (v SList) Free() {
444 | C.g_slist_free(v.GSList)
445 | }
446 |
447 | func (v SList) Free1() {
448 | C.g_slist_free1(v.GSList)
449 | }
450 |
451 | func (v SList) Append(data unsafe.Pointer) *SList {
452 | return &SList{C.g_slist_append(v.GSList, C.gpointer(data))}
453 | }
454 |
455 | func (v SList) Prepend(data unsafe.Pointer) *SList {
456 | return &SList{C.g_slist_prepend(v.GSList, C.gpointer(data))}
457 | }
458 |
459 | // GSList* g_slist_insert (GSList *list, gpointer data, gint position) G_GNUC_WARN_UNUSED_RESULT;
460 | // GSList* g_slist_insert_sorted (GSList *list, gpointer data, GCompareFunc func) G_GNUC_WARN_UNUSED_RESULT;
461 | // GSList* g_slist_insert_sorted_with_data (GSList *list, gpointer data, GCompareDataFunc func, gpointer user_data) G_GNUC_WARN_UNUSED_RESULT;
462 | func (v SList) InsertBefore(sibling SList, data unsafe.Pointer) *SList {
463 | return &SList{C.g_slist_insert_before(v.GSList, sibling.GSList, C.gpointer(data))}
464 | }
465 |
466 | func (v SList) Concat(llink SList) *SList {
467 | return &SList{C.g_slist_concat(v.GSList, llink.GSList)}
468 | }
469 |
470 | func (v SList) Remove(data unsafe.Pointer) *SList {
471 | return &SList{C.g_slist_remove(v.GSList, C.gconstpointer(data))}
472 | }
473 |
474 | func (v SList) RemoveAll(data unsafe.Pointer) *SList {
475 | return &SList{C.g_slist_remove_all(v.GSList, C.gconstpointer(data))}
476 | }
477 |
478 | func (v SList) RemoveLink(llink SList) *SList {
479 | return &SList{C.g_slist_delete_link(v.GSList, llink.GSList)}
480 | }
481 |
482 | func (v SList) DeleteLink(llink SList) *SList {
483 | return &SList{C.g_slist_delete_link(v.GSList, llink.GSList)}
484 | }
485 |
486 | func (v SList) Reverse() *SList {
487 | return &SList{C.g_slist_reverse(v.GSList)}
488 | }
489 |
490 | func (v SList) Copy() *SList {
491 | return &SList{C.g_slist_copy(v.GSList)}
492 | }
493 |
494 | func (v SList) Nth(n uint) *SList {
495 | return &SList{C.g_slist_nth(v.GSList, C.guint(n))}
496 | }
497 |
498 | func (v SList) Find(data unsafe.Pointer) *SList {
499 | return &SList{C.g_slist_find(v.GSList, C.gconstpointer(data))}
500 | }
501 |
502 | // GSList* g_slist_find_custom (GSList *list, gconstpointer data, GCompareFunc func);
503 | func (v SList) Position(llink SList) int {
504 | return int(C.g_slist_position(v.GSList, llink.GSList))
505 | }
506 |
507 | func (v SList) Index(data unsafe.Pointer) int {
508 | return int(C.g_slist_index(v.GSList, C.gconstpointer(data)))
509 | }
510 |
511 | func (v SList) Last() *SList {
512 | return &SList{C.g_slist_last(v.GSList)}
513 | }
514 |
515 | func (v SList) Length() uint {
516 | return uint(C.g_slist_length(v.GSList))
517 | }
518 |
519 | func (v SList) ForEach(callback func(unsafe.Pointer, interface{}), user_datas ...interface{}) {
520 | var user_data interface{}
521 | if len(user_datas) > 0 {
522 | user_data = user_datas[0]
523 | }
524 | for n := uint(0); n < v.Length(); n++ {
525 | callback(v.Nth(n).Data(), user_data)
526 | }
527 | }
528 |
529 | // GSList* g_slist_sort (GSList *list, GCompareFunc compare_func) G_GNUC_WARN_UNUSED_RESULT;
530 | // GSList* g_slist_sort_with_data (GSList *list, GCompareDataFunc compare_func, gpointer user_data) G_GNUC_WARN_UNUSED_RESULT;
531 | func (v SList) NthData(n uint) unsafe.Pointer {
532 | return unsafe.Pointer(C.g_slist_nth_data(v.GSList, C.guint(n)))
533 | }
534 |
535 | //-----------------------------------------------------------------------
536 | // g_error
537 | //-----------------------------------------------------------------------
538 | type Error struct {
539 | GError *C.GError
540 | }
541 |
542 | func (v *Error) Error() string {
543 | return v.Message()
544 | }
545 |
546 | func (v *Error) Message() string {
547 | if unsafe.Pointer(v.GError) == nil || unsafe.Pointer(v.GError.message) == nil {
548 | return ""
549 | }
550 | return C.GoString(C.to_charptr(v.GError.message))
551 | }
552 |
553 | func ErrorFromNative(err unsafe.Pointer) *Error {
554 | return &Error{
555 | C.to_error(err)}
556 | }
557 |
558 | //-----------------------------------------------------------------------
559 | // GObject
560 | //-----------------------------------------------------------------------
561 | type ObjectLike interface {
562 | Ref()
563 | Unref()
564 | Connect(s string, f interface{}, data ...interface{})
565 | }
566 | type GObject struct {
567 | Object unsafe.Pointer
568 | }
569 |
570 | func ObjectFromNative(object unsafe.Pointer) *GObject {
571 | // return &GObject {
572 | // C.to_GObject(object) }
573 | return &GObject{
574 | object}
575 | }
576 |
577 | func (v *GObject) Ref() {
578 | C.g_object_ref(C.gpointer(v.Object))
579 | }
580 |
581 | func (v *GObject) Unref() {
582 | C.g_object_unref(C.gpointer(v.Object))
583 | }
584 |
585 | func (v *GObject) SetData(s string, p unsafe.Pointer) {
586 | ptr := C.CString(s)
587 | defer C.free_string(ptr)
588 | C.g_object_set_data((*C.GObject)(v.Object), C.to_gcharptr(ptr), (C.gpointer)(p))
589 | }
590 |
591 | func (v *GObject) GetData(s string) unsafe.Pointer {
592 | ptr := C.CString(s)
593 | defer C.free_string(ptr)
594 | p := C.g_object_get_data((*C.GObject)(v.Object), C.to_gcharptr(ptr))
595 | return unsafe.Pointer(p)
596 | }
597 |
598 | func (v *GObject) Set(name string, value interface{}) {
599 | ptr := C.CString(name)
600 | defer C.free_string(ptr)
601 |
602 | if _, ok := value.(WrappedObject); ok {
603 | value = value.(WrappedObject).GetInternalValue()
604 | }
605 | if _, ok := value.(GObject); ok {
606 | value = value.(GObject).Object
607 | }
608 | if _, ok := value.(GValue); ok {
609 | value = value.(GValue).Value
610 | }
611 |
612 | switch value.(type) {
613 | case bool:
614 | bval := gbool(value.(bool))
615 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(&bval))
616 | case byte:
617 | bval := C.gchar(value.(byte))
618 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(&bval))
619 | //C._g_object_set(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(reflect.ValueOf(C.gchar(value.(byte))).UnsafeAddr()))
620 | case int:
621 | ival := C.int(value.(int))
622 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(&ival))
623 | case uint:
624 | uval := C.guint(value.(uint))
625 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(&uval))
626 | //C._g_object_set(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(reflect.ValueOf(C.guint(value.(uint))).UnsafeAddr()))
627 | case float32:
628 | f32val := C.gfloat(value.(float32))
629 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(&f32val))
630 | //C._g_object_set(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(reflect.ValueOf(C.gfloat(value.(float64))).UnsafeAddr()))
631 | case float64:
632 | f64val := C.gfloat(value.(float64))
633 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(&f64val))
634 | //C._g_object_set(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(reflect.ValueOf(C.gfloat(value.(float64))).UnsafeAddr()))
635 | case string:
636 | pval := C.CString(value.(string))
637 | defer C.free_string(pval)
638 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(&pval))
639 | default:
640 | if pv, ok := value.(*[0]uint8); ok {
641 | C._g_object_set_ptr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(pv))
642 | } else {
643 | av := reflect.ValueOf(value)
644 | if av.Kind() == reflect.Ptr {
645 | C._g_object_set_ptr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(av.Pointer()))
646 | } else if av.CanAddr() {
647 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(av.UnsafeAddr()))
648 | } else {
649 | C._g_object_set_addr(C.gpointer(v.Object), C.to_gcharptr(ptr), unsafe.Pointer(&value))
650 | }
651 | }
652 | }
653 | }
654 |
655 | func (v *GObject) SetProperty(name string, val *GValue) {
656 | str := C.CString(name)
657 | defer C.free_string(str)
658 | C.g_object_set_property(C.to_GObject(v.Object), C.to_gcharptr(str), &val.Value)
659 | }
660 |
661 | //-----------------------------------------------------------------------
662 | // GValue
663 | //-----------------------------------------------------------------------
664 | func GValueFromNative(value interface{}) *C.GValue {
665 | var gv *C.GValue
666 |
667 | if _, ok := value.(WrappedObject); ok {
668 | value = value.(WrappedObject).GetInternalValue()
669 | }
670 | if _, ok := value.(GObject); ok {
671 | value = value.(GObject).Object
672 | }
673 | if _, ok := value.(GValue); ok {
674 | value = value.(GValue).Value
675 | }
676 |
677 | switch value.(type) {
678 | case bool:
679 | gv = C.init_gvalue_bool(gbool(value.(bool)))
680 | break
681 | case byte:
682 | gv = C.init_gvalue_byte(C.guchar(value.(byte)))
683 | break
684 | case int:
685 | gv = C.init_gvalue_int(C.gint(value.(int)))
686 | break
687 | case uint:
688 | gv = C.init_gvalue_uint(C.guint(value.(uint)))
689 | break
690 | case int64:
691 | gv = C.init_gvalue_int64(C.gint64(value.(int64)))
692 | break
693 | case float32:
694 | gv = C.init_gvalue_double(C.gdouble(value.(float32)))
695 | break
696 | case float64:
697 | gv = C.init_gvalue_double(C.gdouble(value.(float64)))
698 | break
699 | case string:
700 | {
701 | pval := C.CString(value.(string))
702 | defer C.free_string(pval)
703 | gv = C.init_gvalue_string(C.to_gcharptr(pval))
704 | }
705 | break
706 | default:
707 | //gv = C.init_gvalue_pointer(C.gpointer(unsafe.Pointer(&value)));
708 | break
709 | }
710 | return gv
711 | }
712 |
713 | func ValueFromNative(val interface{}) *GValue {
714 | return &GValue{*GValueFromNative(val)}
715 | }
716 |
717 | type GValue struct {
718 | Value C.GValue
719 | }
720 |
721 | const (
722 | G_TYPE_CHAR = 3 << 2
723 | G_TYPE_UCHAR = 4 << 2
724 | G_TYPE_BOOL = 5 << 2
725 | G_TYPE_INT = 6 << 2
726 | G_TYPE_UINT = 7 << 2
727 | G_TYPE_LONG = 8 << 2
728 | G_TYPE_ULONG = 9 << 2
729 | G_TYPE_INT64 = 10 << 2
730 | G_TYPE_UINT64 = 11 << 2
731 | G_TYPE_ENUM = 12 << 2
732 | G_TYPE_FLAGS = 13 << 2
733 | G_TYPE_FLOAT = 14 << 2
734 | G_TYPE_DOUBLE = 15 << 2
735 | G_TYPE_STRING = 16 << 2
736 | G_TYPE_POINTER = 17 << 2
737 | G_TYPE_BOXED = 18 << 2
738 | )
739 |
740 | func (v *GValue) Init(t int) {
741 | if t == G_TYPE_INT {
742 | C.g_value_init_int(&v.Value)
743 | } else if t == G_TYPE_STRING {
744 | C.g_value_init_string(&v.Value)
745 | }
746 | }
747 |
748 | func (v *GValue) GetString() string {
749 | return C.GoString(C.to_charptr(C.g_value_get_string(&v.Value)))
750 | }
751 |
752 | func (v *GValue) GetInt() int {
753 | return int(C.g_value_get_int(&v.Value))
754 | }
755 |
756 | func (v *GValue) GetBool() bool {
757 | return gobool(C.g_value_get_boolean(&v.Value))
758 | }
759 |
760 | //-----------------------------------------------------------------------
761 | // WrappedObject
762 | //-----------------------------------------------------------------------
763 | type WrappedObject interface {
764 | GetInternalValue() unsafe.Pointer
765 | }
766 |
767 | //-----------------------------------------------------------------------
768 | // Events
769 | //-----------------------------------------------------------------------
770 | // the go-gtk Callback is simpler than the one in C, because we have
771 | // full closures, so there is never a need to pass additional data via
772 | // a void * pointer. Where you might have wanted to do that, you can
773 | // instead just use func () { ... using data } to pass the data in.
774 | type CallbackContext struct {
775 | f reflect.Value
776 | cbi unsafe.Pointer
777 | target reflect.Value
778 | data reflect.Value
779 | }
780 |
781 | func (c *CallbackContext) Target() interface{} {
782 | return c.target.Interface()
783 | }
784 |
785 | func (c *CallbackContext) Data() interface{} {
786 | if !c.data.IsValid() {
787 | return nil
788 | }
789 | return c.data.Interface()
790 | }
791 |
792 | func (c *CallbackContext) Args(n int) CallbackArg {
793 | return CallbackArg(C.callback_info_get_arg((*C.callback_info)(c.cbi), C.int(n)))
794 | }
795 |
796 | type CallbackArg uintptr
797 |
798 | func (c CallbackArg) ToString() string {
799 | return C.GoString(C.to_charptr_voidp(unsafe.Pointer(uintptr(c))))
800 | }
801 |
802 | //export _go_glib_callback
803 | func _go_glib_callback(cbi *C.callback_info) {
804 | value, found := callback_contexts.Get(int(cbi.func_no))
805 | if !found {
806 | return
807 | }
808 | context := value.(*CallbackContext)
809 | t := context.f.Type()
810 | fargs := make([]reflect.Value, t.NumIn())
811 | if len(fargs) > 0 {
812 | fargs[0] = reflect.ValueOf(context)
813 | }
814 | ret := context.f.Call(fargs)
815 | if len(ret) > 0 {
816 | value := ret[0].Interface()
817 | switch value.(type) {
818 | case bool:
819 | bval := gbool(value.(bool))
820 | cbi.ret = unsafe.Pointer(&bval)
821 | case byte:
822 | bval := C.gchar(value.(byte))
823 | cbi.ret = unsafe.Pointer(&bval)
824 | case int:
825 | ival := C.int(value.(int))
826 | cbi.ret = unsafe.Pointer(&ival)
827 | case uint:
828 | uval := C.guint(value.(uint))
829 | cbi.ret = unsafe.Pointer(&uval)
830 | case float32:
831 | f32val := C.gfloat(value.(float32))
832 | cbi.ret = unsafe.Pointer(&f32val)
833 | case float64:
834 | f64val := C.gfloat(value.(float64))
835 | cbi.ret = unsafe.Pointer(&f64val)
836 | case string:
837 | cbi.ret = unsafe.Pointer(C.CString(value.(string)))
838 | default:
839 | if pv, ok := value.(*[0]uint8); ok {
840 | cbi.ret = unsafe.Pointer(pv)
841 | } else {
842 | av := reflect.ValueOf(value)
843 | if av.Kind() == reflect.Ptr {
844 | cbi.ret = unsafe.Pointer(av.Pointer())
845 | } else if av.CanAddr() {
846 | cbi.ret = unsafe.Pointer(av.UnsafeAddr())
847 | } else {
848 | cbi.ret = unsafe.Pointer(&value)
849 | }
850 | }
851 | }
852 | }
853 | }
854 |
855 | // Return the handler call_id to use with HandlerBlock, HandlerUnblock and
856 | // HandlerDisconnect.
857 | //
858 | func (v *GObject) Connect(s string, f interface{}, datas ...interface{}) int {
859 | var data interface{}
860 | if len(datas) > 0 {
861 | data = datas[0]
862 | }
863 | return v.SignalConnect(s, f, data, ConnectSwapped)
864 | }
865 |
866 | func (v *GObject) SignalConnect(s string, f interface{}, data interface{}, flags ConnectFlags) int {
867 | ctx := &CallbackContext{reflect.ValueOf(f), nil, reflect.ValueOf(v), reflect.ValueOf(data)}
868 | ptr := C.CString(s)
869 | defer C.free_string(ptr)
870 | id := callback_contexts.Add(ctx)
871 | ctx.cbi = unsafe.Pointer(C._g_signal_connect(unsafe.Pointer(v.Object), C.to_gcharptr(ptr), C.int(id), C.int(flags)))
872 | return id
873 | }
874 |
875 | func (v *GObject) SignalConnectAfter(s string, f interface{}, datas ...interface{}) int {
876 | var data interface{}
877 | if len(datas) > 0 {
878 | data = datas[0]
879 | }
880 | return v.SignalConnect(s, f, data, ConnectAfter)
881 | }
882 |
883 | func (v *GObject) SignalConnectSwapped(s string, f interface{}, datas ...interface{}) int {
884 | var data interface{}
885 | if len(datas) > 0 {
886 | data = datas[0]
887 | }
888 | return v.SignalConnect(s, f, data, ConnectSwapped)
889 | }
890 |
891 | func (v *GObject) StopEmission(s string) {
892 | ptr := C.CString(s)
893 | defer C.free_string(ptr)
894 | C.g_signal_stop_emission_by_name((C.gpointer)(v.Object), C.to_gcharptr(ptr))
895 | }
896 |
897 | func (v *GObject) Emit(s string) {
898 | ptr := C.CString(s)
899 | defer C.free_string(ptr)
900 | C._g_signal_emit_by_name((C.gpointer)(v.Object), C.to_gcharptr(ptr))
901 | }
902 |
903 | func (v *GObject) HandlerBlock(call_id int) {
904 | value, found := callback_contexts.Get(call_id)
905 | if !found {
906 | return
907 | }
908 | context := value.(*CallbackContext)
909 | c_call_id := C._g_signal_callback_id((*C.callback_info)(context.cbi))
910 | C.g_signal_handler_block((C.gpointer)(v.Object), c_call_id)
911 | }
912 |
913 | func (v *GObject) HandlerUnblock(call_id int) {
914 | value, found := callback_contexts.Get(call_id)
915 | if !found {
916 | return
917 | }
918 | context := value.(*CallbackContext)
919 | c_call_id := C._g_signal_callback_id((*C.callback_info)(context.cbi))
920 | C.g_signal_handler_unblock((C.gpointer)(v.Object), c_call_id)
921 | }
922 |
923 | func (v *GObject) HandlerDisconnect(call_id int) {
924 | value, found := callback_contexts.Get(call_id)
925 | if !found {
926 | return
927 | }
928 | context := value.(*CallbackContext)
929 | c_call_id := C._g_signal_callback_id((*C.callback_info)(context.cbi))
930 | C.g_signal_handler_disconnect((C.gpointer)(v.Object), c_call_id)
931 | callback_contexts.Remove(call_id)
932 | }
933 |
934 | //-----------------------------------------------------------------------
935 | // Main Loop
936 | //-----------------------------------------------------------------------
937 | type GMainContext struct {
938 | MainContext *C.GMainContext
939 | }
940 |
941 | type GMainLoop struct {
942 | MainLoop *C.GMainLoop
943 | }
944 |
945 | func NewMainContext() *GMainContext {
946 | return &GMainContext{C.g_main_context_new()}
947 | }
948 |
949 | func (v *GMainContext) Ref() *GMainContext {
950 | return &GMainContext{C.g_main_context_ref(v.MainContext)}
951 | }
952 |
953 | func (v *GMainContext) Unref() {
954 | C.g_main_context_unref(v.MainContext)
955 | }
956 |
957 | func MainContextDefault() *GMainContext {
958 | return &GMainContext{C.g_main_context_default()}
959 | }
960 |
961 | func (v *GMainContext) Iteration(blocking bool) bool {
962 | return gobool(C.g_main_context_iteration(v.MainContext, gbool(blocking)))
963 | }
964 |
965 | func (v *GMainContext) Pending() bool {
966 | return gobool(C.g_main_context_pending(v.MainContext))
967 | }
968 |
969 | func NewMainLoop(context *GMainContext, is_running bool) *GMainLoop {
970 | var ctx *C.GMainContext
971 | if context != nil {
972 | ctx = context.MainContext
973 | }
974 | return &GMainLoop{C.g_main_loop_new(ctx, gbool(is_running))}
975 | }
976 |
977 | func (v *GMainLoop) Ref() *GMainLoop {
978 | return &GMainLoop{C.g_main_loop_ref(v.MainLoop)}
979 | }
980 |
981 | func (v *GMainLoop) Unref() {
982 | C.g_main_loop_unref(v.MainLoop)
983 | }
984 |
985 | func (v *GMainLoop) Run() {
986 | C.g_main_loop_run(v.MainLoop)
987 | }
988 |
989 | func (v *GMainLoop) Quit() {
990 | C.g_main_loop_quit(v.MainLoop)
991 | }
992 |
993 | func (v *GMainLoop) IsRunning() bool {
994 | return gobool(C.g_main_loop_is_running(v.MainLoop))
995 | }
996 |
997 | func (v *GMainLoop) GetContext() *GMainContext {
998 | return &GMainContext{C.g_main_loop_get_context(v.MainLoop)}
999 | }
1000 |
1001 | type SourcefuncContext struct {
1002 | f reflect.Value
1003 | data reflect.Value
1004 | }
1005 |
1006 | //export _go_glib_sourcefunc
1007 | func _go_glib_sourcefunc(sfi *C.sourcefunc_info) {
1008 | id := int(sfi.func_no)
1009 | value, found := sourcefunc_contexts.Get(id)
1010 | if !found {
1011 | return
1012 | }
1013 | context := value.(*SourcefuncContext)
1014 | t := context.f.Type()
1015 | fargs := make([]reflect.Value, t.NumIn())
1016 | if len(fargs) > 0 {
1017 | fargs[0] = reflect.ValueOf(context.data)
1018 | }
1019 | ret := context.f.Call(fargs)
1020 | if len(ret) > 0 {
1021 | bret, _ := ret[0].Interface().(bool)
1022 | sfi.ret = gbool(bret)
1023 | }
1024 | }
1025 |
1026 | func IdleAdd(f interface{}, datas ...interface{}) {
1027 | var data interface{}
1028 | if len(datas) > 0 {
1029 | data = datas[0]
1030 | }
1031 | ctx := &SourcefuncContext{reflect.ValueOf(f), reflect.ValueOf(data)}
1032 | id := sourcefunc_contexts.Add(ctx)
1033 | C._g_idle_add(C.int(id))
1034 | }
1035 |
1036 | func TimeoutAdd(interval uint, f interface{}, datas ...interface{}) {
1037 | var data interface{}
1038 | if len(datas) > 0 {
1039 | data = datas[0]
1040 | }
1041 | ctx := &SourcefuncContext{reflect.ValueOf(f), reflect.ValueOf(data)}
1042 | id := sourcefunc_contexts.Add(ctx)
1043 | C._g_timeout_add(C.guint(interval), C.int(id))
1044 | }
1045 |
1046 | //-----------------------------------------------------------------------
1047 | // thread
1048 | //-----------------------------------------------------------------------
1049 | func ThreadInit(a ...interface{}) {
1050 | // TODO: define GThreadFunctions
1051 | C._g_thread_init(nil)
1052 | }
1053 |
--------------------------------------------------------------------------------
/glib/glib.go.h:
--------------------------------------------------------------------------------
1 | #ifndef GO_GLIB_H
2 | #define GO_GLIB_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | static GList* to_list(void* l) {
10 | return (GList*)l;
11 | }
12 | static GSList* to_slist(void* sl) {
13 | return (GSList*)sl;
14 | }
15 | static GError* to_error(void* err) {
16 | return (GError*)err;
17 | }
18 | static inline GObject* to_GObject(void* o) { return G_OBJECT(o); }
19 |
20 | static inline gchar* to_gcharptr(const char* s) { return (gchar*)s; }
21 |
22 | static inline char* to_charptr(const gchar* s) { return (char*)s; }
23 |
24 | static inline char* to_charptr_from_gpointer(gpointer s) { return (char*)s; }
25 |
26 | static inline char* to_charptr_voidp(const void* s) { return (char*)s; }
27 |
28 | static inline void free_string(char* s) { free(s); }
29 |
30 | static inline gchar* next_string(gchar* s) { return (gchar*)(s + strlen(s) + 1); }
31 |
32 | static gboolean _g_utf8_validate(void* str, int len, void* ppbar) {
33 | return g_utf8_validate((const gchar*)str, (gssize)len, (const gchar**)ppbar);
34 | }
35 |
36 | static gchar* _g_locale_to_utf8(void* opsysstring, int len, int* bytes_read, int* bytes_written, GError** error) {
37 | return g_locale_from_utf8((const gchar*)opsysstring, (gssize)len, (gsize*)bytes_read, (gsize*)bytes_written, error);
38 | }
39 |
40 | static gchar* _g_locale_from_utf8(char* utf8string, int len, int* bytes_read, int* bytes_written, GError** error) {
41 | return g_locale_from_utf8((const gchar*)utf8string, (gssize)len, (gsize*)bytes_read, (gsize*)bytes_written, error);
42 | }
43 | static void _g_object_set_ptr(gpointer object, const gchar *property_name, void* value) {
44 | g_object_set(object, property_name, value, NULL);
45 | }
46 | static void _g_object_set_addr(gpointer object, const gchar *property_name, void* value) {
47 | g_object_set(object, property_name, *(gpointer**)value, NULL);
48 | }
49 | //static void _g_object_get(gpointer object, const gchar *property_name, void* value) {
50 | // g_object_get(object, property_name, value, NULL);
51 | //}
52 |
53 | static void g_value_init_int(GValue* gv) { g_value_init(gv, G_TYPE_INT); }
54 | static void g_value_init_string(GValue* gv) { g_value_init(gv, G_TYPE_STRING); }
55 |
56 | static GValue* init_gvalue_string_type() {
57 | GValue* gv = g_new0(GValue, 1);
58 | g_value_init(gv, G_TYPE_STRING);
59 | return gv;
60 | }
61 | static GValue* init_gvalue_string(gchar* val) {
62 | GValue* gv = init_gvalue_string_type();
63 | g_value_set_string(gv, val);
64 | return gv;
65 | }
66 |
67 | static GValue* init_gvalue_int_type() {
68 | GValue* gv = g_new0(GValue, 1);
69 | g_value_init(gv, G_TYPE_INT);
70 | return gv;
71 | }
72 | static GValue* init_gvalue_int(gint val) {
73 | GValue* gv = init_gvalue_int_type();
74 | g_value_set_int(gv, val);
75 | return gv;
76 | }
77 |
78 | static GValue* init_gvalue_uint(guint val) { GValue* gv = g_new0(GValue, 1); g_value_init(gv, G_TYPE_UINT); g_value_set_uint(gv, val); return gv; }
79 | static GValue* init_gvalue_int64(gint64 val) { GValue* gv = g_new0(GValue, 1); g_value_init(gv, G_TYPE_INT64); g_value_set_int64(gv, val); return gv; }
80 | static GValue* init_gvalue_double(gdouble val) { GValue* gv = g_new0(GValue, 1); g_value_init(gv, G_TYPE_DOUBLE); g_value_set_double(gv, val); return gv; }
81 | static GValue* init_gvalue_byte(guchar val) { GValue* gv = g_new0(GValue, 1); g_value_init(gv, G_TYPE_UCHAR); g_value_set_uchar(gv, val); return gv; }
82 | static GValue* init_gvalue_bool(gboolean val) { GValue* gv = g_new0(GValue, 1); g_value_init(gv, G_TYPE_BOOLEAN); g_value_set_boolean(gv, val); return gv; }
83 | //static GValue* init_gvalue_pointer(gpointer val) { GValue* gv = g_new0(GValue, 1); g_value_init(gv, G_TYPE_POINTER); g_value_set_pointer(gv, val); return gv; }
84 |
85 | typedef struct {
86 | char *name;
87 | int func_no;
88 | void* target;
89 | uintptr_t* args;
90 | int args_no;
91 | void* ret;
92 | gulong id;
93 | } callback_info;
94 |
95 | static uintptr_t callback_info_get_arg(callback_info* cbi, int idx) {
96 | return cbi->args[idx];
97 | }
98 | extern void _go_glib_callback(callback_info* cbi);
99 | static uintptr_t _glib_callback(void *data, ...) {
100 | va_list ap;
101 | callback_info *cbi = (callback_info*) data;
102 |
103 | int i;
104 | cbi->args = (uintptr_t*)malloc(sizeof(uintptr_t)*cbi->args_no);
105 | va_start(ap, data);
106 | for (i = 0; i < cbi->args_no; i++) {
107 | cbi->args[i] = va_arg(ap, uintptr_t);
108 | }
109 | va_end(ap);
110 |
111 | _go_glib_callback(cbi);
112 |
113 | free(cbi->args);
114 |
115 | return *(uintptr_t*)(&cbi->ret);
116 | }
117 |
118 | static void free_callback_info(gpointer data, GClosure *closure) {
119 | g_slice_free(callback_info, data);
120 | }
121 |
122 | static callback_info* _g_signal_connect(void* obj, gchar* name, int func_no, int flags) {
123 | GSignalQuery query;
124 | callback_info* cbi;
125 | guint signal_id = g_signal_lookup(name, G_OBJECT_TYPE(obj));
126 | g_signal_query(signal_id, &query);
127 | cbi = g_slice_new0(callback_info);
128 | cbi->name = g_strdup(name);
129 | cbi->func_no = func_no;
130 | cbi->args = NULL;
131 | cbi->target = obj;
132 | cbi->args_no = query.n_params;
133 | if (((GConnectFlags)flags) == G_CONNECT_AFTER)
134 | cbi->id = g_signal_connect_data((gpointer)obj, name, G_CALLBACK(_glib_callback), (gpointer)cbi, free_callback_info, G_CONNECT_AFTER);
135 | else
136 | cbi->id = g_signal_connect_data((gpointer)obj, name, G_CALLBACK(_glib_callback), (gpointer)cbi, free_callback_info, G_CONNECT_SWAPPED);
137 | return cbi;
138 | }
139 |
140 | static void _g_signal_emit_by_name(gpointer instance, const gchar *detailed_signal) {
141 | g_signal_emit_by_name(instance, detailed_signal);
142 | }
143 |
144 | static gulong _g_signal_callback_id(callback_info* cbi) {
145 | return cbi->id;
146 | }
147 |
148 | typedef struct {
149 | int func_no;
150 | gboolean ret;
151 | guint id;
152 | } sourcefunc_info;
153 |
154 | extern void _go_glib_sourcefunc(sourcefunc_info* sfi);
155 | static gboolean _go_sourcefunc(void *data) {
156 | sourcefunc_info *sfi = (sourcefunc_info*) data;
157 |
158 | _go_glib_sourcefunc(sfi);
159 |
160 | return sfi->ret;
161 | }
162 |
163 | static void free_sourcefunc_info(gpointer data) {
164 | g_slice_free(sourcefunc_info, data);
165 | }
166 |
167 | static sourcefunc_info* _g_idle_add(int func_no) {
168 | sourcefunc_info* sfi;
169 | sfi = g_slice_new0(sourcefunc_info);
170 | sfi->func_no = func_no;
171 | sfi->id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, _go_sourcefunc, sfi, free_sourcefunc_info);
172 | return sfi;
173 | }
174 |
175 | static sourcefunc_info* _g_timeout_add(guint interval, int func_no) {
176 | sourcefunc_info* sfi;
177 | sfi = g_slice_new0(sourcefunc_info);
178 | sfi->func_no = func_no;
179 | sfi->id = g_timeout_add_full(G_PRIORITY_DEFAULT, interval, _go_sourcefunc, sfi, free_sourcefunc_info);
180 | return sfi;
181 | }
182 |
183 | static void _g_thread_init(GThreadFunctions *vtable) {
184 | #if !GLIB_CHECK_VERSION(2,32,0)
185 | #ifdef G_THREADS_ENABLED
186 | g_thread_init(vtable);
187 | #endif
188 | #endif
189 | }
190 |
191 | #if !GLIB_CHECK_VERSION(2,28,0)
192 | static const gchar *
193 | g_get_user_runtime_dir (void)
194 | {
195 | #ifndef G_OS_WIN32
196 | static const gchar *runtime_dir;
197 | static gsize initialised;
198 |
199 | if (g_once_init_enter (&initialised)) {
200 | runtime_dir = g_strdup (getenv ("XDG_RUNTIME_DIR"));
201 | if (runtime_dir == NULL)
202 | g_warning ("XDG_RUNTIME_DIR variable not set. Falling back to XDG cache dir.");
203 | g_once_init_leave (&initialised, 1);
204 | }
205 |
206 | if (runtime_dir)
207 | return runtime_dir;
208 |
209 | /* Both fallback for UNIX and the default
210 | * in Windows: use the user cache directory.
211 | */
212 | #endif
213 |
214 | return g_get_user_cache_dir ();
215 | }
216 | #endif
217 |
218 | #endif
219 |
--------------------------------------------------------------------------------
/gtk/gtk_internal_test.go:
--------------------------------------------------------------------------------
1 | package gtk
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestAboutDialog_GetAuthors(t *testing.T) {
10 | Init(nil)
11 | dialog := NewAboutDialog()
12 | assert.Equal(t, len(dialog.GetAuthors()), 0)
13 | dialog.SetAuthors([]string{"a", ""})
14 | assert.Equal(t, len(dialog.GetAuthors()), 2)
15 | dialog.SetAuthors(nil)
16 | assert.Equal(t, len(dialog.GetAuthors()), 0)
17 | }
18 |
19 | func TestUpdateTreeViewColumns(t *testing.T) {
20 | Init(nil)
21 |
22 | columnsDesc := []struct {
23 | Title string
24 | Type string
25 | GTKType ICellRenderer
26 | }{
27 | {"Col_1", "text", NewCellRendererText()},
28 | {"Col_2", "text", NewCellRendererText()},
29 | }
30 |
31 | tw := NewTreeView()
32 | for i, c := range columnsDesc {
33 | tw.AppendColumn(NewTreeViewColumnWithAttributes(c.Title, c.GTKType, c.Type, i))
34 | }
35 |
36 | columns := tw.GetColumns()
37 |
38 | if len(columns) != len(columnsDesc) {
39 | t.Error("Wrong number of the columns:", len(columns), len(columnsDesc))
40 | } else {
41 |
42 | for i, _ := range columnsDesc {
43 | if columns[i].GetTitle() != columnsDesc[i].Title {
44 | t.Error("Wrong column title:", columns[i].GetTitle(), columnsDesc[i].Title)
45 | }
46 | }
47 | }
48 |
49 | for lastIndex := len(columns) - 1; lastIndex >= 0; {
50 | c := columns[lastIndex]
51 |
52 | after := tw.RemoveColumn(c)
53 |
54 | numbersColumns := lastIndex
55 | if numbersColumns != after {
56 | t.Error("Failed remove column:", numbersColumns, after)
57 | }
58 |
59 | lastIndex -= 1
60 | if lastIndex >= 0 {
61 | if title := tw.GetColumns()[lastIndex].GetTitle(); title != columnsDesc[lastIndex].Title {
62 | t.Error("Wrong column title:", title, columnsDesc[lastIndex].Title)
63 | }
64 | }
65 | }
66 |
67 | if count := len(tw.GetColumns()); count != 0 {
68 | t.Error("Wrong number of the columns:", count)
69 | }
70 | }
71 |
72 | func TestDialog_GetWidgetForResponse(t *testing.T) {
73 | Init(nil)
74 | dialog := NewDialog()
75 | dialog.AddButton("A", RESPONSE_ACCEPT)
76 | dialog.AddButton("B", RESPONSE_CANCEL)
77 | accept := dialog.GetWidgetForResponse(RESPONSE_ACCEPT)
78 | cancel := dialog.GetWidgetForResponse(RESPONSE_CANCEL)
79 | assert.Equal(t, newButtonInternal(accept.GWidget).GetLabel(), "A")
80 | assert.Equal(t, newButtonInternal(cancel.GWidget).GetLabel(), "B")
81 | }
82 |
83 | func TestEntry_SetInnerBorder(t *testing.T) {
84 | Init(nil)
85 | e := NewEntry()
86 | assert.Nil(t, e.GetInnerBorder())
87 | e.SetInnerBorder(&Border{1,2,3,4,})
88 | border := e.GetInnerBorder()
89 | assert.NotNil(t, border)
90 | assert.Equal(t, *border, Border{1,2,3,4,})
91 | e.SetInnerBorder(nil)
92 | assert.Nil(t, e.GetInnerBorder())
93 | }
94 |
--------------------------------------------------------------------------------
/gtk/gtk_test.go:
--------------------------------------------------------------------------------
1 | package gtk_test
2 |
3 | import (
4 | "io/ioutil"
5 | "testing"
6 | "os"
7 | "runtime"
8 |
9 | "github.com/mattn/go-gtk/gtk"
10 | "github.com/stretchr/testify/assert"
11 | )
12 |
13 | func gtkRun() {
14 | for gtk.EventsPending() {
15 | gtk.MainIterationDo(false)
16 | runtime.Gosched()
17 | }
18 | }
19 |
20 | func TestFILE_CHOOSER(t *testing.T) {
21 | gtk.Init(nil)
22 | d := gtk.NewFileChooserDialog("Select File", nil, gtk.FILE_CHOOSER_ACTION_OPEN, "Save", gtk.RESPONSE_OK)
23 | assert.NotNil(t, d)
24 |
25 | d.SetShowHidden(false)
26 | assert.False(t, d.GetShowHidden())
27 | d.SetShowHidden(true)
28 | assert.True(t, d.GetShowHidden())
29 |
30 | d.SetDoOverwriteConfirmation(false)
31 | assert.False(t, d.GetDoOverwriteConfirmation())
32 | d.SetDoOverwriteConfirmation(true)
33 | assert.True(t, d.GetDoOverwriteConfirmation())
34 |
35 | d.SetCreateFolders(false)
36 | assert.False(t, d.GetCreateFolders())
37 | d.SetCreateFolders(true)
38 | assert.True(t, d.GetCreateFolders())
39 |
40 | d.SelectFilename("foobar")
41 | d.UnselectFilename("foobar")
42 |
43 | d.SelectAll()
44 | d.UnselectAll()
45 |
46 | f1, err := ioutil.TempFile("/tmp", "go-gtk")
47 | assert.NoError(t, err)
48 | f1.Close()
49 | defer os.Remove(f1.Name())
50 |
51 | f2, err := ioutil.TempFile("/tmp", "go-gtk")
52 | assert.NoError(t, err)
53 | f2.Close()
54 | defer os.Remove(f2.Name())
55 |
56 | d.SelectFilename(f1.Name())
57 | gtkRun()
58 | d.GetFilename()
59 | //assert.Equal(t, f1.Name(), d.GetFilename())
60 |
61 | d.GetUri()
62 | //assert.Equal(t, "file://"+f1.Name(), d.GetUri())
63 | d.SetUri("file://" + f2.Name())
64 | d.GetUri()
65 | //assert.Equal(t, "file://"+f2.Name(), d.GetUri())
66 |
67 | assert.True(t, d.SelectUri("file://"+f1.Name()))
68 | gtkRun()
69 | d.UnselectUri("file://"+f1.Name())
70 |
71 | d.UnselectAll()
72 | gtkRun()
73 | d.GetFilenames()
74 | //assert.Equal(t, []string{}, d.GetFilenames())
75 | d.GetUris()
76 | //assert.Equal(t, []string{}, d.GetUris())
77 |
78 | d.SelectFilename(f2.Name())
79 | d.GetFilenames()
80 | //assert.Equal(t, []string{f2.Name()}, d.GetFilenames())
81 | d.GetUris()
82 | //assert.Equal(t, []string{"file://" + f2.Name()}, d.GetUris())
83 | }
84 |
85 | func TestFileChooser_SetCurrentName(t *testing.T) {
86 | gtk.Init(nil)
87 | d := gtk.NewFileChooserWidget(gtk.FILE_CHOOSER_ACTION_SAVE)
88 | d.SetCurrentName("foobar")
89 | // no way to check this until GTK+ 3.10
90 | }
91 |
92 |
93 | func TestMisc_GetPadding(t *testing.T) {
94 | gtk.Init(nil)
95 | m := gtk.NewImage()
96 | m.SetPadding(1, 2)
97 | x, y := m.GetPadding()
98 | assert.Equal(t, x, 1)
99 | assert.Equal(t, y, 2)
100 | }
101 |
--------------------------------------------------------------------------------
/gtk/gtk_x11.go:
--------------------------------------------------------------------------------
1 | // +build with-x11
2 |
3 | package gtk
4 |
5 | import (
6 | "unsafe"
7 |
8 | "github.com/mattn/go-gtk/gdk"
9 | )
10 |
11 | func (v *Window) XID() int32 {
12 | return gdk.WindowFromUnsafe(unsafe.Pointer(v.GWidget.window)).GetNativeWindowID()
13 | }
14 |
--------------------------------------------------------------------------------
/gtkgl/gdkgl.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package gtkgl
4 |
5 | const (
6 | ATTR_NONE = 0
7 | ATTR_USE_GL = 1
8 | ATTR_BUFFER_SIZE = 2
9 | ATTR_LEVEL = 3
10 | ATTR_RGBA = 4
11 | ATTR_DOUBLEBUFFER = 5
12 | ATTR_STEREO = 6
13 | ATTR_AUX_BUFFERS = 7
14 | ATTR_RED_SIZE = 8
15 | ATTR_GREEN_SIZE = 9
16 | ATTR_BLUE_SIZE = 10
17 | ATTR_ALPGHA_SIZE = 11
18 | ATTR_DEPTH_SIZE = 12
19 | ATTR_STENCIL_SIZE = 13
20 | ATTR_ACCUM_RED_SIZE = 14
21 | ATTR_ACCUM_GREEN_SIZE = 15
22 | ATTR_ACCUM_BLUE_SIZE = 16
23 | ATTR_ACCUM_ALPHA_SIZE = 17
24 | )
25 |
26 | const (
27 | ATTR_X_VISUAL_TYPE_EXT = 0x22
28 | ATTR_TRANSPARENT_TYPE_EXT = 0x23
29 | ATTR_TRANSPARENT_INDEX_VALUE_EXT = 0x24
30 | ATTR_TRANSPARENT_RED_VALUE_EXT = 0x25
31 | ATTR_TRANSPARENT_GREEN_VALUE_EXT = 0x26
32 | ATTR_TRANSPARENT_BLUE_VALUE_EXT = 0x27
33 | ATTR_TRANSPARENT_ALPHA_VALUE_EXT = 0x28
34 | )
35 |
--------------------------------------------------------------------------------
/gtkgl/gtkgl.go.h:
--------------------------------------------------------------------------------
1 | #ifndef GO_GTKGL_H
2 | #define GO_GTKGL_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | void *make_area(int attr_count, int *attrs) {
10 | if (attr_count > 0 && attrs[attr_count-1] == 0) {
11 | // already null terminated; use the pointer directly
12 | return gtk_gl_area_new(attrs);
13 | } else {
14 | // make a null terminated copy of the attribute list
15 | GtkWidget *area = NULL;
16 | int *zattrs = malloc((attr_count+1)*sizeof(int));
17 | if (!zattrs) {
18 | return NULL;
19 | }
20 | memcpy(zattrs, attrs, attr_count * sizeof(attrs));
21 | zattrs[attr_count] = 0;
22 | area = gtk_gl_area_new(zattrs);
23 | free(zattrs);
24 | return area;
25 | }
26 | }
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/gtkgl/gtkglarea.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package gtkgl
4 |
5 | // #include "gtkgl.go.h"
6 | // #cgo pkg-config: gtkgl-2.0
7 | import "C"
8 |
9 | import "github.com/mattn/go-gtk/gtk"
10 | import "unsafe"
11 |
12 | type GLArea struct {
13 | gtk.DrawingArea
14 | }
15 |
16 | func NewGLArea(attrList []int) *GLArea {
17 | return &GLArea{gtk.DrawingArea{
18 | *gtk.WidgetFromNative(C.make_area(C.int(len(attrList)), (*C.int)(unsafe.Pointer(&attrList[0]))))}}
19 | }
20 |
21 | func (v *GLArea) MakeCurrent() {
22 | C.gtk_gl_area_make_current((*C.GtkGLArea)(unsafe.Pointer(v.GWidget)))
23 | }
24 |
25 | func (v *GLArea) SwapBuffers() {
26 | C.gtk_gl_area_swap_buffers((*C.GtkGLArea)(unsafe.Pointer(v.GWidget)))
27 | }
28 |
--------------------------------------------------------------------------------
/gtksourceview/gtksourceview.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package gtksourceview
4 |
5 | // #include "gtksourceview.go.h"
6 | // #cgo pkg-config: gtksourceview-2.0
7 | import "C"
8 | import (
9 | "unsafe"
10 |
11 | "github.com/mattn/go-gtk/gtk"
12 | )
13 |
14 | func gstring(s *C.char) *C.gchar { return C.toGstr(s) }
15 | func cstring(s *C.gchar) *C.char { return C.toCstr(s) }
16 | func gostring(s *C.gchar) string { return C.GoString(cstring(s)) }
17 |
18 | func gbool(b bool) C.gboolean {
19 | if b {
20 | return C.gboolean(1)
21 | }
22 | return C.gboolean(0)
23 | }
24 |
25 | func gobool(b C.gboolean) bool {
26 | if b != 0 {
27 | return true
28 | }
29 | return false
30 | }
31 |
32 | func cfree(s *C.char) { C.freeCstr(s) }
33 |
34 | //-----------------------------------------------------------------------
35 | // GtkSourceBuffer
36 | //-----------------------------------------------------------------------
37 | type SourceBuffer struct {
38 | GSourceBuffer *C.GtkSourceBuffer
39 | *gtk.TextBuffer
40 | }
41 |
42 | func NewSourceBuffer() *SourceBuffer {
43 | v := C.gtk_source_buffer_new(nil)
44 | return &SourceBuffer{v, gtk.NewTextBufferFromPointer(unsafe.Pointer(v))}
45 | }
46 |
47 | func NewSourceBufferWithLanguage(lang *SourceLanguage) *SourceBuffer {
48 | v := C.gtk_source_buffer_new_with_language(lang.GSourceLanguage)
49 | return &SourceBuffer{v, gtk.NewTextBufferFromPointer(unsafe.Pointer(v))}
50 | }
51 |
52 | func (v *SourceBuffer) GetNativeBuffer() unsafe.Pointer {
53 | return unsafe.Pointer(v.GSourceBuffer)
54 | }
55 |
56 | func (v *SourceBuffer) SetHighlightSyntax(highlight bool) {
57 | C.gtk_source_buffer_set_highlight_syntax(v.GSourceBuffer, gbool(highlight))
58 | }
59 |
60 | func (v *SourceBuffer) GetHighlightSyntax() bool {
61 | return gobool(C.gtk_source_buffer_get_highlight_syntax(v.GSourceBuffer))
62 | }
63 |
64 | func (v *SourceBuffer) SetHighlightMatchingBrackets(hl bool) {
65 | C.gtk_source_buffer_set_highlight_matching_brackets(v.GSourceBuffer, gbool(hl))
66 | }
67 |
68 | func (v *SourceBuffer) SetLanguage(lang *SourceLanguage) {
69 | C.gtk_source_buffer_set_language(v.GSourceBuffer, lang.GSourceLanguage)
70 | }
71 |
72 | func (v *SourceBuffer) GetLanguage() *SourceLanguage {
73 | return &SourceLanguage{C.gtk_source_buffer_get_language(v.GSourceBuffer)}
74 | }
75 |
76 | func (v *SourceBuffer) BeginNotUndoableAction() {
77 | C.gtk_source_buffer_begin_not_undoable_action(v.GSourceBuffer)
78 | }
79 |
80 | func (v *SourceBuffer) EndNotUndoableAction() {
81 | C.gtk_source_buffer_end_not_undoable_action(v.GSourceBuffer)
82 | }
83 |
84 | func (v *SourceBuffer) SetStyleScheme(scheme *SourceStyleScheme) {
85 | C.gtk_source_buffer_set_style_scheme(v.GSourceBuffer, scheme.GSourceStyleScheme)
86 | }
87 |
88 | //-----------------------------------------------------------------------
89 | // GtkSourceView
90 | //-----------------------------------------------------------------------
91 | type SourceView struct {
92 | gtk.TextView
93 | }
94 |
95 | func NewSourceView() *SourceView {
96 | return &SourceView{gtk.TextView{gtk.Container{
97 | *gtk.WidgetFromNative(unsafe.Pointer(C.gtk_source_view_new()))}}}
98 | }
99 |
100 | func NewSourceViewWithBuffer(buf *SourceBuffer) *SourceView {
101 | return &SourceView{gtk.TextView{gtk.Container{
102 | *gtk.WidgetFromNative(unsafe.Pointer(C.gtk_source_view_new_with_buffer(buf.GSourceBuffer)))}}}
103 | }
104 |
105 | func (v *SourceView) ToNativeSourceView() *C.GtkSourceView {
106 | return C.toGtkSourceView(unsafe.Pointer(v.GWidget))
107 | }
108 |
109 | func (v *SourceView) SetAutoIndent(enable bool) {
110 | C.gtk_source_view_set_auto_indent(v.ToNativeSourceView(), gbool(enable))
111 | }
112 |
113 | func (v *SourceView) GetAutoIndent() bool {
114 | return gobool(C.gtk_source_view_get_auto_indent(v.ToNativeSourceView()))
115 | }
116 |
117 | func (v *SourceView) SetHighlightCurrentLine(enable bool) {
118 | C.gtk_source_view_set_highlight_current_line(v.ToNativeSourceView(), gbool(enable))
119 | }
120 |
121 | func (v *SourceView) GetHighlightCurrentLine() bool {
122 | return gobool(C.gtk_source_view_get_highlight_current_line(v.ToNativeSourceView()))
123 | }
124 |
125 | func (v *SourceView) SetShowLineNumbers(enable bool) {
126 | C.gtk_source_view_set_show_line_numbers(v.ToNativeSourceView(), gbool(enable))
127 | }
128 |
129 | func (v *SourceView) GetShowLineNumbers() bool {
130 | return gobool(C.gtk_source_view_get_show_line_numbers(v.ToNativeSourceView()))
131 | }
132 |
133 | func (v *SourceView) SetRightMarginPosition(pos uint) {
134 | C.gtk_source_view_set_right_margin_position(v.ToNativeSourceView(), C.guint(pos))
135 | }
136 |
137 | func (v *SourceView) GetRightMarginPosition() uint {
138 | return uint(C.gtk_source_view_get_right_margin_position(v.ToNativeSourceView()))
139 | }
140 |
141 | func (v *SourceView) SetIndentWidth(width int) {
142 | C.gtk_source_view_set_indent_width(v.ToNativeSourceView(), C.gint(width))
143 | }
144 |
145 | func (v *SourceView) GetIndentWidth() int {
146 | return int(C.gtk_source_view_get_indent_width(v.ToNativeSourceView()))
147 | }
148 |
149 | func (v *SourceView) SetShowRightMargin(enable bool) {
150 | C.gtk_source_view_set_show_right_margin(v.ToNativeSourceView(), gbool(enable))
151 | }
152 |
153 | func (v *SourceView) GetShowRightMargin() bool {
154 | return gobool(C.gtk_source_view_get_show_right_margin(v.ToNativeSourceView()))
155 | }
156 |
157 | func (v *SourceView) SetInsertSpacesInsteadOfTabs(enable bool) {
158 | C.gtk_source_view_set_insert_spaces_instead_of_tabs(v.ToNativeSourceView(), gbool(enable))
159 | }
160 |
161 | func (v *SourceView) GetInsertSpacesInsteadOfTabs() bool {
162 | return gobool(C.gtk_source_view_get_insert_spaces_instead_of_tabs(v.ToNativeSourceView()))
163 | }
164 |
165 | type SourceDrawSpacesFlags int
166 |
167 | const (
168 | SOURCE_DRAW_SPACES_SPACE SourceDrawSpacesFlags = 1 << 0
169 | SOURCE_DRAW_SPACES_TAB SourceDrawSpacesFlags = 1 << 1
170 | SOURCE_DRAW_SPACES_NEWLINE SourceDrawSpacesFlags = 1 << 2
171 | SOURCE_DRAW_SPACES_NBSP SourceDrawSpacesFlags = 1 << 3
172 | SOURCE_DRAW_SPACES_LEADING SourceDrawSpacesFlags = 1 << 4
173 | SOURCE_DRAW_SPACES_TEXT SourceDrawSpacesFlags = 1 << 5
174 | SOURCE_DRAW_SPACES_TRAILING SourceDrawSpacesFlags = 1 << 6
175 | SOURCE_DRAW_SPACES_ALL SourceDrawSpacesFlags = (SOURCE_DRAW_SPACES_SPACE |
176 | SOURCE_DRAW_SPACES_TAB |
177 | SOURCE_DRAW_SPACES_NEWLINE |
178 | SOURCE_DRAW_SPACES_NBSP |
179 | SOURCE_DRAW_SPACES_LEADING |
180 | SOURCE_DRAW_SPACES_TEXT |
181 | SOURCE_DRAW_SPACES_TRAILING)
182 | )
183 |
184 | func (v *SourceView) SetDrawSpaces(flags SourceDrawSpacesFlags) {
185 | C.gtk_source_view_set_draw_spaces(v.ToNativeSourceView(),
186 | C.GtkSourceDrawSpacesFlags(flags))
187 | }
188 |
189 | func (v *SourceView) GetDrawSpaces() SourceDrawSpacesFlags {
190 | return SourceDrawSpacesFlags(C.gtk_source_view_get_draw_spaces(v.ToNativeSourceView()))
191 | }
192 |
193 | func (v *SourceView) SetTabWidth(width uint) {
194 | C.gtk_source_view_set_tab_width(v.ToNativeSourceView(),
195 | C.guint(width))
196 | }
197 |
198 | func (v *SourceView) GetTabWidth() uint {
199 | return uint(C.gtk_source_view_get_tab_width(v.ToNativeSourceView()))
200 | }
201 |
202 | type SourceSmartHomeEndType int
203 |
204 | const (
205 | SOURCE_SMART_HOME_END_DISABLED SourceSmartHomeEndType = 0
206 | SOURCE_SMART_HOME_END_BEFORE SourceSmartHomeEndType = 1
207 | SOURCE_SMART_HOME_END_AFTER SourceSmartHomeEndType = 2
208 | SOURCE_SMART_HOME_END_ALWAYS SourceSmartHomeEndType = 3
209 | )
210 |
211 | func (v *SourceView) SetSmartHomeEnd(flags SourceSmartHomeEndType) {
212 | C.gtk_source_view_set_smart_home_end(v.ToNativeSourceView(),
213 | C.GtkSourceSmartHomeEndType(flags))
214 | }
215 |
216 | func (v *SourceView) GetSmartHomeEnd() SourceSmartHomeEndType {
217 | return SourceSmartHomeEndType(C.gtk_source_view_get_smart_home_end(v.ToNativeSourceView()))
218 | }
219 |
220 | //-----------------------------------------------------------------------
221 | // GtkSourceLanguage
222 | //-----------------------------------------------------------------------
223 | type SourceLanguage struct {
224 | GSourceLanguage *C.GtkSourceLanguage
225 | }
226 |
227 | func (v *SourceLanguage) GetId() string {
228 | return gostring(C.gtk_source_language_get_id(v.GSourceLanguage))
229 | }
230 |
231 | func (v *SourceLanguage) GetName() string {
232 | return gostring(C.gtk_source_language_get_name(v.GSourceLanguage))
233 | }
234 |
235 | func (v *SourceLanguage) GetSection() string {
236 | return gostring(C.gtk_source_language_get_section(v.GSourceLanguage))
237 | }
238 |
239 | func (v *SourceLanguage) GetHidden() bool {
240 | return gobool(C.gtk_source_language_get_hidden(v.GSourceLanguage))
241 | }
242 |
243 | func (v *SourceLanguage) GetMetadata(name string) string {
244 | cname := C.CString(name)
245 | defer cfree(cname)
246 | return gostring(C.gtk_source_language_get_metadata(v.GSourceLanguage, gstring(cname)))
247 | }
248 |
249 | func (v *SourceLanguage) GetMimeTypes() []string {
250 | var types []string
251 | ctypes := C.gtk_source_language_get_mime_types(v.GSourceLanguage)
252 | for {
253 | types = append(types, gostring(*ctypes))
254 | ctypes = C.nextGstr(ctypes)
255 | if *ctypes == nil {
256 | break
257 | }
258 | }
259 | return types
260 | }
261 |
262 | func (v *SourceLanguage) GetGlobs() []string {
263 | var globs []string
264 | cglobs := C.gtk_source_language_get_globs(v.GSourceLanguage)
265 | for {
266 | globs = append(globs, gostring(*cglobs))
267 | cglobs = C.nextGstr(cglobs)
268 | if *cglobs == nil {
269 | break
270 | }
271 | }
272 | return globs
273 | }
274 |
275 | func (v *SourceLanguage) GetStyleName(styleId string) string {
276 | cstyleId := C.CString(styleId)
277 | defer cfree(cstyleId)
278 | return gostring(C.gtk_source_language_get_metadata(v.GSourceLanguage, gstring(cstyleId)))
279 | }
280 |
281 | func (v *SourceLanguage) GetStyleIds() []string {
282 | var ids []string
283 | cids := C.gtk_source_language_get_globs(v.GSourceLanguage)
284 | for {
285 | ids = append(ids, gostring(*cids))
286 | cids = C.nextGstr(cids)
287 | if *cids == nil {
288 | break
289 | }
290 | }
291 | return ids
292 | }
293 |
294 | //FINISH
295 |
296 | //-----------------------------------------------------------------------
297 | // GtkSourceLanguageManager
298 | //-----------------------------------------------------------------------
299 | type SourceLanguageManager struct {
300 | GSourceLanguageManager *C.GtkSourceLanguageManager
301 | }
302 |
303 | func NewSourceLanguageManager() *SourceLanguageManager {
304 | return &SourceLanguageManager{C.gtk_source_language_manager_new()}
305 | }
306 |
307 | func SourceLanguageManagerGetDefault() *SourceLanguageManager {
308 | return &SourceLanguageManager{C.gtk_source_language_manager_get_default()}
309 | }
310 |
311 | func (v *SourceLanguageManager) SetSearchPath(paths []string) {
312 | cpaths := C.make_strings(C.int(len(paths) + 1))
313 | for i, path := range paths {
314 | ptr := C.CString(path)
315 | defer cfree(ptr)
316 | C.set_string(cpaths, C.int(i), gstring(ptr))
317 | }
318 | C.set_string(cpaths, C.int(len(paths)), nil)
319 | C.gtk_source_language_manager_set_search_path(v.GSourceLanguageManager, cpaths)
320 | C.destroy_strings(cpaths)
321 | }
322 |
323 | func (v *SourceLanguageManager) GetSearchPath() []string {
324 | var dirs []string
325 | cdirs := C.gtk_source_language_manager_get_search_path(v.GSourceLanguageManager)
326 | for {
327 | dirs = append(dirs, gostring(*cdirs))
328 | cdirs = C.nextGstr(cdirs)
329 | if *cdirs == nil {
330 | break
331 | }
332 | }
333 | return dirs
334 | }
335 |
336 | func (v *SourceLanguageManager) GetLanguageIds() []string {
337 | var ids []string
338 | cids := C.gtk_source_language_manager_get_language_ids(v.GSourceLanguageManager)
339 | for {
340 | ids = append(ids, gostring(*cids))
341 | cids = C.nextGstr(cids)
342 | if *cids == nil {
343 | break
344 | }
345 | }
346 | return ids
347 | }
348 |
349 | func (v *SourceLanguageManager) GetLanguage(id string) *SourceLanguage {
350 | cid := C.CString(id)
351 | defer cfree(cid)
352 | return &SourceLanguage{C.gtk_source_language_manager_get_language(v.GSourceLanguageManager, gstring(cid))}
353 | }
354 |
355 | func (v *SourceLanguageManager) GuessLanguage(filename string, contentType string) *SourceLanguage {
356 | if filename == "" {
357 | cct := C.CString(contentType)
358 | defer cfree(cct)
359 | return &SourceLanguage{C.gtk_source_language_manager_guess_language(v.GSourceLanguageManager, nil, gstring(cct))}
360 | }
361 | cfn := C.CString(filename)
362 | defer cfree(cfn)
363 | return &SourceLanguage{C.gtk_source_language_manager_guess_language(v.GSourceLanguageManager, gstring(cfn), nil)}
364 | }
365 |
366 | //FINISH
367 |
368 | //-----------------------------------------------------------------------
369 | // GtkSourceStyle
370 | //-----------------------------------------------------------------------
371 | type SourceStyleScheme struct {
372 | GSourceStyleScheme *C.GtkSourceStyleScheme
373 | }
374 |
375 | // gtk_source_style_scheme_get_id
376 | // gtk_source_style_scheme_get_name
377 | // gtk_source_style_scheme_get_description
378 | // gtk_source_style_scheme_get_authors
379 | // gtk_source_style_scheme_get_filename
380 | // gtk_source_style_scheme_get_style
381 |
382 | //-----------------------------------------------------------------------
383 | // GtkSourceStyleSchemeManager
384 | //-----------------------------------------------------------------------
385 | type SourceStyleSchemeManager struct {
386 | GSourceStyleSchemeManager *C.GtkSourceStyleSchemeManager
387 | }
388 |
389 | func NewSourceStyleSchemeManager() *SourceStyleSchemeManager {
390 | return &SourceStyleSchemeManager{C.gtk_source_style_scheme_manager_new()}
391 | }
392 |
393 | func SourceStyleSchemeManagerGetDefault() *SourceStyleSchemeManager {
394 | return &SourceStyleSchemeManager{C.gtk_source_style_scheme_manager_get_default()}
395 | }
396 |
397 | func (v *SourceStyleSchemeManager) GetScheme(scheme_id string) *SourceStyleScheme {
398 | cscheme_id := C.CString(scheme_id)
399 | defer cfree(cscheme_id)
400 | return &SourceStyleScheme{C.gtk_source_style_scheme_manager_get_scheme(v.GSourceStyleSchemeManager, gstring(cscheme_id))}
401 | }
402 |
403 | func (v *SourceStyleSchemeManager) SetSearchPath(paths []string) {
404 | cpaths := C.make_strings(C.int(len(paths) + 1))
405 | for i, path := range paths {
406 | ptr := C.CString(path)
407 | defer cfree(ptr)
408 | C.set_string(cpaths, C.int(i), gstring(ptr))
409 | }
410 | C.set_string(cpaths, C.int(len(paths)), nil)
411 | C.gtk_source_style_scheme_manager_set_search_path(v.GSourceStyleSchemeManager, cpaths)
412 | }
413 |
414 | func (v *SourceStyleSchemeManager) GetSearchPath() []string {
415 | var dirs []string
416 | cdirs := C.gtk_source_style_scheme_manager_get_search_path(v.GSourceStyleSchemeManager)
417 | for {
418 | dirs = append(dirs, gostring(*cdirs))
419 | cdirs = C.nextGstr(cdirs)
420 | if *cdirs == nil {
421 | break
422 | }
423 | }
424 | return dirs
425 | }
426 |
427 | func (v *SourceStyleSchemeManager) AppendSearchPath(path string) {
428 | cpath := C.CString(path)
429 | defer cfree(cpath)
430 | C.gtk_source_style_scheme_manager_append_search_path(v.GSourceStyleSchemeManager, gstring(cpath))
431 | }
432 |
433 | func (v *SourceStyleSchemeManager) PrepandSearchPath(path string) {
434 | cpath := C.CString(path)
435 | defer cfree(cpath)
436 | C.gtk_source_style_scheme_manager_prepend_search_path(v.GSourceStyleSchemeManager, gstring(cpath))
437 | }
438 |
439 | func (v *SourceStyleSchemeManager) GetSchemeIds() []string {
440 | var ids []string
441 | cids := C.gtk_source_style_scheme_manager_get_scheme_ids(v.GSourceStyleSchemeManager)
442 | for {
443 | ids = append(ids, gostring(*cids))
444 | cids = C.nextGstr(cids)
445 | if *cids == nil {
446 | break
447 | }
448 | }
449 | return ids
450 | }
451 |
452 | func (v *SourceStyleSchemeManager) ForseRescan() {
453 | C.gtk_source_style_scheme_manager_force_rescan(v.GSourceStyleSchemeManager)
454 | }
455 |
456 | //FINISH
457 |
--------------------------------------------------------------------------------
/gtksourceview/gtksourceview.go.h:
--------------------------------------------------------------------------------
1 | #ifndef GO_GTKSOURCEVIEW_H
2 | #define GO_GTKSOURCEVIEW_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | static inline gchar** make_strings(int count) {
12 | return (gchar**)malloc(sizeof(gchar*) * count);
13 | }
14 |
15 | static inline void destroy_strings(gchar** strings) {
16 | free(strings);
17 | }
18 |
19 | static inline void set_string(gchar** strings, int n, gchar* str) {
20 | strings[n] = str;
21 | }
22 |
23 | static inline GObject* toGObject(void* o) { return G_OBJECT(o); }
24 | static inline gchar* toGstr(const char* s) { return (gchar*)s; }
25 | static inline char* toCstr(const gchar* s) { return (char*)s; }
26 | static inline gchar** nextGstr(gchar** s) { return (s+1); }
27 | static inline void freeCstr(char* s) { free(s); }
28 | static GtkSourceView* toGtkSourceView(void* w) { return GTK_SOURCE_VIEW(w); }
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/gtkspell/gtkspell.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package gtkspell
4 |
5 | /*
6 | #include
7 | #include
8 | #include
9 |
10 | static GtkTextView* to_GtkTextView(void* w) { return GTK_TEXT_VIEW(w); }
11 | static inline gchar* to_gcharptr(const char* s) { return (gchar*)s; }
12 | */
13 | // #cgo pkg-config: gtkspell-2.0
14 | import "C"
15 | import "unsafe"
16 |
17 | import "github.com/mattn/go-gtk/glib"
18 | import "github.com/mattn/go-gtk/gtk"
19 |
20 | //-----------------------------------------------------------------------
21 | // GtkSpell
22 | //-----------------------------------------------------------------------
23 | type GtkSpell struct {
24 | Spell *C.GtkSpell
25 | }
26 |
27 | func New(textview *gtk.TextView, language string) (*GtkSpell, *glib.Error) {
28 | var lang *C.char
29 | if len(language) > 0 {
30 | lang = C.CString(language)
31 | defer C.free(unsafe.Pointer(lang))
32 | }
33 |
34 | var gerror *C.GError
35 | v := C.gtkspell_new_attach(C.to_GtkTextView(unsafe.Pointer(&textview.Widget)), C.to_gcharptr(lang), &gerror)
36 | if gerror != nil {
37 | return nil, glib.ErrorFromNative(unsafe.Pointer(gerror))
38 | }
39 | return &GtkSpell{v}, nil
40 | }
41 |
42 | func (spell *GtkSpell) SetLanguage(language string) *glib.Error {
43 | lang := C.CString(language)
44 | defer C.free(unsafe.Pointer(lang))
45 |
46 | var gerror *C.GError
47 | C.gtkspell_set_language(spell.Spell, C.to_gcharptr(lang), &gerror)
48 | if gerror != nil {
49 | return glib.ErrorFromNative(unsafe.Pointer(gerror))
50 | }
51 | return nil
52 | }
53 |
54 | func (spell *GtkSpell) Recheck() {
55 | C.gtkspell_recheck_all(spell.Spell)
56 | }
57 |
--------------------------------------------------------------------------------
/pango/pango.go:
--------------------------------------------------------------------------------
1 | // +build !cgocheck
2 |
3 | package pango
4 |
5 | // #include "pango.go.h"
6 | // #cgo pkg-config: pango
7 | import "C"
8 | import "unsafe"
9 |
10 | const (
11 | SCALE = C.PANGO_SCALE
12 | )
13 |
14 | func bool2gboolean(b bool) C.gboolean {
15 | if b {
16 | return C.gboolean(1)
17 | }
18 | return C.gboolean(0)
19 | }
20 |
21 | func gboolean2bool(b C.gboolean) bool {
22 | if b != 0 {
23 | return true
24 | }
25 | return false
26 | }
27 |
28 | type WrapMode int
29 |
30 | const (
31 | WRAP_WORD WrapMode = 0
32 | WRAP_CHAR WrapMode = 1
33 | WRAP_WORD_CHAR WrapMode = 2
34 | )
35 |
36 | type EllipsizeMode int
37 |
38 | const (
39 | ELLIPSIZE_NONE EllipsizeMode = 0
40 | ELLIPSIZE_START EllipsizeMode = 1
41 | ELLIPSIZE_MIDDLE EllipsizeMode = 2
42 | ELLIPSIZE_END EllipsizeMode = 3
43 | )
44 |
45 | type Context struct {
46 | GContext *C.PangoContext
47 | }
48 |
49 | type Layout struct {
50 | GLayout *C.PangoLayout
51 | }
52 |
53 | type FontDescription struct {
54 | GFontDescription *C.PangoFontDescription
55 | }
56 |
57 | func ContextFromUnsafe(context unsafe.Pointer) *Context {
58 | return &Context{(*C.PangoContext)(context)}
59 | }
60 |
61 | func (v *Layout) Unref() {
62 | C.g_object_unref(C.gpointer(v.GLayout))
63 | }
64 |
65 | func (v *Layout) SetWidth(width int) {
66 | C.pango_layout_set_width(v.GLayout, C.int(width))
67 | }
68 |
69 | func (v *Layout) SetFontDescription(d *FontDescription) {
70 | C.pango_layout_set_font_description(v.GLayout, d.GFontDescription)
71 | }
72 |
73 | func (v *Layout) SetText(s string) {
74 | cs := C.CString(s)
75 | C.pango_layout_set_text(v.GLayout, cs, -1)
76 | C.free(unsafe.Pointer(cs))
77 | }
78 |
79 | func NewLayout(ctx *Context) *Layout {
80 | return &Layout{C.pango_layout_new(ctx.GContext)}
81 | }
82 |
83 | func NewFontDescription() *FontDescription {
84 | return &FontDescription{C.pango_font_description_new()}
85 | }
86 |
87 | func (v *FontDescription) Free() {
88 | C.pango_font_description_free(v.GFontDescription)
89 | }
90 |
91 | func (v *FontDescription) SetSize(size int) {
92 | C.pango_font_description_set_size(v.GFontDescription, C.gint(size))
93 | }
94 |
95 | func (v *FontDescription) Copy() *FontDescription {
96 | return &FontDescription{C.pango_font_description_copy(v.GFontDescription)}
97 | }
98 |
99 | func (f *FontDescription) GetSize() int {
100 | return int(C.pango_font_description_get_size(f.GFontDescription))
101 | }
102 |
--------------------------------------------------------------------------------
/pango/pango.go.h:
--------------------------------------------------------------------------------
1 | #ifndef GO_PANGO_H
2 | #define GO_PANGO_H
3 |
4 | #ifndef uintptr
5 | #define uintptr unsigned int*
6 | #endif
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | //static const gchar* to_gcharptr(const char* s) { return (const gchar*)s; }
15 | //static guchar* to_gucharptr(void* s) { return (guchar*)s; }
16 |
17 | //static void free_string(char* s) { free(s); }
18 |
19 | //static gchar* to_gcharptr(char* s) { return (gchar*)s; }
20 |
21 | //static void free_string(char* s) { free(s); }
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/tools/gogtkinfo/gogtkinfo.go:
--------------------------------------------------------------------------------
1 | /*
2 | Simple tool to approximatively count the progress of go-gtk library.
3 | Counts line starting by "func" (binding done) or starting by "//" and containing "gtk_" (binding to do) for each section (starting by a "// text" comment preceded by a "//------------")
4 | */
5 | package main
6 |
7 | import (
8 | "bufio"
9 | "flag"
10 | "fmt"
11 | "log"
12 | "os"
13 | "sort"
14 | "strings"
15 | )
16 |
17 | func main() {
18 | list := make([]string, 0, 100)
19 | alphabeticalOrder := flag.Bool("a", false, "alphabetical order")
20 | githubCode := flag.Bool("g", false, "prepend spaces to each line so github will format them as code")
21 | flag.Parse()
22 | fname := flag.Arg(0)
23 | if fname == "" {
24 | fmt.Println("Usage: gogtkinfo [-ag] file")
25 | return
26 | }
27 | file, err := os.Open(fname)
28 | if err != nil {
29 | log.Print(err.Error())
30 | return
31 | }
32 | defer file.Close()
33 | rd := bufio.NewReader(file)
34 | var currentSection, sectionAlertName string
35 | var cDone, cTodo, p, tDone, tTodo int
36 | var sectionAlert, falseAlarm bool
37 | for {
38 | var l string
39 | if falseAlarm {
40 | falseAlarm = false
41 | } else {
42 | line, isPrefix, err := rd.ReadLine()
43 | if err != nil {
44 | break
45 | }
46 | if isPrefix {
47 | return
48 | }
49 | l = string(line)
50 | }
51 | if strings.HasPrefix(l, "//---------------") {
52 | if sectionAlertName == "" {
53 | sectionAlert = true
54 | } else {
55 | if currentSection != "" {
56 | cTot := cDone + cTodo
57 | if cTot == 0 {
58 | p = 100
59 | } else {
60 | p = 100 * cDone / cTot
61 | }
62 | s := fmt.Sprintf("%-30s: %3d%% (%3d/%3d)\n", currentSection, p, cDone, cTot)
63 | list = append(list, s)
64 | }
65 | currentSection = sectionAlertName
66 | tDone += cDone
67 | tTodo += cTodo
68 | cDone = 0
69 | cTodo = 0
70 | sectionAlertName = ""
71 | }
72 | } else if sectionAlert {
73 | if strings.HasPrefix(l, "//") && len(l) > 3 && !strings.Contains(l, "gtk_") {
74 | sectionAlertName = strings.TrimSpace(l[2:len(l)])
75 | } else {
76 | falseAlarm = true
77 | }
78 | sectionAlert = false
79 | } else if strings.HasPrefix(l, "func") {
80 | cDone++
81 | } else if strings.HasPrefix(l, "//") && strings.Contains(l, "gtk_") {
82 | cTodo++
83 | }
84 | }
85 | if *alphabeticalOrder {
86 | sort.StringSlice(list).Sort()
87 | }
88 | for _, s := range list {
89 | if *githubCode {
90 | fmt.Print(" ")
91 | }
92 | fmt.Print(s)
93 | }
94 | tTot := tDone + tTodo
95 | if tTot == 0 {
96 | p = 0
97 | } else {
98 | p = 100 * tDone / tTot
99 | }
100 | if *githubCode {
101 | fmt.Print("\n ")
102 | } else {
103 | fmt.Print("\n")
104 | }
105 | fmt.Printf("Total progress : %18d%% (%d/%d)\n", p, tDone, tTot)
106 | }
107 |
--------------------------------------------------------------------------------
/tools/make_inline_pixbuf/make_inline_pixbuf.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 |
7 | "github.com/mattn/go-gtk/gdkpixbuf"
8 | "github.com/mattn/go-gtk/gtk"
9 | )
10 |
11 | func main() {
12 | if len(os.Args) != 3 {
13 | fmt.Fprintf(os.Stderr, "Usage: make-inline-pixbuf resourceName input > output\n")
14 | os.Exit(1)
15 | }
16 |
17 | image := gtk.NewImageFromFile(os.Args[2])
18 | pb := image.GetPixbuf()
19 | if pb.GetWidth() == -1 {
20 | fmt.Fprintf(os.Stderr, "ERROR: invalid pixbuf image\n")
21 | os.Exit(2)
22 | }
23 |
24 | var pbd gdkpixbuf.PixbufData
25 | pbd.Data = pb.GetPixelsWithLength()
26 | pbd.Width, pbd.Height, pbd.RowStride, pbd.HasAlpha = pb.GetWidth(), pb.GetHeight(), pb.GetRowstride(), pb.GetHasAlpha()
27 | pbd.Colorspace, pbd.BitsPerSample = pb.GetColorspace(), pb.GetBitsPerSample()
28 |
29 | fmt.Printf("package main \n\nimport \"github.com/mattn/go-gtk/gdkpixbuf\"\n\nvar (\n")
30 | fmt.Printf("\t%s = %#v\n", os.Args[1], pbd)
31 |
32 | fmt.Println(")\n")
33 | }
34 |
--------------------------------------------------------------------------------