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.
@@ -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: