rabbit 3.0.0 → 3.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/data/locale/en/LC_MESSAGES/rabbit.mo +0 -0
  3. data/data/locale/ja/LC_MESSAGES/rabbit.mo +0 -0
  4. data/doc/_config.yml +2 -2
  5. data/doc/en/faq.rd +4 -2
  6. data/doc/en/news.rd +91 -0
  7. data/doc/en/sample/hiki/rabbit.hiki +0 -4
  8. data/doc/en/sample/rd/rabbit.rd +0 -4
  9. data/doc/en/usage/rabbit-slide.rd +3 -3
  10. data/doc/index.html.en +1 -1
  11. data/doc/ja/faq.rd +2 -0
  12. data/doc/ja/news.rd +90 -0
  13. data/doc/ja/sample/hiki/rabbit.hiki +0 -4
  14. data/doc/ja/sample/rd/rabbit.rd +0 -4
  15. data/doc/ja/usage/rabbit-slide.rd +3 -3
  16. data/doc/ja/users.rd +7 -0
  17. data/lib/rabbit/action/toggle.rb +7 -0
  18. data/lib/rabbit/author-configuration.rb +3 -4
  19. data/lib/rabbit/canvas.rb +11 -1
  20. data/lib/rabbit/command/rabbit-slide.rb +59 -1
  21. data/lib/rabbit/command/rabbit-slide.ui +127 -49
  22. data/lib/rabbit/command/rabbit.rb +5 -9
  23. data/lib/rabbit/element/image.rb +78 -94
  24. data/lib/rabbit/element/video.rb +3 -11
  25. data/lib/rabbit/error.rb +2 -2
  26. data/lib/rabbit/frame.rb +102 -4
  27. data/lib/rabbit/gem-pusher.rb +28 -6
  28. data/lib/rabbit/image/base.rb +97 -26
  29. data/lib/rabbit/image/dia.rb +21 -6
  30. data/lib/rabbit/image/pdf.rb +1 -4
  31. data/lib/rabbit/image/svg.rb +1 -4
  32. data/lib/rabbit/image.rb +3 -4
  33. data/lib/rabbit/info-window.rb +106 -80
  34. data/lib/rabbit/keys.rb +6 -0
  35. data/lib/rabbit/menu.rb +2 -0
  36. data/lib/rabbit/parser/ext/charty.rb +58 -0
  37. data/lib/rabbit/parser/ext/image.rb +2 -1
  38. data/lib/rabbit/parser/rd/ext/block-verbatim.rb +13 -5
  39. data/lib/rabbit/progress.rb +1 -1
  40. data/lib/rabbit/properties.rb +141 -0
  41. data/lib/rabbit/rabbit.rb +3 -1
  42. data/lib/rabbit/relative-size.rb +28 -0
  43. data/lib/rabbit/renderer/base.rb +6 -0
  44. data/lib/rabbit/renderer/display/drawing-area-base.rb +0 -1
  45. data/lib/rabbit/renderer/display/drawing-area-primitive.rb +1 -0
  46. data/lib/rabbit/renderer/display/info.rb +6 -1
  47. data/lib/rabbit/renderer/display/key-handler.rb +27 -2
  48. data/lib/rabbit/renderer/engine/cairo.rb +24 -3
  49. data/lib/rabbit/renderer/screen.rb +0 -1
  50. data/lib/rabbit/slide-configuration.rb +12 -8
  51. data/lib/rabbit/task/slide.rb +3 -3
  52. data/lib/rabbit/theme/clear-blue/clear-blue.rb +3 -1
  53. data/lib/rabbit/theme/edge-info-toolkit/edge-info-toolkit.rb +12 -2
  54. data/lib/rabbit/theme/image-slide-number/image-slide-number.rb +1 -1
  55. data/lib/rabbit/theme/slide-footer-info/slide-footer-info.rb +2 -0
  56. data/lib/rabbit/theme/tag/tag.rb +9 -2
  57. data/lib/rabbit/theme-configuration.rb +3 -4
  58. data/lib/rabbit/version.rb +1 -1
  59. data/lib/rabbit/video-window.rb +14 -3
  60. data/lib/rabbit/yaml-loader.rb +39 -0
  61. data/po/en/rabbit.edit.po +82 -64
  62. data/po/en/rabbit.po +16 -2
  63. data/po/fr/rabbit.edit.po +81 -63
  64. data/po/fr/rabbit.po +15 -1
  65. data/po/ja/rabbit.edit.po +108 -65
  66. data/po/ja/rabbit.po +19 -3
  67. data/sample/can_rabbit.rd +0 -24
  68. data/sample/rabbit-en.hiki +0 -4
  69. data/sample/rabbit-en.rd +0 -4
  70. data/sample/rabbit.hiki +0 -4
  71. data/sample/rabbit.rd +0 -4
  72. data/test/test-slide-configuration.rb +3 -2
  73. metadata +27 -24
