apngasm-gui 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -0,0 +1,11 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'libnotify'
7
+ gem 'guard'
8
+ gem 'guard-rspec'
9
+ gem 'rubocop'
10
+ gem 'guard-rubocop'
11
+ end
@@ -0,0 +1,4 @@
1
+ apngasm-gui
2
+ ===========
3
+
4
+ Graphical tool for creating Animated PNG images
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module APNGAsmGUI
2
+ require 'gtk3'
3
+ end
@@ -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: