apngasm-gui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/Gemfile +11 -0
- data/README.md +4 -0
- data/apngasm-gui.gemspec +16 -0
- data/bin/apngasm-gui +17 -0
- data/lib/apngasm-gui.rb +3 -0
- data/lib/apngasm-gui/adapter.rb +64 -0
- data/lib/apngasm-gui/editor_window.rb +340 -0
- data/lib/apngasm-gui/frame.rb +72 -0
- data/lib/apngasm-gui/frame_list.rb +88 -0
- data/lib/apngasm-gui/layout.glade +557 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c591c6168d94eed149cbeb9b9ed24b500b6562fa
|
4
|
+
data.tar.gz: 760dcc89b39b68d528840bf3de9c93671e7444d9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a41becf6cf4953debd976e2311e1d9b45932ac319f204aafb3d458a69eb7a284387a994e97dcfbec51581988a219466325712c2e6c3dbfb0871b0ab80ec38b77
|
7
|
+
data.tar.gz: 87ff15d4bb872a0c089d04369cab35490192d5f1e41229c12aa1518383a536804eaf1d019de93758999375c8f27699c06dd8e1d59fd94d73fb1334cd687091df
|
data/.gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
.DS_Store
|
2
|
+
*.swp
|
3
|
+
*.swo
|
4
|
+
.project
|
5
|
+
|
6
|
+
*.gem
|
7
|
+
*.rbc
|
8
|
+
.bundle
|
9
|
+
.config
|
10
|
+
coverage
|
11
|
+
InstalledFiles
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
|
20
|
+
Gemfile.lock
|
21
|
+
|
22
|
+
# YARD artifacts
|
23
|
+
.yardoc
|
24
|
+
_yardoc
|
25
|
+
doc/
|
data/Gemfile
ADDED
data/README.md
ADDED
data/apngasm-gui.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'apngasm-gui'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.license = 'GNU GPL v3'
|
5
|
+
s.summary = ""
|
6
|
+
s.description = ""
|
7
|
+
s.authors = ['Rika Yoshida', 'Rei Kagetsuki']
|
8
|
+
s.email = 'info@genshin.org'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.homepage = 'https://github.com/apngasm/apngasm-gui'
|
11
|
+
|
12
|
+
s.executables << 'apngasm-gui'
|
13
|
+
|
14
|
+
s.add_dependency 'rapngasm', '~> 3.1', '3.1.2'
|
15
|
+
s.add_dependency 'gtk3'
|
16
|
+
end
|
data/bin/apngasm-gui
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#apngasm GUI by Genshin Souzou Kabushiki Kaisha
|
4
|
+
#licensed under the GNU GPL v3
|
5
|
+
|
6
|
+
require_relative '../lib/apngasm-gui/editor_window.rb'
|
7
|
+
|
8
|
+
class APNGAsmGUIStandalone
|
9
|
+
TITLE = 'apngasm GUI'
|
10
|
+
NAME = 'apngasm-gui'
|
11
|
+
|
12
|
+
def initialize(width = 800, height = 600, file = nil)
|
13
|
+
@editor_window = APNGAsmGUI::EditorWindow.new(width, height)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
APNGAsmGUIStandalone.new
|
data/lib/apngasm-gui.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rapngasm'
|
2
|
+
require 'fileutils'
|
3
|
+
require_relative 'frame_list.rb'
|
4
|
+
require_relative 'frame.rb'
|
5
|
+
|
6
|
+
class APNGAsmGUI::Adapter
|
7
|
+
def initialize
|
8
|
+
@apngasm = APNGAsm.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def import(frame_list, filename)
|
12
|
+
@apngasm.reset
|
13
|
+
apngframes = @apngasm.disassemble(filename)
|
14
|
+
filename = File.basename(filename, '.png')
|
15
|
+
new_frames = []
|
16
|
+
|
17
|
+
apngframes.each_with_index do |apngframe, i|
|
18
|
+
new_frames << APNGAsmGUI::Frame.new("#{filename}_#{i}.png", frame_list, apngframe)
|
19
|
+
end
|
20
|
+
|
21
|
+
new_frames
|
22
|
+
end
|
23
|
+
|
24
|
+
def export(frame_list, filename, frames_status)
|
25
|
+
@apngasm.reset
|
26
|
+
filename = set_filename(filename)
|
27
|
+
|
28
|
+
frame_list.list.each do |frame|
|
29
|
+
if frame.apngframe.nil?
|
30
|
+
@apngasm.add_frame_file(frame.filename, frame.delay)
|
31
|
+
else
|
32
|
+
set_apngframe(frame)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@apngasm.assemble("#{filename}.png")
|
36
|
+
|
37
|
+
save_frames(filename) if frames_status
|
38
|
+
|
39
|
+
GC.start
|
40
|
+
end
|
41
|
+
|
42
|
+
def save_frames(filename)
|
43
|
+
@apngasm.reset
|
44
|
+
@apngasm.disassemble("#{filename}.png")
|
45
|
+
FileUtils.mkdir_p(filename) unless File.exist?(filename)
|
46
|
+
@apngasm.save_pngs(filename)
|
47
|
+
@apngasm.save_json("#{filename}/animation.json", filename)
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_apngframe(frame)
|
51
|
+
filename = "#{File.basename(frame.filename, '.png')}"
|
52
|
+
|
53
|
+
Dir::mktmpdir(nil, File.dirname(__FILE__)) do |dir|
|
54
|
+
frame.apngframe.save("#{dir}/#{filename}.png")
|
55
|
+
@apngasm.add_frame_file("#{dir}/#{filename}.png", frame.delay)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_filename(filename)
|
60
|
+
dirname = File.dirname(filename)
|
61
|
+
basename = File.basename(filename, '.png')
|
62
|
+
new_filename = "#{dirname}/#{basename}"
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,340 @@
|
|
1
|
+
require_relative '../apngasm-gui.rb'
|
2
|
+
require_relative 'frame_list.rb'
|
3
|
+
require_relative 'frame.rb'
|
4
|
+
require_relative 'adapter.rb'
|
5
|
+
|
6
|
+
class APNGAsmGUI::EditorWindow
|
7
|
+
def initialize(width = 800, height = 600)
|
8
|
+
@play = false
|
9
|
+
@loop_status = false
|
10
|
+
@frames_status = false
|
11
|
+
|
12
|
+
@builder = Gtk::Builder.new
|
13
|
+
@builder.add_from_file(File.expand_path('../layout.glade', __FILE__))
|
14
|
+
|
15
|
+
@window_base = @builder['editor_window']
|
16
|
+
@window_base.set_default_size(width, height)
|
17
|
+
|
18
|
+
$preview = @builder['preview_image']
|
19
|
+
|
20
|
+
@frame_hbox = Gtk::Box.new(:horizontal)
|
21
|
+
@frame_list = APNGAsmGUI::FrameList.new(@frame_hbox)
|
22
|
+
|
23
|
+
@scrolled_window = @builder['frame_list_scrolled_window']
|
24
|
+
@scrolled_window.add_with_viewport(@frame_hbox)
|
25
|
+
|
26
|
+
@first_button = @builder['first_button']
|
27
|
+
@first_button.signal_connect('clicked') do
|
28
|
+
move_to_first
|
29
|
+
end
|
30
|
+
|
31
|
+
@back_button = @builder['back_button']
|
32
|
+
@back_button.signal_connect('clicked') do
|
33
|
+
move_to_prev
|
34
|
+
end
|
35
|
+
|
36
|
+
@play_button = @builder['play_button']
|
37
|
+
@play_button.signal_connect('clicked') do
|
38
|
+
if @play
|
39
|
+
stop_animation
|
40
|
+
elsif @frame_list.size > 1
|
41
|
+
play_animation
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
@forward_button = @builder['forward_button']
|
46
|
+
@forward_button.signal_connect('clicked') do
|
47
|
+
move_to_next
|
48
|
+
end
|
49
|
+
|
50
|
+
@last_button = @builder['last_button']
|
51
|
+
@last_button.signal_connect('clicked') do
|
52
|
+
move_to_last
|
53
|
+
end
|
54
|
+
|
55
|
+
@add_frame_button = @builder['add_frame_button']
|
56
|
+
@add_frame_button.signal_connect('clicked') do
|
57
|
+
add_dialog
|
58
|
+
end
|
59
|
+
|
60
|
+
@import_button = @builder['file_chooser']
|
61
|
+
@import_button.add_filter(create_filter)
|
62
|
+
@import_button.signal_connect('file_set') do |response|
|
63
|
+
file_import(File.expand_path(response.filename))
|
64
|
+
end
|
65
|
+
|
66
|
+
@export_button = @builder['export_button']
|
67
|
+
@export_button.signal_connect('clicked') do
|
68
|
+
export_dialog if @frame_list.size > 0
|
69
|
+
end
|
70
|
+
|
71
|
+
@loop_checkbutton = @builder['loop_checkbutton']
|
72
|
+
@loop_checkbutton.signal_connect('toggled') do
|
73
|
+
@loop_status = @loop_checkbutton.active?
|
74
|
+
@play_loop.set_active(@loop_status)
|
75
|
+
end
|
76
|
+
|
77
|
+
@frames_checkbutton = @builder['frames_checkbutton']
|
78
|
+
@frames_checkbutton.signal_connect('toggled') do
|
79
|
+
@frames_status = @frames_checkbutton.active?
|
80
|
+
end
|
81
|
+
|
82
|
+
@file_new = @builder['menu_file_new']
|
83
|
+
@file_new.signal_connect('activate') do
|
84
|
+
label = Gtk::Label.new('New File?')
|
85
|
+
label.show
|
86
|
+
dialog = create_confirm_dialog(label, "new")
|
87
|
+
dialog.destroy
|
88
|
+
end
|
89
|
+
|
90
|
+
@file_import = @builder['menu_file_import']
|
91
|
+
@file_import.signal_connect('activate') do
|
92
|
+
import_dialog
|
93
|
+
end
|
94
|
+
|
95
|
+
@file_export = @builder['menu_file_export']
|
96
|
+
@file_export.signal_connect('activate') do
|
97
|
+
export_dialog if @frame_list.size > 0
|
98
|
+
end
|
99
|
+
|
100
|
+
@file_export_frames = @builder['menu_file_export_frames']
|
101
|
+
@file_export_frames.signal_connect('activate') do
|
102
|
+
@frames_checkbutton.set_active(true)
|
103
|
+
@frames_status = true
|
104
|
+
export_dialog if @frame_list.size > 0
|
105
|
+
end
|
106
|
+
|
107
|
+
@file_quit = @builder['menu_file_quit']
|
108
|
+
@file_quit.signal_connect('activate') do
|
109
|
+
label = Gtk::Label.new('Quit?')
|
110
|
+
label.show
|
111
|
+
dialog = create_confirm_dialog(label, "quit")
|
112
|
+
dialog.destroy
|
113
|
+
end
|
114
|
+
|
115
|
+
@frame_add = @builder['menu_frame_add']
|
116
|
+
@frame_add.signal_connect('activate') do
|
117
|
+
add_dialog
|
118
|
+
end
|
119
|
+
|
120
|
+
@frame_next = @builder['menu_frame_next']
|
121
|
+
@frame_next.signal_connect('activate') do
|
122
|
+
move_to_next
|
123
|
+
end
|
124
|
+
|
125
|
+
@frame_prev = @builder['menu_frame_prev']
|
126
|
+
@frame_prev.signal_connect('activate') do
|
127
|
+
move_to_prev
|
128
|
+
end
|
129
|
+
|
130
|
+
@frame_last = @builder['menu_frame_last']
|
131
|
+
@frame_last.signal_connect('activate') do
|
132
|
+
move_to_last
|
133
|
+
end
|
134
|
+
|
135
|
+
@frame_first = @builder['menu_frame_first']
|
136
|
+
@frame_first.signal_connect('activate') do
|
137
|
+
move_to_first
|
138
|
+
end
|
139
|
+
|
140
|
+
@frame_delete = @builder['menu_frame_delete']
|
141
|
+
@frame_delete.signal_connect('activate') do
|
142
|
+
if @frame_list.size > 1
|
143
|
+
@frame_list.delete_at(@frame_list.cur)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
@play_play = @builder['menu_play_play']
|
148
|
+
@play_play.signal_connect('activate') do
|
149
|
+
if @frame_list.size > 1 && !@play
|
150
|
+
play_animation
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
@play_stop = @builder['menu_play_stop']
|
155
|
+
@play_stop.signal_connect('activate') do
|
156
|
+
stop_animation if @play
|
157
|
+
end
|
158
|
+
|
159
|
+
@play_loop = @builder['menu_play_loop']
|
160
|
+
@play_loop.set_active(@loop_status)
|
161
|
+
@play_loop.signal_connect('toggled') do
|
162
|
+
@loop_status = @play_loop.active?
|
163
|
+
@loop_checkbutton.set_active(@loop_status)
|
164
|
+
end
|
165
|
+
|
166
|
+
@help_about = @builder['menu_help_about']
|
167
|
+
@help_about.signal_connect('activate') do
|
168
|
+
help_dialog
|
169
|
+
end
|
170
|
+
|
171
|
+
@window_base.signal_connect('destroy') do
|
172
|
+
Gtk.main_quit
|
173
|
+
end
|
174
|
+
|
175
|
+
@window_base.show_all
|
176
|
+
Gtk.main
|
177
|
+
end
|
178
|
+
|
179
|
+
def move_to_next
|
180
|
+
if @frame_list.cur < @frame_list.size - 1
|
181
|
+
swap_frame(@frame_list.cur, @frame_list.cur + 1)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def move_to_prev
|
186
|
+
if @frame_list.cur != 0
|
187
|
+
swap_frame(@frame_list.cur, @frame_list.cur - 1)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def move_to_last
|
192
|
+
if @frame_list.size > 1
|
193
|
+
swap_frame(@frame_list.cur, @frame_list.size - 1)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def move_to_first
|
198
|
+
if @frame_list.size > 1
|
199
|
+
swap_frame(@frame_list.cur, 0)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def add_dialog
|
204
|
+
dialog = create_dialog('Open File', Gtk::FileChooser::Action::OPEN, Gtk::Stock::OPEN)
|
205
|
+
dialog.set_select_multiple(true)
|
206
|
+
dialog.add_filter(create_filter)
|
207
|
+
|
208
|
+
if dialog.run == Gtk::ResponseType::ACCEPT
|
209
|
+
dialog.filenames.each do |filename|
|
210
|
+
create_frame(File.expand_path(filename))
|
211
|
+
end
|
212
|
+
@window_base.show_all
|
213
|
+
end
|
214
|
+
|
215
|
+
dialog.destroy
|
216
|
+
end
|
217
|
+
|
218
|
+
def import_dialog
|
219
|
+
dialog = create_dialog('Import File', Gtk::FileChooser::Action::OPEN, Gtk::Stock::OPEN)
|
220
|
+
dialog.add_filter(create_filter)
|
221
|
+
|
222
|
+
if dialog.run == Gtk::ResponseType::ACCEPT
|
223
|
+
file_import(File.expand_path(dialog.filename))
|
224
|
+
@import_button.filename = dialog.filename
|
225
|
+
end
|
226
|
+
|
227
|
+
dialog.destroy
|
228
|
+
end
|
229
|
+
|
230
|
+
def export_dialog
|
231
|
+
dialog = create_dialog('Save File', Gtk::FileChooser::Action::SAVE, Gtk::Stock::SAVE)
|
232
|
+
dialog.do_overwrite_confirmation = true
|
233
|
+
|
234
|
+
if dialog.run == Gtk::ResponseType::ACCEPT
|
235
|
+
file_export(File.expand_path(dialog.filename))
|
236
|
+
end
|
237
|
+
|
238
|
+
dialog.destroy
|
239
|
+
end
|
240
|
+
|
241
|
+
def help_dialog
|
242
|
+
# TODO dialog message
|
243
|
+
dialog = Gtk::MessageDialog.new(message: 'apngasm-gui is a software to create an APNG file.',
|
244
|
+
parent: @window_base)
|
245
|
+
dialog.run
|
246
|
+
dialog.destroy
|
247
|
+
end
|
248
|
+
|
249
|
+
def create_dialog(title, action, stock)
|
250
|
+
Gtk::FileChooserDialog.new(title: title,
|
251
|
+
parent: @window_base,
|
252
|
+
action: action,
|
253
|
+
buttons: [[Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL],
|
254
|
+
[stock, Gtk::ResponseType::ACCEPT]])
|
255
|
+
end
|
256
|
+
|
257
|
+
def create_filter
|
258
|
+
filter = Gtk::FileFilter.new
|
259
|
+
filter.name = 'PNG File'
|
260
|
+
filter.add_pattern('*.png')
|
261
|
+
filter
|
262
|
+
end
|
263
|
+
|
264
|
+
def create_confirm_dialog(title, mode)
|
265
|
+
dialog = Gtk::Dialog.new
|
266
|
+
dialog.child.pack_start(title, expand: true, fill: true, padding: 30)
|
267
|
+
dialog.add_buttons(['Yes', Gtk::ResponseType::YES], ['No', Gtk::ResponseType::NO])
|
268
|
+
|
269
|
+
if dialog.run == Gtk::ResponseType::YES
|
270
|
+
@import_button.filename = 'blank'
|
271
|
+
@frame_list.delete_all if mode == 'new'
|
272
|
+
Gtk.main_quit if mode == 'quit'
|
273
|
+
end
|
274
|
+
|
275
|
+
dialog
|
276
|
+
end
|
277
|
+
|
278
|
+
def create_frame(filename)
|
279
|
+
frame = APNGAsmGUI::Frame.new(filename, @frame_list)
|
280
|
+
@frame_list << frame
|
281
|
+
$preview.set_pixbuf(frame.pixbuf)
|
282
|
+
@frame_list.frame_hbox.pack_start(frame, expand: false, fill: false, padding: 10)
|
283
|
+
end
|
284
|
+
|
285
|
+
def swap_frame(old_position, new_position)
|
286
|
+
@frame_list.swap(old_position, new_position)
|
287
|
+
@frame_list.cur = new_position
|
288
|
+
$preview.set_pixbuf(@frame_list.pixbuf(@frame_list.cur))
|
289
|
+
view_reload
|
290
|
+
end
|
291
|
+
|
292
|
+
def view_reload
|
293
|
+
@frame_list.view_reload
|
294
|
+
@window_base.show_all
|
295
|
+
end
|
296
|
+
|
297
|
+
def play_animation
|
298
|
+
@play = true
|
299
|
+
image = Gtk::Image.new(stock: Gtk::Stock::MEDIA_STOP, size: Gtk::IconSize::IconSize::BUTTON)
|
300
|
+
@play_button.set_image(image)
|
301
|
+
|
302
|
+
@frame_list.cur = 0
|
303
|
+
@handle = GLib::Idle.add {
|
304
|
+
unless @loop_status
|
305
|
+
stop_animation if @frame_list.cur == @frame_list.size - 1
|
306
|
+
end
|
307
|
+
|
308
|
+
$preview.set_pixbuf(@frame_list.pixbuf(@frame_list.cur))
|
309
|
+
@frame_list.cur - 1 < 0 ? delay_num = @frame_list.size - 1 : delay_num = @frame_list.cur - 1
|
310
|
+
sleep(@frame_list.delay(delay_num) * 0.001)
|
311
|
+
@frame_list.cur + 1 >= @frame_list.size ? @frame_list.cur = 0 : @frame_list.cur += 1
|
312
|
+
}
|
313
|
+
end
|
314
|
+
|
315
|
+
def stop_animation
|
316
|
+
GLib::Source.remove(@handle)
|
317
|
+
|
318
|
+
@play = false
|
319
|
+
image = Gtk::Image.new(stock: Gtk::Stock::MEDIA_PLAY, size: Gtk::IconSize::IconSize::BUTTON)
|
320
|
+
@play_button.set_image(image)
|
321
|
+
end
|
322
|
+
|
323
|
+
def file_import(filename)
|
324
|
+
adapter = APNGAsmGUI::Adapter.new
|
325
|
+
new_frames = adapter.import(@frame_list, filename)
|
326
|
+
|
327
|
+
new_frames.each do |frame|
|
328
|
+
@frame_list << frame
|
329
|
+
@frame_list.frame_hbox.pack_start(frame, expand: false, fill: false, padding: 10)
|
330
|
+
end
|
331
|
+
|
332
|
+
$preview.set_pixbuf(@frame_list.pixbuf(@frame_list.cur)) if @frame_list.size > 0
|
333
|
+
@window_base.show_all
|
334
|
+
end
|
335
|
+
|
336
|
+
def file_export(filename)
|
337
|
+
adapter = APNGAsmGUI::Adapter.new
|
338
|
+
adapter.export(@frame_list, filename, @frames_status)
|
339
|
+
end
|
340
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'gtk3'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
class APNGAsmGUI::Frame < Gtk::Frame
|
5
|
+
THUMBNAIL_SIZE = 100
|
6
|
+
attr_accessor :filename, :pixbuf, :apngframe
|
7
|
+
|
8
|
+
def initialize(filename, parent, apngframe = nil)
|
9
|
+
super()
|
10
|
+
@filename = filename
|
11
|
+
@parent = parent
|
12
|
+
@apngframe = apngframe
|
13
|
+
|
14
|
+
if @apngframe.nil?
|
15
|
+
image = Gtk::Image.new(file: @filename)
|
16
|
+
else
|
17
|
+
Dir::mktmpdir(nil, File.dirname(__FILE__)) do |dir|
|
18
|
+
@apngframe.save("#{dir}/#{@filename}")
|
19
|
+
image = Gtk::Image.new(file: "#{dir}/#{@filename}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if image.pixbuf != nil
|
24
|
+
if image.pixbuf.width > THUMBNAIL_SIZE || image.pixbuf.height > THUMBNAIL_SIZE
|
25
|
+
image.pixbuf = resize(image.pixbuf, THUMBNAIL_SIZE)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@pixbuf = image.pixbuf
|
29
|
+
|
30
|
+
image_button = Gtk::Button.new
|
31
|
+
image_button.set_relief(Gtk::ReliefStyle::NONE)
|
32
|
+
image_button.add(image)
|
33
|
+
image_button.signal_connect('clicked') do
|
34
|
+
@parent.focus(self)
|
35
|
+
end
|
36
|
+
|
37
|
+
box = Gtk::Box.new(:vertical)
|
38
|
+
box.pack_start(image_button, expand: true, fill: false, padding: 10)
|
39
|
+
|
40
|
+
adjustment = Gtk::Adjustment.new(100, 1, 999, 1, 1, 0)
|
41
|
+
@delay_spinner = Gtk::SpinButton.new(adjustment, 1, 0)
|
42
|
+
set_delay(@apngframe.nil? ? 100 : @apngframe.delay_numerator)
|
43
|
+
box.pack_start(@delay_spinner, expand: false, fill: false)
|
44
|
+
|
45
|
+
delete_button = Gtk::Button.new(label: 'Delete')
|
46
|
+
delete_button.signal_connect('clicked') do
|
47
|
+
@parent.delete(self)
|
48
|
+
end
|
49
|
+
box.pack_start(delete_button, expand: false, fill: false)
|
50
|
+
|
51
|
+
add(box)
|
52
|
+
end
|
53
|
+
|
54
|
+
def resize(pixbuf, size)
|
55
|
+
if pixbuf.width >= pixbuf.height
|
56
|
+
scale = pixbuf.height.to_f / pixbuf.width.to_f
|
57
|
+
pixbuf = pixbuf.scale(size, size * scale, Gdk::Pixbuf::INTERP_BILINEAR)
|
58
|
+
else
|
59
|
+
scale = pixbuf.width.to_f / pixbuf.height.to_f
|
60
|
+
pixbuf = pixbuf.scale(size * scale, size, Gdk::Pixbuf::INTERP_BILINEAR)
|
61
|
+
end
|
62
|
+
pixbuf
|
63
|
+
end
|
64
|
+
|
65
|
+
def delay
|
66
|
+
@delay_spinner.value
|
67
|
+
end
|
68
|
+
|
69
|
+
def set_delay(value)
|
70
|
+
@delay_spinner.set_value(value)
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'gtk3'
|
2
|
+
|
3
|
+
class APNGAsmGUI::FrameList
|
4
|
+
attr_accessor :frame_hbox, :cur, :list
|
5
|
+
|
6
|
+
def initialize(frame_hbox)
|
7
|
+
@frame_hbox = frame_hbox
|
8
|
+
@list = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(data)
|
12
|
+
@list << data
|
13
|
+
@cur = @list.size - 1
|
14
|
+
end
|
15
|
+
|
16
|
+
def size
|
17
|
+
@list.size
|
18
|
+
end
|
19
|
+
|
20
|
+
def filename(position = nil)
|
21
|
+
return @list[@cur].filename if position.nil?
|
22
|
+
return nil if position > @list.size
|
23
|
+
return @list[position].filename
|
24
|
+
end
|
25
|
+
|
26
|
+
def pixbuf(position = nil)
|
27
|
+
return @list[@cur].pixbuf if position.nil?
|
28
|
+
return nil if position > @list.size
|
29
|
+
return @list[position].pixbuf
|
30
|
+
end
|
31
|
+
|
32
|
+
def delay(position = nil)
|
33
|
+
return @list[@cur].delay if position.nil?
|
34
|
+
return nil if position > @list.size
|
35
|
+
return @list[position].delay
|
36
|
+
end
|
37
|
+
|
38
|
+
def swap(old_position, new_position)
|
39
|
+
case new_position
|
40
|
+
when 0 then
|
41
|
+
@list.insert(0, @list[old_position])
|
42
|
+
@list.delete_at(old_position + 1)
|
43
|
+
when @list.size - 1 then
|
44
|
+
@list << @list[old_position]
|
45
|
+
@list.delete_at(old_position)
|
46
|
+
else
|
47
|
+
@list[old_position], @list[new_position] = @list[new_position], @list[old_position]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def delete(child)
|
52
|
+
@list.delete(child)
|
53
|
+
@frame_hbox.remove(child)
|
54
|
+
@cur -= 1 unless @cur == 0
|
55
|
+
if @list.size == 0
|
56
|
+
$preview.set_stock(Gtk::Stock::MISSING_IMAGE)
|
57
|
+
else
|
58
|
+
$preview.set_pixbuf(@list[@cur].pixbuf)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete_at(index)
|
63
|
+
child = @list[index]
|
64
|
+
delete(child)
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete_all
|
68
|
+
for i in 0..@list.size do
|
69
|
+
child = @list[0]
|
70
|
+
@list.delete(child)
|
71
|
+
@frame_hbox.remove(child)
|
72
|
+
end
|
73
|
+
@cur == 0
|
74
|
+
$preview.set_stock(Gtk::Stock::MISSING_IMAGE)
|
75
|
+
end
|
76
|
+
|
77
|
+
def focus(child)
|
78
|
+
@cur = @list.find_index(child)
|
79
|
+
$preview.set_pixbuf(@list[@cur].pixbuf)
|
80
|
+
end
|
81
|
+
|
82
|
+
def view_reload
|
83
|
+
@list.each { |frame| @frame_hbox.remove(frame) }
|
84
|
+
@list.each do |frame|
|
85
|
+
@frame_hbox.pack_start(frame, expand: false, fill: false, padding: 10)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,557 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<interface>
|
3
|
+
<!-- interface-requires gtk+ 3.0 -->
|
4
|
+
<object class="GtkImage" id="export_button_image">
|
5
|
+
<property name="visible">True</property>
|
6
|
+
<property name="can_focus">False</property>
|
7
|
+
<property name="stock">gtk-save-as</property>
|
8
|
+
</object>
|
9
|
+
<object class="GtkWindow" id="editor_window">
|
10
|
+
<property name="can_focus">False</property>
|
11
|
+
<child>
|
12
|
+
<object class="GtkVBox" id="vbox_base">
|
13
|
+
<property name="visible">True</property>
|
14
|
+
<property name="can_focus">False</property>
|
15
|
+
<child>
|
16
|
+
<object class="GtkMenuBar" id="menubar">
|
17
|
+
<property name="visible">True</property>
|
18
|
+
<property name="can_focus">False</property>
|
19
|
+
<child>
|
20
|
+
<object class="GtkMenuItem" id="menuitem_file">
|
21
|
+
<property name="visible">True</property>
|
22
|
+
<property name="can_focus">False</property>
|
23
|
+
<property name="label" translatable="yes">_File</property>
|
24
|
+
<property name="use_underline">True</property>
|
25
|
+
<child type="submenu">
|
26
|
+
<object class="GtkMenu" id="menu_file">
|
27
|
+
<property name="visible">True</property>
|
28
|
+
<property name="can_focus">False</property>
|
29
|
+
<child>
|
30
|
+
<object class="GtkImageMenuItem" id="menu_file_new">
|
31
|
+
<property name="label">gtk-new</property>
|
32
|
+
<property name="visible">True</property>
|
33
|
+
<property name="can_focus">False</property>
|
34
|
+
<property name="use_underline">True</property>
|
35
|
+
<property name="use_stock">True</property>
|
36
|
+
</object>
|
37
|
+
</child>
|
38
|
+
<child>
|
39
|
+
<object class="GtkImageMenuItem" id="menu_file_import">
|
40
|
+
<property name="label">Import</property>
|
41
|
+
<property name="visible">True</property>
|
42
|
+
<property name="can_focus">False</property>
|
43
|
+
<property name="use_underline">True</property>
|
44
|
+
<property name="use_stock">True</property>
|
45
|
+
</object>
|
46
|
+
</child>
|
47
|
+
<child>
|
48
|
+
<object class="GtkImageMenuItem" id="menu_file_export">
|
49
|
+
<property name="label">Export</property>
|
50
|
+
<property name="visible">True</property>
|
51
|
+
<property name="can_focus">False</property>
|
52
|
+
<property name="use_underline">True</property>
|
53
|
+
<property name="use_stock">True</property>
|
54
|
+
</object>
|
55
|
+
</child>
|
56
|
+
<child>
|
57
|
+
<object class="GtkImageMenuItem" id="menu_file_export_frames">
|
58
|
+
<property name="label">Export with frames</property>
|
59
|
+
<property name="visible">True</property>
|
60
|
+
<property name="can_focus">False</property>
|
61
|
+
<property name="use_underline">True</property>
|
62
|
+
<property name="use_stock">True</property>
|
63
|
+
</object>
|
64
|
+
</child>
|
65
|
+
<child>
|
66
|
+
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
|
67
|
+
<property name="visible">True</property>
|
68
|
+
<property name="can_focus">False</property>
|
69
|
+
</object>
|
70
|
+
</child>
|
71
|
+
<child>
|
72
|
+
<object class="GtkImageMenuItem" id="menu_file_quit">
|
73
|
+
<property name="label">gtk-quit</property>
|
74
|
+
<property name="visible">True</property>
|
75
|
+
<property name="can_focus">False</property>
|
76
|
+
<property name="use_underline">True</property>
|
77
|
+
<property name="use_stock">True</property>
|
78
|
+
</object>
|
79
|
+
</child>
|
80
|
+
</object>
|
81
|
+
</child>
|
82
|
+
</object>
|
83
|
+
</child>
|
84
|
+
<child>
|
85
|
+
<object class="GtkMenuItem" id="menuitem_frame">
|
86
|
+
<property name="visible">True</property>
|
87
|
+
<property name="can_focus">False</property>
|
88
|
+
<property name="label" translatable="yes">_Frame</property>
|
89
|
+
<property name="use_underline">True</property>
|
90
|
+
<child type="submenu">
|
91
|
+
<object class="GtkMenu" id="menu_frame">
|
92
|
+
<property name="visible">True</property>
|
93
|
+
<property name="can_focus">False</property>
|
94
|
+
<child>
|
95
|
+
<object class="GtkImageMenuItem" id="menu_frame_add">
|
96
|
+
<property name="label">Add frame</property>
|
97
|
+
<property name="visible">True</property>
|
98
|
+
<property name="can_focus">False</property>
|
99
|
+
<property name="use_underline">True</property>
|
100
|
+
<property name="use_stock">True</property>
|
101
|
+
</object>
|
102
|
+
</child>
|
103
|
+
<child>
|
104
|
+
<object class="GtkImageMenuItem" id="menu_frame_next">
|
105
|
+
<property name="label">Move to next</property>
|
106
|
+
<property name="visible">True</property>
|
107
|
+
<property name="can_focus">False</property>
|
108
|
+
<property name="use_underline">True</property>
|
109
|
+
<property name="use_stock">True</property>
|
110
|
+
</object>
|
111
|
+
</child>
|
112
|
+
<child>
|
113
|
+
<object class="GtkImageMenuItem" id="menu_frame_prev">
|
114
|
+
<property name="label">Move to prev</property>
|
115
|
+
<property name="visible">True</property>
|
116
|
+
<property name="can_focus">False</property>
|
117
|
+
<property name="use_underline">True</property>
|
118
|
+
<property name="use_stock">True</property>
|
119
|
+
</object>
|
120
|
+
</child>
|
121
|
+
<child>
|
122
|
+
<object class="GtkImageMenuItem" id="menu_frame_last">
|
123
|
+
<property name="label">Move to last</property>
|
124
|
+
<property name="visible">True</property>
|
125
|
+
<property name="can_focus">False</property>
|
126
|
+
<property name="use_underline">True</property>
|
127
|
+
<property name="use_stock">True</property>
|
128
|
+
</object>
|
129
|
+
</child>
|
130
|
+
<child>
|
131
|
+
<object class="GtkImageMenuItem" id="menu_frame_first">
|
132
|
+
<property name="label">Move to first</property>
|
133
|
+
<property name="visible">True</property>
|
134
|
+
<property name="can_focus">False</property>
|
135
|
+
<property name="use_underline">True</property>
|
136
|
+
<property name="use_stock">True</property>
|
137
|
+
</object>
|
138
|
+
</child>
|
139
|
+
<child>
|
140
|
+
<object class="GtkImageMenuItem" id="menu_frame_delete">
|
141
|
+
<property name="label">Delete frame</property>
|
142
|
+
<property name="visible">True</property>
|
143
|
+
<property name="can_focus">False</property>
|
144
|
+
<property name="use_underline">True</property>
|
145
|
+
<property name="use_stock">True</property>
|
146
|
+
</object>
|
147
|
+
</child>
|
148
|
+
</object>
|
149
|
+
</child>
|
150
|
+
</object>
|
151
|
+
</child>
|
152
|
+
<child>
|
153
|
+
<object class="GtkMenuItem" id="menuitem_play">
|
154
|
+
<property name="visible">True</property>
|
155
|
+
<property name="can_focus">False</property>
|
156
|
+
<property name="label" translatable="yes">_Play</property>
|
157
|
+
<property name="use_underline">True</property>
|
158
|
+
<child type="submenu">
|
159
|
+
<object class="GtkMenu" id="menu_play">
|
160
|
+
<property name="visible">True</property>
|
161
|
+
<property name="can_focus">False</property>
|
162
|
+
<child>
|
163
|
+
<object class="GtkImageMenuItem" id="menu_play_play">
|
164
|
+
<property name="label">Play</property>
|
165
|
+
<property name="visible">True</property>
|
166
|
+
<property name="can_focus">False</property>
|
167
|
+
<property name="use_underline">True</property>
|
168
|
+
<property name="use_stock">True</property>
|
169
|
+
</object>
|
170
|
+
</child>
|
171
|
+
<child>
|
172
|
+
<object class="GtkImageMenuItem" id="menu_play_stop">
|
173
|
+
<property name="label">Stop</property>
|
174
|
+
<property name="visible">True</property>
|
175
|
+
<property name="can_focus">False</property>
|
176
|
+
<property name="use_underline">True</property>
|
177
|
+
<property name="use_stock">True</property>
|
178
|
+
</object>
|
179
|
+
</child>
|
180
|
+
<child>
|
181
|
+
<object class="GtkCheckMenuItem" id="menu_play_loop">
|
182
|
+
<property name="label">Loop</property>
|
183
|
+
<property name="visible">True</property>
|
184
|
+
<property name="can_focus">True</property>
|
185
|
+
<property name="use_underline">True</property>
|
186
|
+
<property name="use_stock">True</property>
|
187
|
+
</object>
|
188
|
+
</child>
|
189
|
+
</object>
|
190
|
+
</child>
|
191
|
+
</object>
|
192
|
+
</child>
|
193
|
+
<child>
|
194
|
+
<object class="GtkMenuItem" id="menuitem_help">
|
195
|
+
<property name="visible">True</property>
|
196
|
+
<property name="can_focus">False</property>
|
197
|
+
<property name="label" translatable="yes">_Help</property>
|
198
|
+
<property name="use_underline">True</property>
|
199
|
+
<child type="submenu">
|
200
|
+
<object class="GtkMenu" id="menu_help">
|
201
|
+
<property name="visible">True</property>
|
202
|
+
<property name="can_focus">False</property>
|
203
|
+
<child>
|
204
|
+
<object class="GtkImageMenuItem" id="menu_help_about">
|
205
|
+
<property name="label">gtk-about</property>
|
206
|
+
<property name="visible">True</property>
|
207
|
+
<property name="can_focus">False</property>
|
208
|
+
<property name="use_underline">True</property>
|
209
|
+
<property name="use_stock">True</property>
|
210
|
+
</object>
|
211
|
+
</child>
|
212
|
+
</object>
|
213
|
+
</child>
|
214
|
+
</object>
|
215
|
+
</child>
|
216
|
+
</object>
|
217
|
+
<packing>
|
218
|
+
<property name="expand">False</property>
|
219
|
+
<property name="fill">True</property>
|
220
|
+
<property name="position">0</property>
|
221
|
+
</packing>
|
222
|
+
</child>
|
223
|
+
<child>
|
224
|
+
<object class="GtkHBox" id="hbox_top">
|
225
|
+
<property name="visible">True</property>
|
226
|
+
<property name="can_focus">False</property>
|
227
|
+
<property name="spacing">10</property>
|
228
|
+
<child>
|
229
|
+
<object class="GtkVBox" id="view_vbox">
|
230
|
+
<property name="visible">True</property>
|
231
|
+
<property name="can_focus">False</property>
|
232
|
+
<property name="spacing">10</property>
|
233
|
+
<child>
|
234
|
+
<object class="GtkScrolledWindow" id="viewport_scrolledwindow">
|
235
|
+
<property name="visible">True</property>
|
236
|
+
<property name="can_focus">false</property>
|
237
|
+
<property name="hscrollbar_policy">automatic</property>
|
238
|
+
<property name="vscrollbar_policy">automatic</property>
|
239
|
+
<child>
|
240
|
+
<object class="GtkViewport" id="viewport_preview">
|
241
|
+
<property name="visible">True</property>
|
242
|
+
<property name="can_focus">False</property>
|
243
|
+
<property name="resize_mode">queue</property>
|
244
|
+
<child>
|
245
|
+
<object class="GtkImage" id="preview_image">
|
246
|
+
<property name="visible">True</property>
|
247
|
+
<property name="can_focus">False</property>
|
248
|
+
<property name="xpad">10</property>
|
249
|
+
<property name="ypad">10</property>
|
250
|
+
<property name="stock">gtk-missing-image</property>
|
251
|
+
</object>
|
252
|
+
</child>
|
253
|
+
</object>
|
254
|
+
</child>
|
255
|
+
</object>
|
256
|
+
<packing>
|
257
|
+
<property name="expand">True</property>
|
258
|
+
<property name="fill">True</property>
|
259
|
+
<property name="position">0</property>
|
260
|
+
</packing>
|
261
|
+
</child>
|
262
|
+
<child>
|
263
|
+
<object class="GtkHBox" id="play_hbox">
|
264
|
+
<property name="visible">True</property>
|
265
|
+
<property name="can_focus">False</property>
|
266
|
+
<child>
|
267
|
+
<object class="GtkButton" id="first_button">
|
268
|
+
<property name="visible">True</property>
|
269
|
+
<property name="can_focus">True</property>
|
270
|
+
<property name="receives_default">True</property>
|
271
|
+
<property name="image">first_img</property>
|
272
|
+
</object>
|
273
|
+
<packing>
|
274
|
+
<property name="expand">True</property>
|
275
|
+
<property name="fill">True</property>
|
276
|
+
<property name="position">0</property>
|
277
|
+
</packing>
|
278
|
+
</child>
|
279
|
+
<child>
|
280
|
+
<object class="GtkButton" id="back_button">
|
281
|
+
<property name="visible">True</property>
|
282
|
+
<property name="can_focus">True</property>
|
283
|
+
<property name="receives_default">True</property>
|
284
|
+
<property name="image">previous_img</property>
|
285
|
+
</object>
|
286
|
+
<packing>
|
287
|
+
<property name="expand">True</property>
|
288
|
+
<property name="fill">True</property>
|
289
|
+
<property name="position">1</property>
|
290
|
+
</packing>
|
291
|
+
</child>
|
292
|
+
<child>
|
293
|
+
<object class="GtkButton" id="play_button">
|
294
|
+
<property name="visible">True</property>
|
295
|
+
<property name="can_focus">True</property>
|
296
|
+
<property name="receives_default">True</property>
|
297
|
+
<property name="image">play_img</property>
|
298
|
+
</object>
|
299
|
+
<packing>
|
300
|
+
<property name="expand">True</property>
|
301
|
+
<property name="fill">True</property>
|
302
|
+
<property name="position">2</property>
|
303
|
+
</packing>
|
304
|
+
</child>
|
305
|
+
<child>
|
306
|
+
<object class="GtkButton" id="forward_button">
|
307
|
+
<property name="visible">True</property>
|
308
|
+
<property name="can_focus">True</property>
|
309
|
+
<property name="receives_default">True</property>
|
310
|
+
<property name="image">next_img</property>
|
311
|
+
</object>
|
312
|
+
<packing>
|
313
|
+
<property name="expand">True</property>
|
314
|
+
<property name="fill">True</property>
|
315
|
+
<property name="position">3</property>
|
316
|
+
</packing>
|
317
|
+
</child>
|
318
|
+
<child>
|
319
|
+
<object class="GtkButton" id="last_button">
|
320
|
+
<property name="visible">True</property>
|
321
|
+
<property name="can_focus">True</property>
|
322
|
+
<property name="receives_default">True</property>
|
323
|
+
<property name="image">last_img</property>
|
324
|
+
</object>
|
325
|
+
<packing>
|
326
|
+
<property name="expand">True</property>
|
327
|
+
<property name="fill">True</property>
|
328
|
+
<property name="position">4</property>
|
329
|
+
</packing>
|
330
|
+
</child>
|
331
|
+
<child>
|
332
|
+
<object class="GtkButton" id="add_frame_button">
|
333
|
+
<property name="label">gtk-add</property>
|
334
|
+
<property name="visible">True</property>
|
335
|
+
<property name="can_focus">False</property>
|
336
|
+
<property name="receives_default">True</property>
|
337
|
+
<property name="use_stock">True</property>
|
338
|
+
</object>
|
339
|
+
<packing>
|
340
|
+
<property name="expand">True</property>
|
341
|
+
<property name="fill">True</property>
|
342
|
+
<property name="position">5</property>
|
343
|
+
</packing>
|
344
|
+
</child>
|
345
|
+
</object>
|
346
|
+
<packing>
|
347
|
+
<property name="expand">False</property>
|
348
|
+
<property name="fill">False</property>
|
349
|
+
<property name="position">1</property>
|
350
|
+
</packing>
|
351
|
+
</child>
|
352
|
+
</object>
|
353
|
+
<packing>
|
354
|
+
<property name="expand">True</property>
|
355
|
+
<property name="fill">True</property>
|
356
|
+
<property name="padding">10</property>
|
357
|
+
<property name="position">0</property>
|
358
|
+
</packing>
|
359
|
+
</child>
|
360
|
+
</object>
|
361
|
+
<packing>
|
362
|
+
<property name="expand">True</property>
|
363
|
+
<property name="fill">True</property>
|
364
|
+
<property name="padding">10</property>
|
365
|
+
<property name="position">1</property>
|
366
|
+
</packing>
|
367
|
+
</child>
|
368
|
+
<child>
|
369
|
+
<object class="GtkScrolledWindow" id="frame_list_scrolled_window">
|
370
|
+
<property name="visible">True</property>
|
371
|
+
<property name="can_focus">False</property>
|
372
|
+
<property name="min_content_height">200</property>
|
373
|
+
<child>
|
374
|
+
<placeholder/>
|
375
|
+
</child>
|
376
|
+
</object>
|
377
|
+
<packing>
|
378
|
+
<property name="expand">False</property>
|
379
|
+
<property name="fill">True</property>
|
380
|
+
<property name="position">2</property>
|
381
|
+
</packing>
|
382
|
+
</child>
|
383
|
+
<child>
|
384
|
+
<object class="GtkHBox" id="export_box">
|
385
|
+
<property name="can_focus">False</property>
|
386
|
+
<child>
|
387
|
+
<object class="GtkFileChooserButton" id="file_chooser">
|
388
|
+
<property name="can_focus">False</property>
|
389
|
+
</object>
|
390
|
+
<packing>
|
391
|
+
<property name="expand">True</property>
|
392
|
+
<property name="fill">True</property>
|
393
|
+
<property name="position">1</property>
|
394
|
+
</packing>
|
395
|
+
</child>
|
396
|
+
<child>
|
397
|
+
<object class="GtkButton" id="export_button">
|
398
|
+
<property name="can_focus">False</property>
|
399
|
+
<property name="receives_default">True</property>
|
400
|
+
<property name="image">export_button_image</property>
|
401
|
+
</object>
|
402
|
+
<packing>
|
403
|
+
<property name="expand">False</property>
|
404
|
+
<property name="fill">True</property>
|
405
|
+
<property name="position">3</property>
|
406
|
+
</packing>
|
407
|
+
</child>
|
408
|
+
<child>
|
409
|
+
<object class="GtkCheckButton" id="loop_checkbutton">
|
410
|
+
<property name="label" translatable="yes">Loop</property>
|
411
|
+
<property name="visible">True</property>
|
412
|
+
<property name="can_focus">True</property>
|
413
|
+
<property name="receives_default">False</property>
|
414
|
+
<property name="xalign">0</property>
|
415
|
+
<property name="draw_indicator">True</property>
|
416
|
+
</object>
|
417
|
+
<packing>
|
418
|
+
<property name="expand">False</property>
|
419
|
+
<property name="fill">False</property>
|
420
|
+
<property name="padding">10</property>
|
421
|
+
<property name="position">4</property>
|
422
|
+
</packing>
|
423
|
+
</child>
|
424
|
+
<child>
|
425
|
+
<object class="GtkCheckButton" id="frames_checkbutton">
|
426
|
+
<property name="label" translatable="yes">Frames</property>
|
427
|
+
<property name="visible">True</property>
|
428
|
+
<property name="can_focus">False</property>
|
429
|
+
<property name="receives_default">False</property>
|
430
|
+
<property name="xalign">0</property>
|
431
|
+
<property name="draw_indicator">True</property>
|
432
|
+
</object>
|
433
|
+
<packing>
|
434
|
+
<property name="expand">False</property>
|
435
|
+
<property name="fill">True</property>
|
436
|
+
<property name="position">5</property>
|
437
|
+
</packing>
|
438
|
+
</child>
|
439
|
+
</object>
|
440
|
+
<packing>
|
441
|
+
<property name="expand">False</property>
|
442
|
+
<property name="fill">True</property>
|
443
|
+
<property name="position">3</property>
|
444
|
+
</packing>
|
445
|
+
</child>
|
446
|
+
</object>
|
447
|
+
</child>
|
448
|
+
</object>
|
449
|
+
<object class="GtkImage" id="first_img">
|
450
|
+
<property name="visible">True</property>
|
451
|
+
<property name="can_focus">False</property>
|
452
|
+
<property name="stock">gtk-goto-first</property>
|
453
|
+
</object>
|
454
|
+
<object class="GtkWindow" id="frame_window">
|
455
|
+
<property name="can_focus">False</property>
|
456
|
+
<child>
|
457
|
+
<object class="GtkBox" id="box1">
|
458
|
+
<property name="visible">True</property>
|
459
|
+
<property name="can_focus">False</property>
|
460
|
+
<property name="orientation">vertical</property>
|
461
|
+
<child>
|
462
|
+
<object class="GtkImage" id="frame_image">
|
463
|
+
<property name="visible">True</property>
|
464
|
+
<property name="can_focus">False</property>
|
465
|
+
<property name="stock">gtk-missing-image</property>
|
466
|
+
</object>
|
467
|
+
<packing>
|
468
|
+
<property name="expand">True</property>
|
469
|
+
<property name="fill">True</property>
|
470
|
+
<property name="position">0</property>
|
471
|
+
</packing>
|
472
|
+
</child>
|
473
|
+
<child>
|
474
|
+
<object class="GtkBox" id="box2">
|
475
|
+
<property name="visible">True</property>
|
476
|
+
<property name="can_focus">False</property>
|
477
|
+
<child>
|
478
|
+
<object class="GtkLabel" id="label1">
|
479
|
+
<property name="visible">True</property>
|
480
|
+
<property name="can_focus">False</property>
|
481
|
+
<property name="label" translatable="yes">Delay</property>
|
482
|
+
</object>
|
483
|
+
<packing>
|
484
|
+
<property name="expand">False</property>
|
485
|
+
<property name="fill">True</property>
|
486
|
+
<property name="position">0</property>
|
487
|
+
</packing>
|
488
|
+
</child>
|
489
|
+
<child>
|
490
|
+
<object class="GtkSpinButton" id="spinbutton1">
|
491
|
+
<property name="visible">True</property>
|
492
|
+
<property name="can_focus">False</property>
|
493
|
+
<property name="invisible_char">•</property>
|
494
|
+
</object>
|
495
|
+
<packing>
|
496
|
+
<property name="expand">True</property>
|
497
|
+
<property name="fill">True</property>
|
498
|
+
<property name="position">1</property>
|
499
|
+
</packing>
|
500
|
+
</child>
|
501
|
+
<child>
|
502
|
+
<object class="GtkLabel" id="label2">
|
503
|
+
<property name="visible">True</property>
|
504
|
+
<property name="can_focus">False</property>
|
505
|
+
<property name="label" translatable="yes">ms</property>
|
506
|
+
</object>
|
507
|
+
<packing>
|
508
|
+
<property name="expand">False</property>
|
509
|
+
<property name="fill">True</property>
|
510
|
+
<property name="position">2</property>
|
511
|
+
</packing>
|
512
|
+
</child>
|
513
|
+
<child>
|
514
|
+
<object class="GtkButton" id="button1">
|
515
|
+
<property name="label">gtk-delete</property>
|
516
|
+
<property name="visible">True</property>
|
517
|
+
<property name="can_focus">False</property>
|
518
|
+
<property name="receives_default">True</property>
|
519
|
+
<property name="use_stock">True</property>
|
520
|
+
</object>
|
521
|
+
<packing>
|
522
|
+
<property name="expand">False</property>
|
523
|
+
<property name="fill">True</property>
|
524
|
+
<property name="position">3</property>
|
525
|
+
</packing>
|
526
|
+
</child>
|
527
|
+
</object>
|
528
|
+
<packing>
|
529
|
+
<property name="expand">False</property>
|
530
|
+
<property name="fill">True</property>
|
531
|
+
<property name="position">1</property>
|
532
|
+
</packing>
|
533
|
+
</child>
|
534
|
+
</object>
|
535
|
+
</child>
|
536
|
+
</object>
|
537
|
+
<object class="GtkImage" id="last_img">
|
538
|
+
<property name="visible">True</property>
|
539
|
+
<property name="can_focus">False</property>
|
540
|
+
<property name="stock">gtk-goto-last</property>
|
541
|
+
</object>
|
542
|
+
<object class="GtkImage" id="next_img">
|
543
|
+
<property name="visible">True</property>
|
544
|
+
<property name="can_focus">False</property>
|
545
|
+
<property name="stock">gtk-go-forward</property>
|
546
|
+
</object>
|
547
|
+
<object class="GtkImage" id="play_img">
|
548
|
+
<property name="visible">True</property>
|
549
|
+
<property name="can_focus">False</property>
|
550
|
+
<property name="stock">gtk-media-play</property>
|
551
|
+
</object>
|
552
|
+
<object class="GtkImage" id="previous_img">
|
553
|
+
<property name="visible">True</property>
|
554
|
+
<property name="can_focus">False</property>
|
555
|
+
<property name="stock">gtk-go-back</property>
|
556
|
+
</object>
|
557
|
+
</interface>
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: apngasm-gui
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rika Yoshida
|
8
|
+
- Rei Kagetsuki
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-05-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rapngasm
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.1'
|
21
|
+
- - '='
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.1.2
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '3.1'
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.1.2
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: gtk3
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
type: :runtime
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
description: ''
|
49
|
+
email: info@genshin.org
|
50
|
+
executables:
|
51
|
+
- apngasm-gui
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- ".gitignore"
|
56
|
+
- Gemfile
|
57
|
+
- README.md
|
58
|
+
- apngasm-gui.gemspec
|
59
|
+
- bin/apngasm-gui
|
60
|
+
- lib/apngasm-gui.rb
|
61
|
+
- lib/apngasm-gui/adapter.rb
|
62
|
+
- lib/apngasm-gui/editor_window.rb
|
63
|
+
- lib/apngasm-gui/frame.rb
|
64
|
+
- lib/apngasm-gui/frame_list.rb
|
65
|
+
- lib/apngasm-gui/layout.glade
|
66
|
+
homepage: https://github.com/apngasm/apngasm-gui
|
67
|
+
licenses:
|
68
|
+
- GNU GPL v3
|
69
|
+
metadata: {}
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
requirements: []
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 2.2.2
|
87
|
+
signing_key:
|
88
|
+
specification_version: 4
|
89
|
+
summary: ''
|
90
|
+
test_files: []
|
91
|
+
has_rdoc:
|