@@ -32,7 +32,12 @@ module Rabbit
32
32
 
33
33
  def post_move(old_index, index)
34
34
  super
35
- @info_window.moved(index)
35
+ @info_window.moved
36
+ end
37
+
38
+ def post_move_in_slide(old_index, index)
39
+ super
40
+ @info_window.moved
36
41
  end
37
42
 
38
43
  def index_mode_on
@@ -19,10 +19,19 @@ module Rabbit
19
19
  @user_accel_group.disconnect_key(keyval, modifier)
20
20
  end
21
21
 
22
+ def pre_terminal
23
+ @window.remove_accel_group(@accel_group)
24
+ end
25
+
26
+ def post_terminal
27
+ @window.add_accel_group(@accel_group)
28
+ end
29
+
22
30
  private
23
31
  def init_key_handler
24
32
  @user_accel_group = nil
25
33
  init_accel_group
34
+ init_toggle_terminal_accel_group
26
35
  end
27
36
 
28
37
  def clear_user_accel_group
@@ -31,10 +40,12 @@ module Rabbit
31
40
 
32
41
  def attach_key(window)
33
42
  window.add_accel_group(@accel_group)
43
+ window.add_accel_group(@toggle_terminal_accel_group)
34
44
  end
35
45
 
36
46
  def detach_key(window)
37
47
  window.remove_accel_group(@accel_group)
48
+ window.remove_accel_group(@toggle_terminal_accel_group)
38
49
  end
39
50
 
40
51
  def clear_keys
@@ -53,10 +64,24 @@ module Rabbit
53
64
  init_alt_keys
54
65
  end
55
66
 
56
- def set_keys(keys, mod, flags=nil, &block)
67
+ def init_toggle_terminal_accel_group
68
+ @toggle_terminal_accel_group = Gtk::AccelGroup.new
69
+ mod = Gdk::ModifierType::SHIFT_MASK |
70
+ Gdk::ModifierType::CONTROL_MASK |
71
+ Gdk::ModifierType::MOD1_MASK
72
+ keys = Keys::ShiftControlAlt::TOGGLE_TERMINAL_KEYS
73
+ set_keys(keys,
74
+ mod,
75
+ nil,
76
+ @toggle_terminal_accel_group) do |group, obj, val, modifier|
77
+ @canvas.activate("ToggleTerminal")
78
+ end
79
+ end
80
+
81
+ def set_keys(keys, mod, flags=nil, accel_group=@accel_group, &block)
57
82
  flags ||= Gtk::AccelFlags::VISIBLE
58
83
  keys.each do |val|
59
- @accel_group.connect(val, mod, flags, &block)
84
+ accel_group.connect(val, mod, flags, &block)
60
85
  end
61
86
  end
62
87
 
@@ -195,6 +195,7 @@ module Rabbit
195
195
  def draw_pixbuf(pixbuf, x, y, params={})
196
196
  x, y = from_screen(x, y)
197
197
  @context.save do
198
+ apply_clip(x, y, pixbuf.width, pixbuf.height, params)
198
199
  @context.translate(x, y)
199
200
  set_source_pixbuf(pixbuf, params)
200
201
  @context.paint(params[:alpha])
@@ -244,11 +245,14 @@ module Rabbit
244
245
  def draw_rsvg_handle(handle, x, y, params={})
245
246
  x, y = from_screen(x, y)
246
247
  dim = handle.dimensions
247
- width = (params[:width] || dim.width).to_f
248
- height = (params[:height] || dim.height).to_f
248
+ w = dim.width
249
+ h = dim.height
250
+ width = (params[:width] || w).to_f
251
+ height = (params[:height] || h).to_f
249
252
  @context.save do
253
+ apply_clip(x, y, w, h, params)
250
254
  @context.translate(x, y)
251
- @context.scale(width / dim.width, height / dim.height)
255
+ @context.scale(width / w, height / h)
252
256
  @context.render_rsvg_handle(handle)
253
257
  end
254
258
 
@@ -262,6 +266,7 @@ module Rabbit
262
266
  width = (params[:width] || w).to_f
263
267
  height = (params[:height] || h).to_f
264
268
  @context.save do
269
+ apply_clip(x, y, w, h, params)
265
270
  @context.translate(x, y)
266
271
  @context.scale(width / w, height / h)
267
272
  @context.render_poppler_page(page)
@@ -396,6 +401,22 @@ module Rabbit
396
401
  end
397
402
  end
398
403
 
404
+ def apply_clip(x, y, w, h, params)
405
+ clip_x = params[:clip_x]
406
+ clip_y = params[:clip_y]
407
+ clip_width = params[:clip_width]
408
+ clip_height = params[:clip_height]
409
+ if clip_x or clip_y or clip_width or clip_height
410
+ @context.rectangle(x,
411
+ y,
412
+ clip_width || w,
413
+ clip_height || h)
414
+ @context.clip
415
+ @context.translate(x - (clip_x || x),
416
+ y - (clip_y || y))
417
+ end
418
+ end
419
+
399
420
  def make_matrix(xx, xy, x0, yx, yy, y0)
400
421
  ::Cairo::Matrix.new(xx, yx, xy, yy, x0, y0)
401
422
  end
@@ -25,7 +25,6 @@ require "rabbit/renderer/display/mask"
25
25
  require "rabbit/renderer/display/search"
26
26
  require "rabbit/renderer/display/gesture"
27
27
  require "rabbit/renderer/display/graffiti"
28
- require "rabbit/renderer/display/menu"
29
28
  require "rabbit/renderer/display/button-handler"
30
29
  require "rabbit/renderer/display/key-handler"
31
30
  require "rabbit/renderer/display/scroll-handler"
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2012-2017 Kouhei Sutou <kou@cozmixng.org>
1
+ # Copyright (C) 2012-2021 Sutou Kouhei <kou@cozmixng.org>
2
2
  #
3
3
  # This program is free software; you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -17,12 +17,11 @@
17
17
  require "date"
18
18
  require "time"
19
19
 
20
- require "yaml"
21
-
22
20
  require "rabbit/gettext"
23
21
  require "rabbit/logger"
24
22
  require "rabbit/author-configuration"
25
23
  require "rabbit/path-manipulatable"
24
+ require "rabbit/yaml-loader"
26
25
 
27
26
  module Rabbit
28
27
  class SlideConfiguration
@@ -41,11 +40,12 @@ module Rabbit
41
40
  attr_accessor :licenses
42
41
  attr_accessor :slideshare_id
43
42
  attr_accessor :speaker_deck_id
44
- attr_accessor :ustream_id
45
43
  attr_accessor :vimeo_id
46
44
  attr_accessor :youtube_id
47
45
  attr_writer :version
48
46
  attr_accessor :author
47
+ attr_accessor :width
48
+ attr_accessor :height
49
49
  def initialize(logger=nil)
50
50
  @logger = logger || Logger.default
51
51
  clear
@@ -65,7 +65,7 @@ module Rabbit
65
65
 
66
66
  def load
67
67
  return unless File.exist?(path)
68
- conf = YAML.load(File.read(path))
68
+ conf = YAMLLoader.load(File.read(path))
69
69
  clear
70
70
  merge!(conf)
71
71
  rescue
@@ -94,10 +94,11 @@ module Rabbit
94
94
  @licenses = []
95
95
  @slideshare_id = nil
96
96
  @speaker_deck_id = nil
97
- @ustream_id = nil
98
97
  @vimeo_id = nil
99
98
  @youtube_id = nil
100
99
  @author = nil
100
+ @width = 800
101
+ @height = 600
101
102
  end
102
103
 
103
104
 
@@ -113,7 +114,6 @@ module Rabbit
113
114
  @version = conf["version"] || @version
114
115
  @slideshare_id = conf["slideshare_id"] || @slideshare_id
115
116
  @speaker_deck_id = conf["speaker_deck_id"] || @speaker_deck_id
116
- @ustream_id = conf["ustream_id"] || @ustream_id
117
117
  @vimeo_id = conf["vimeo_id"] || @vimeo_id
118
118
  @youtube_id = conf["youtube_id"] || @youtube_id
119
119
 
@@ -122,6 +122,9 @@ module Rabbit
122
122
 
123
123
  @author ||= AuthorConfiguration.new(@logger)
124
124
  @author.merge!(conf["author"] || {})
125
+
126
+ @width = conf["width"] || @width
127
+ @height = conf["height"] || @height
125
128
  end
126
129
 
127
130
  def to_hash
@@ -136,9 +139,10 @@ module Rabbit
136
139
  "licenses" => @licenses,
137
140
  "slideshare_id" => @slideshare_id,
138
141
  "speaker_deck_id" => @speaker_deck_id,
139
- "ustream_id" => @ustream_id,
140
142
  "vimeo_id" => @vimeo_id,
141
143
  "youtube_id" => @youtube_id,
144
+ "width" => @width,
145
+ "height" => @height,
142
146
  }
143
147
  config["author"] = @author.to_hash if @author
144
148
  config
@@ -174,7 +174,7 @@ module Rabbit
174
174
  end
175
175
 
176
176
  def define_publish_rubygems_task
177
- desc(_("Publish the slide to %s" % "RubyGems.org"))
177
+ desc(_("Publish the slide to %s") % "RubyGems.org")
178
178
  task :rubygems => :gem do
179
179
  pusher = GemPusher.new(gem_path, @slide.author.rubygems_user)
180
180
  pusher.push
@@ -183,7 +183,7 @@ module Rabbit
183
183
 
184
184
  def define_publish_slideshare_task
185
185
  slideshare_user = @slide.author.slideshare_user
186
- desc(_("Publish the slide to %s" % "SlideShare"))
186
+ desc(_("Publish the slide to %s") % "SlideShare")
187
187
  task :slideshare => [:pdf, "gem:validate"] do
188
188
  require "rabbit/slideshare"
189
189
  slideshare = SlideShare.new(@logger)
@@ -207,7 +207,7 @@ module Rabbit
207
207
  end
208
208
 
209
209
  def define_publish_speaker_deck_task
210
- desc(_("Publish the slide to %s" % "Speaker Deck"))
210
+ desc(_("Publish the slide to %s") % "Speaker Deck")
211
211
  task :speaker_deck => :pdf do
212
212
  puts "Not implemented yet."
213
213
  end
@@ -77,8 +77,10 @@ match(Slide, HeadLine) do |heads|
77
77
  end
78
78
 
79
79
  match(Slide, Body) do |bodies|
80
- bodies.vertical_centering = true
81
80
  bodies.each do |body|
81
+ if body.slide["enable-clear-blue-slide-body-vertical-centering"] != "false"
82
+ body.vertical_centering = true
83
+ end
82
84
  next if body.elements.all? {|element| element.is_a?(Image)}
83
85
  next if body.elements.any? {|element| element.is_a?(BlockQuote)}
84
86
  next if body.elements.any? {|element| element.is_a?(PreformattedBlock)}
@@ -13,6 +13,7 @@ match(SlideElement) do |slides|
13
13
  line_color = options[:line_color] || "#666"
14
14
  line_params = options[:line_params] || {}
15
15
  left_text = options[:left_text]
16
+ center_text = options[:center_text]
16
17
  right_text = options[:right_text]
17
18
  text_position = options[:text_position] || :lower
18
19
  text_over_line = options[:text_over_line]
@@ -36,15 +37,20 @@ match(SlideElement) do |slides|
36
37
  "size" => text_size,
37
38
  "color" => text_color,
38
39
  }
39
- left_layout = right_layout = nil
40
+ left_layout = center_layout = right_layout = nil
40
41
  if left_text and !left_text.empty?
41
42
  left_layout = make_formatted_layout.call(props, left_text)
42
43
  end
44
+ if center_text and !center_text.empty?
45
+ center_layout = make_formatted_layout.call(props, center_text)
46
+ center_layout.alignment = :center
47
+ center_layout.width = (w - (x_margin * 2)) * Pango::SCALE
48
+ end
43
49
  if right_text and !right_text.empty?
44
50
  right_layout = make_formatted_layout.call(props, right_text)
45
51
  end
46
52
 
47
- layouts = [left_layout, right_layout].compact
53
+ layouts = [left_layout, center_layout, right_layout].compact
48
54
  unless layouts.empty?
49
55
  max_height = layouts.collect {|layout| layout.pixel_size[1]}.max
50
56
  if text_position == :lower
@@ -63,6 +69,10 @@ match(SlideElement) do |slides|
63
69
  canvas.draw_layout(left_layout, x_margin, text_base_y)
64
70
  end
65
71
 
72
+ if center_layout
73
+ canvas.draw_layout(center_layout, x_margin, text_base_y)
74
+ end
75
+
66
76
  if right_layout
67
77
  text_width, text_height = right_layout.pixel_size
68
78
  right_text_x = canvas.width - text_width - x_margin
@@ -88,7 +88,7 @@ match(Slide) do |slides|
88
88
  margin_bottom = @image_slide_number_margin_bottom || slide.margin_bottom
89
89
  base_x = margin_left
90
90
  base_y = canvas.height - loader.height - margin_bottom
91
- max_width = canvas.width - margin_left - base_x - loader.width
91
+ max_width = canvas.width - margin_right - base_x - loader.width
92
92
  start_base_x = base_x
93
93
  goal_base_x = canvas.width - margin_right - goal_flag_width
94
94
 
@@ -25,6 +25,7 @@ end
25
25
  @slide_footer_info_base_y ||= canvas.height - @margin_bottom
26
26
 
27
27
  @slide_footer_info_left_text ||= nil
28
+ @slide_footer_info_center_text ||= nil
28
29
  @slide_footer_info_right_text ||= nil
29
30
 
30
31
  include_theme("edge-info-toolkit")
@@ -39,6 +40,7 @@ match(SlideElement) do
39
40
  :line_color => @slide_footer_info_line_color,
40
41
  :line_params => @slide_footer_info_line_params,
41
42
  :left_text => @slide_footer_info_left_text,
43
+ :center_text => @slide_footer_info_center_text,
42
44
  :right_text => @slide_footer_info_right_text,
43
45
  :text_position => :lower,
44
46
  :text_over_line => @slide_footer_info_text_over_line,
@@ -61,12 +61,19 @@ match("**", CustomTag) do |tags|
61
61
  find_target.call(tag).prop_set("size", @xx_large_font_size)
62
62
  when /\A(normal|oblique|italic)\z/
63
63
  find_target.call(tag).prop_set("style", $1)
64
- when /\Amargin-(top|bottom|left|right)(?:\s*\*\s*(\d+))?\z/
64
+ when /\Amargin-(top|bottom|left|right)(?:\s*\*\s*([-\d.]+))?\z/
65
65
  target = "margin_#{$1}"
66
- scale = Integer($2 || 1)
66
+ scale = Float($2 || 1)
67
67
  outer_block = find_outer_block.call(tag)
68
68
  current_value = outer_block.send(target)
69
69
  outer_block.send("#{target}=", current_value + (@space * scale))
70
+ when /\Awrap-(.+)\z/
71
+ wrap = $1
72
+ find_target.call(tag).wrap_mode = wrap
73
+ when /\Ajustify?\z/
74
+ find_target.call(tag).justify = true
75
+ when /\Ano-justify?\z/
76
+ find_target.call(tag).justify = false
70
77
  else
71
78
  handler = find_handler.call(tag)
72
79
  if handler
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2012 Kouhei Sutou <kou@cozmixng.org>
1
+ # Copyright (C) 2012-2021 Sutou Kouhei <kou@cozmixng.org>
2
2
  #
3
3
  # This program is free software; you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -14,11 +14,10 @@
14
14
  # with this program; if not, write to the Free Software Foundation, Inc.,
15
15
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
16
 
17
- require "yaml"
18
-
19
17
  require "rabbit/gettext"
20
18
  require "rabbit/author-configuration"
21
19
  require "rabbit/path-manipulatable"
20
+ require "rabbit/yaml-loader"
22
21
 
23
22
  module Rabbit
24
23
  class ThemeConfiguration
@@ -42,7 +41,7 @@ module Rabbit
42
41
 
43
42
  def load
44
43
  return unless File.exist?(path)
45
- conf = YAML.load(File.read(path))
44
+ conf = YAMLLoader.load(File.read(path))
46
45
  merge!(conf)
47
46
  rescue
48
47
  format = _("Failed to read slide configuration: %s: %s")
@@ -15,5 +15,5 @@
15
15
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
16
 
17
17
  module Rabbit
18
- VERSION = "3.0.0"
18
+ VERSION = "3.0.1"
19
19
  end
@@ -87,11 +87,11 @@ module Rabbit
87
87
  @window.signal_connect(:key_press_event) do |widget, key|
88
88
  case key.keyval
89
89
  when Gdk::Keyval::KEY_space
90
- @video.toggle
90
+ @player.playing = !@player.playing?
91
91
  when Gdk::Keyval::KEY_plus
92
- @video.seek(10)
92
+ seek(10)
93
93
  when Gdk::Keyval::KEY_minus
94
- @video.seek(-10)
94
+ seek(-10)
95
95
  when *[
96
96
  Keys::MOVE_TO_NEXT_KEYS, Keys::MOVE_TO_PREVIOUS_KEYS,
97
97
  Keys::MOVE_TO_LAST_KEYS, Keys::MOVE_TO_LAST_KEYS,
@@ -104,5 +104,16 @@ module Rabbit
104
104
  true
105
105
  end
106
106
  end
107
+
108
+ def seek(second)
109
+ duration = @player.duration
110
+ progress = @player.progress + (second / duration)
111
+ if progress < 0.0
112
+ progress = 0.0
113
+ elsif progress > 1.0
114
+ progress = 1.0
115
+ end
116
+ @player.progress = progress
117
+ end
107
118
  end
108
119
  end
@@ -0,0 +1,39 @@
1
+ # Copyright (C) 2021 Sutou Kouhei <kou@cozmixng.org>
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License along
14
+ # with this program; if not, write to the Free Software Foundation, Inc.,
15
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+
17
+ require "date"
18
+ require "yaml"
19
+
20
+ module Rabbit
21
+ class YAMLLoader
22
+ class << self
23
+ def load(yaml)
24
+ new(yaml).load
25
+ end
26
+ end
27
+
28
+ def initialize(yaml)
29
+ @yaml = yaml
30
+ end
31
+
32
+ def load
33
+ YAML.safe_load(@yaml,
34
+ permitted_classes: [
35
+ Date, Symbol,
36
+ ])
37
+ end
38
+ end
39
+ end