rabbit 2.2.1 → 3.0.0

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 (177) hide show
  1. checksums.yaml +5 -5
  2. data/data/locale/ja/LC_MESSAGES/rabbit.mo +0 -0
  3. data/doc/_config.yml +2 -2
  4. data/doc/_layouts/en.html +1 -1
  5. data/doc/_layouts/ja.html +1 -1
  6. data/doc/en/news.rd +140 -0
  7. data/doc/en/sample/hiki/rabbit.hiki +2 -2
  8. data/doc/en/sample/markdown/rabbit.md +1 -1
  9. data/doc/en/sample/rd/rabbit.rd +1 -1
  10. data/doc/en/usage/rabbit-slide.rd +3 -3
  11. data/doc/images/screenshots/en/blue-circle-raw.png +0 -0
  12. data/doc/images/screenshots/en/blue-circle.png +0 -0
  13. data/doc/images/screenshots/en/clear-blue-raw.png +0 -0
  14. data/doc/images/screenshots/en/clear-blue.png +0 -0
  15. data/doc/images/screenshots/en/cozmixng-raw.png +0 -0
  16. data/doc/images/screenshots/en/cozmixng.png +0 -0
  17. data/doc/images/screenshots/en/dark-gradation-raw.png +0 -0
  18. data/doc/images/screenshots/en/dark-gradation.png +0 -0
  19. data/doc/images/screenshots/en/day-white-raw.png +0 -0
  20. data/doc/images/screenshots/en/day-white.png +0 -0
  21. data/doc/images/screenshots/en/debian-raw.png +0 -0
  22. data/doc/images/screenshots/en/debian.png +0 -0
  23. data/doc/images/screenshots/en/green-circle-raw.png +0 -0
  24. data/doc/images/screenshots/en/green-circle.png +0 -0
  25. data/doc/images/screenshots/en/night-black-raw.png +0 -0
  26. data/doc/images/screenshots/en/night-black.png +0 -0
  27. data/doc/images/screenshots/en/rabbit-raw.png +0 -0
  28. data/doc/images/screenshots/en/rabbit.png +0 -0
  29. data/doc/images/screenshots/en/ranguba-raw.png +0 -0
  30. data/doc/images/screenshots/en/ranguba.png +0 -0
  31. data/doc/images/screenshots/en/red-frame-raw.png +0 -0
  32. data/doc/images/screenshots/en/red-frame.png +0 -0
  33. data/doc/images/screenshots/en/ruby-gnome2-raw.png +0 -0
  34. data/doc/images/screenshots/en/ruby-gnome2.png +0 -0
  35. data/doc/images/screenshots/en/rubykaigi2011-raw.png +0 -0
  36. data/doc/images/screenshots/en/rubykaigi2011.png +0 -0
  37. data/doc/images/screenshots/ja/blue-circle-raw.png +0 -0
  38. data/doc/images/screenshots/ja/blue-circle.png +0 -0
  39. data/doc/images/screenshots/ja/clear-blue-raw.png +0 -0
  40. data/doc/images/screenshots/ja/clear-blue.png +0 -0
  41. data/doc/images/screenshots/ja/cozmixng-raw.png +0 -0
  42. data/doc/images/screenshots/ja/cozmixng.png +0 -0
  43. data/doc/images/screenshots/ja/dark-gradation-raw.png +0 -0
  44. data/doc/images/screenshots/ja/dark-gradation.png +0 -0
  45. data/doc/images/screenshots/ja/day-white-raw.png +0 -0
  46. data/doc/images/screenshots/ja/day-white.png +0 -0
  47. data/doc/images/screenshots/ja/debian-raw.png +0 -0
  48. data/doc/images/screenshots/ja/debian.png +0 -0
  49. data/doc/images/screenshots/ja/green-circle-raw.png +0 -0
  50. data/doc/images/screenshots/ja/green-circle.png +0 -0
  51. data/doc/images/screenshots/ja/night-black-raw.png +0 -0
  52. data/doc/images/screenshots/ja/night-black.png +0 -0
  53. data/doc/images/screenshots/ja/rabbit-raw.png +0 -0
  54. data/doc/images/screenshots/ja/rabbit.png +0 -0
  55. data/doc/images/screenshots/ja/ranguba-raw.png +0 -0
  56. data/doc/images/screenshots/ja/ranguba.png +0 -0
  57. data/doc/images/screenshots/ja/red-frame-raw.png +0 -0
  58. data/doc/images/screenshots/ja/red-frame.png +0 -0
  59. data/doc/images/screenshots/ja/ruby-gnome2-raw.png +0 -0
  60. data/doc/images/screenshots/ja/ruby-gnome2.png +0 -0
  61. data/doc/images/screenshots/ja/rubykaigi2011-raw.png +0 -0
  62. data/doc/images/screenshots/ja/rubykaigi2011.png +0 -0
  63. data/doc/ja/how-to-make/index.rd +1 -1
  64. data/doc/ja/news.rd +143 -0
  65. data/doc/ja/sample/hiki/rabbit.hiki +2 -2
  66. data/doc/ja/sample/markdown/rabbit.md +1 -1
  67. data/doc/ja/sample/rd/rabbit.rd +1 -1
  68. data/doc/ja/slides.rd +1 -1
  69. data/doc/ja/usage/rabbit-slide.rd +3 -3
  70. data/doc/ja/users.rd +1 -1
  71. data/lib/rabbit/action.rb +23 -4
  72. data/lib/rabbit/canvas.rb +70 -14
  73. data/lib/rabbit/command/rabbit-slide.rb +252 -67
  74. data/lib/rabbit/command/rabbit-slide.ui +180 -0
  75. data/lib/rabbit/command/rabbit.rb +14 -20
  76. data/lib/rabbit/console.rb +9 -3
  77. data/lib/rabbit/dependency-canvas.rb +19 -1
  78. data/lib/rabbit/element.rb +34 -7
  79. data/lib/rabbit/element/poppler-page.rb +1 -2
  80. data/lib/rabbit/element/text-container-element.rb +2 -2
  81. data/lib/rabbit/element/text-renderer.rb +5 -4
  82. data/lib/rabbit/element/title-slide.rb +8 -0
  83. data/lib/rabbit/element/video.rb +1 -2
  84. data/lib/rabbit/filename.rb +39 -0
  85. data/lib/rabbit/formatter.rb +61 -30
  86. data/lib/rabbit/frame.rb +1 -19
  87. data/lib/rabbit/front.rb +23 -2
  88. data/lib/rabbit/gesture/handler.rb +21 -2
  89. data/lib/rabbit/graffiti/config-dialog.rb +15 -18
  90. data/lib/rabbit/gtk.rb +2 -191
  91. data/lib/rabbit/html/generator.rb +38 -30
  92. data/lib/rabbit/image-data-loader.rb +6 -1
  93. data/lib/rabbit/image.rb +22 -4
  94. data/lib/rabbit/image/base.rb +34 -2
  95. data/lib/rabbit/image/default.rb +1 -1
  96. data/lib/rabbit/image/eps.rb +1 -1
  97. data/lib/rabbit/image/gimp.rb +1 -1
  98. data/lib/rabbit/info-window.rb +27 -15
  99. data/lib/rabbit/logger/gui.rb +21 -23
  100. data/lib/rabbit/logger/stderr.rb +1 -1
  101. data/lib/rabbit/pango-markup.rb +44 -0
  102. data/lib/rabbit/parser.rb +20 -3
  103. data/lib/rabbit/parser/ext/image.rb +25 -8
  104. data/lib/rabbit/parser/ext/video.rb +21 -2
  105. data/lib/rabbit/parser/markdown.rb +1 -2
  106. data/lib/rabbit/parser/pdf.rb +23 -7
  107. data/lib/rabbit/parser/rd/rd2rabbit-lib.rb +20 -0
  108. data/lib/rabbit/progress.rb +34 -23
  109. data/lib/rabbit/renderer.rb +17 -23
  110. data/lib/rabbit/renderer/base.rb +31 -57
  111. data/lib/rabbit/renderer/color.rb +46 -53
  112. data/lib/rabbit/renderer/display/base.rb +71 -62
  113. data/lib/rabbit/renderer/display/button-handler.rb +2 -1
  114. data/lib/rabbit/renderer/display/clutter-embed.rb +60 -26
  115. data/lib/rabbit/renderer/display/drawing-area-base.rb +1 -1
  116. data/lib/rabbit/renderer/display/drawing-area-primitive.rb +34 -21
  117. data/lib/rabbit/renderer/display/graffiti.rb +1 -3
  118. data/lib/rabbit/renderer/display/hook-handler.rb +8 -4
  119. data/lib/rabbit/renderer/display/key-handler.rb +7 -2
  120. data/lib/rabbit/renderer/display/magnifier.rb +2 -2
  121. data/lib/rabbit/renderer/display/progress.rb +10 -2
  122. data/lib/rabbit/renderer/display/spotlight.rb +2 -2
  123. data/lib/rabbit/renderer/engine/cairo.rb +0 -3
  124. data/lib/rabbit/renderer/kernel.rb +54 -0
  125. data/lib/rabbit/renderer/offscreen.rb +14 -6
  126. data/lib/rabbit/renderer/print-layout.rb +150 -0
  127. data/lib/rabbit/renderer/printer.rb +236 -0
  128. data/lib/rabbit/renderer/screen.rb +288 -0
  129. data/lib/rabbit/renderer/widget/drawing-area.rb +93 -0
  130. data/lib/rabbit/size.rb +52 -25
  131. data/lib/rabbit/slide-configuration.rb +56 -12
  132. data/lib/rabbit/source.rb +24 -8
  133. data/lib/rabbit/task/slide.rb +1 -1
  134. data/lib/rabbit/theme/applier.rb +26 -9
  135. data/lib/rabbit/theme/base/base.rb +7 -7
  136. data/lib/rabbit/theme/clear-blue/clear-blue.rb +1 -1
  137. data/lib/rabbit/theme/image-timer/image-timer.rb +3 -1
  138. data/lib/rabbit/theme/image-viewer/image-viewer.rb +13 -1
  139. data/lib/rabbit/theme/image/image.rb +4 -4
  140. data/lib/rabbit/theme/lightning-talk-toolkit/lightning-talk-toolkit.rb +3 -1
  141. data/lib/rabbit/theme/tag/tag.rb +12 -4
  142. data/lib/rabbit/version.rb +2 -2
  143. data/lib/rabbit/video-window.rb +75 -89
  144. data/misc/emacs/rabbit-mode.el +11 -7
  145. data/po/en/rabbit.edit.po +189 -185
  146. data/po/en/rabbit.po +15 -12
  147. data/po/fr/rabbit.edit.po +189 -185
  148. data/po/fr/rabbit.po +15 -12
  149. data/po/ja/rabbit.edit.po +190 -186
  150. data/po/ja/rabbit.po +16 -13
  151. data/rabbit.gemspec +34 -16
  152. data/test/command/test-rabbit.rb +100 -0
  153. data/test/{rabbit-test-utils.rb → helper.rb} +7 -4
  154. data/test/{rabbit-test-utils → helper}/fixture.rb +2 -2
  155. data/test/{rabbit-test-utils → helper}/parser.rb +2 -2
  156. data/test/image/test-dia.rb +2 -2
  157. data/test/image/test-eps.rb +2 -2
  158. data/test/parser/test-markdown.rb +3 -5
  159. data/test/parser/test-rd.rb +1 -3
  160. data/test/parser/test-wiki.rb +3 -5
  161. data/test/run-test.rb +3 -3
  162. data/test/test-applier.rb +60 -29
  163. data/test/test-canvas.rb +70 -0
  164. data/test/test-color.rb +18 -9
  165. data/test/test-element.rb +15 -3
  166. data/test/test-size.rb +25 -22
  167. data/test/test-slide-configuration.rb +16 -6
  168. data/test/test-source.rb +15 -5
  169. data/test/test-utils.rb +15 -1
  170. metadata +55 -84
  171. data/lib/rabbit/renderer/print.rb +0 -31
  172. data/lib/rabbit/renderer/print/base.rb +0 -78
  173. data/lib/rabbit/renderer/print/cairo.rb +0 -122
  174. data/lib/rabbit/renderer/print/layout.rb +0 -123
  175. data/lib/rabbit/renderer/print/multiple.rb +0 -202
  176. data/lib/rabbit/source/hiki.rb +0 -36
  177. data/lib/rabbit/source/slide-share.rb +0 -53
@@ -187,10 +187,10 @@ title: "サンプルスライド: Rabbit"
187
187
 
188
188
  URL先の画像をダウンロード
189
189
 
190
- {{image("http://www.cozmixng.org/repos/images/cozmixchu.png",
190
+ {{image("https://raw.githubusercontent.com/rabbit-shocker/rabbit/master/data/rabbit/image/cozmixng-images/cozmixchu.png",
191
191
  :caption => "こずみっくちゅー")}}
192
192
 
193
- // [[こずみっくちゅー|http://www.cozmixng.org/repos/images/cozmixchu.png]]
193
+ // [[こずみっくちゅー|https://raw.githubusercontent.com/rabbit-shocker/rabbit/master/data/rabbit/image/cozmixng-images/cozmixchu.png]]
194
194
  // ↑の書式はまだ使えない
195
195
 
196
196
  ! 数式
@@ -163,7 +163,7 @@ background-image-relative-margin-right
163
163
 
164
164
  URL先の画像をダウンロード
165
165
 
166
- ![](http://www.cozmixng.org/repos/images/cozmixchu.png "こずみっくちゅー")
166
+ ![](https://raw.githubusercontent.com/rabbit-shocker/rabbit/master/data/rabbit/image/cozmixng-images/cozmixchu.png "こずみっくちゅー")
167
167
 
168
168
  # 数式
169
169
 
@@ -194,7 +194,7 @@ title: "サンプルスライド: Rabbit"
194
194
  URL先の画像をダウンロード
195
195
 
196
196
  # image
197
- # src = http://www.cozmixng.org/repos/images/cozmixchu.png
197
+ # src = https://raw.githubusercontent.com/rabbit-shocker/rabbit/master/data/rabbit/image/cozmixng-images/cozmixchu.png
198
198
  # caption = こずみっくちゅー
199
199
 
200
200
  = 数式
@@ -7,7 +7,7 @@ title: スライド
7
7
  Rabbitで作ったスライドがたくさん公開されています。Rabbitで作っ
8
8
  たスライドを公開したら自由に追加してください。
9
9
 
10
- * ((<kou|URL:http://slide.rabbit-shocker.org/authors/kou/>))
10
+ * ((<kou|URL:https://slide.rabbit-shocker.org/authors/kou/>))
11
11
  * ((<zunda|URL:http://zunda.freeshell.org/d/?year=2004;month=3Q;category=rabbit>))さん
12
12
  * ((<oxy|URL:http://mono.kmc.gr.jp/~oxy/d/?date=20041019#p02>))さん
13
13
  * かずひこさん
@@ -19,7 +19,7 @@ RubyGems.orgやSlideShareへの公開をコマンド一発で実行できます
19
19
  Rabbitでよいスライドを作成し、よい発表をし、そして、共有しましょう!
20
20
 
21
21
  RubyGems.orgに公開したスライドは((<Rabbit Slide
22
- Show|URL:http://slide.rabbit-shocker.org/>))で閲覧できます。
22
+ Show|URL:https://slide.rabbit-shocker.org/>))で閲覧できます。
23
23
 
24
24
  == 雛形作成
25
25
 
@@ -203,8 +203,8 @@ RubyGems.orgのユーザー名が((%rabbit%))でスライドIDが
203
203
  % rabbit rabbit-theme-benchmark-ja.gem
204
204
 
205
205
  RubyGems.orgに公開したスライドは((<Rabbit Slide
206
- Show|URL:http://slide.rabbit-shocker.org/>))で閲覧できます。URLは
207
- ((%http://slide.rabbit-shocker.org/authors/#{RubyGems.orgのユーザー
206
+ Show|URL:https://slide.rabbit-shocker.org/>))で閲覧できます。URLは
207
+ ((%https://slide.rabbit-shocker.org/authors/#{RubyGems.orgのユーザー
208
208
  名}/#{スライドID}/%))です。
209
209
 
210
210
  Rabbit Slide ShowはRubyGems.orgに公開されているスライドを自動で収集して
@@ -15,7 +15,7 @@ Rabbitショッカーの主な活動場所はプレゼンテーションの場
15
15
 
16
16
  RabbitショッカーのみなさんはRabbitを使ってプレゼンテーションした後は使っ
17
17
  たスライドを
18
- ((<slide.rabbit-shocker.org|URL:http://slide.rabbit-shocker.org/>))へアッ
18
+ ((<slide.rabbit-shocker.org|URL:https://slide.rabbit-shocker.org/>))へアッ
19
19
  プロードしています。slide.rabbit-shocker.orgへ行けばRabbitでどんなスラ
20
20
  イドを作れるかを確認することができます。
21
21
 
@@ -1,4 +1,22 @@
1
- require 'rabbit/gtk'
1
+ # Copyright (C) 2005-2017 Kouhei Sutou <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 "rabbit/gtk"
18
+
19
+ Gtk.init if Gtk.respond_to?(:init)
2
20
 
3
21
  module Gtk
4
22
  class Action
@@ -129,9 +147,6 @@ module Rabbit
129
147
  end
130
148
  end
131
149
 
132
- dir = ::File.join("rabbit", "action")
133
- require_files_under_directory_in_load_path(dir)
134
-
135
150
  module_function
136
151
  def update_processing_action_status(canvas)
137
152
  canvas.action("ToggleIndexMode").sensitive = !canvas.processing?
@@ -141,3 +156,7 @@ module Rabbit
141
156
  end
142
157
  end
143
158
  end
159
+
160
+ require "rabbit/action/basic"
161
+ require "rabbit/action/radio"
162
+ require "rabbit/action/toggle"
@@ -1,10 +1,26 @@
1
+ # Copyright (C) 2004-2019 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
+
1
17
  require "forwardable"
2
18
  require "rabbit/gtk"
3
19
 
4
20
  require "rabbit/rabbit"
5
- require 'rabbit/frame'
6
- require 'rabbit/renderer'
7
- require 'rabbit/element'
21
+ require "rabbit/filename"
22
+ require "rabbit/frame"
23
+ require "rabbit/element"
8
24
  require "rabbit/parser"
9
25
  require "rabbit/theme/manager"
10
26
  require "rabbit/front"
@@ -18,7 +34,7 @@ module Rabbit
18
34
 
19
35
  include GetText
20
36
 
21
- INTERNAL_DPI = 80.0
37
+ INTERNAL_DPI = 96.0
22
38
 
23
39
  def_delegators(:@frame, :icon, :icon=, :set_icon)
24
40
  def_delegators(:@frame, :icon_list, :icon_list=, :set_icon_list)
@@ -29,7 +45,12 @@ module Rabbit
29
45
  def_delegators(:@frame, :iconify_available?)
30
46
 
31
47
  def_delegators(:@renderer, :width, :height)
32
- def_delegators(:@renderer, :width=, :height=)
48
+ # Deprecated. Use #base_width= instead.
49
+ def_delegator(:@renderer, :base_width=, :width=)
50
+ # Deprecated. Use #base_height= instead.
51
+ def_delegator(:@renderer, :base_height=, :height=)
52
+ def_delegators(:@renderer, :base_width, :base_height)
53
+ def_delegators(:@renderer, :base_width=, :base_height=)
33
54
  def_delegators(:@renderer, :paper_width, :paper_height)
34
55
  def_delegators(:@renderer, :paper_width=, :paper_height=)
35
56
  def_delegators(:@renderer, :margin_left, :margin_left=)
@@ -78,7 +99,7 @@ module Rabbit
78
99
 
79
100
  def_delegators(:@renderer, :z_far, :z_view)
80
101
 
81
- def_delegators(:@renderer, :to_attrs, :flag_size)
102
+ def_delegators(:@renderer, :flag_size)
82
103
 
83
104
  def_delegators(:@renderer, :create_pango_context, :pango_context=)
84
105
 
@@ -328,10 +349,14 @@ module Rabbit
328
349
  @source = source || @source
329
350
  begin
330
351
  index = current_index
352
+ current_allotted_time = allotted_time
331
353
  keep_index do
332
354
  @renderer.pre_parse
333
355
  clear
334
356
  Parser.parse(self, @source)
357
+ new_allotted_time = allotted_time
358
+ reset_timer if new_allotted_time != current_allotted_time
359
+ apply_timer
335
360
  set_current_index(index)
336
361
  reload_theme do
337
362
  if @parse_request_queue.last != id
@@ -413,9 +438,9 @@ module Rabbit
413
438
 
414
439
  def saved_image_base_name
415
440
  if @saved_image_base_name
416
- base_name = GLib.filename_to_utf8(@saved_image_base_name)
441
+ base_name = @saved_image_base_name.encode("UTF-8")
417
442
  else
418
- base_name = title.dup
443
+ base_name = Filename.sanitize(title)
419
444
  end
420
445
  base_name << "-index" if index_mode?
421
446
  base_name
@@ -518,7 +543,9 @@ module Rabbit
518
543
  end
519
544
 
520
545
  def have_previous?
521
- have_previous_slide? or (current_slide and !current_slide.first?)
546
+ return true if have_previous_slide?
547
+ return !current_slide.first? if current_slide
548
+ false
522
549
  end
523
550
 
524
551
  def have_next_slide?
@@ -526,7 +553,9 @@ module Rabbit
526
553
  end
527
554
 
528
555
  def have_next?
529
- have_next_slide? or (current_slide and !current_slide.last?)
556
+ return true if have_next_slide?
557
+ return !current_slide.last? if current_slide
558
+ false
530
559
  end
531
560
 
532
561
  def cache_all_slides
@@ -543,10 +572,11 @@ module Rabbit
543
572
  stop_auto_redraw_timer
544
573
  timer = GLib::Timeout.add(interval * 1000) do
545
574
  if quitted?
546
- false
575
+ @auto_redraw_timer = nil
576
+ GLib::Source::REMOVE
547
577
  else
548
578
  activate("Redraw")
549
- true
579
+ GLib::Source::CONTINUE
550
580
  end
551
581
  end
552
582
  @auto_redraw_timer = timer
@@ -617,7 +647,18 @@ module Rabbit
617
647
 
618
648
  def allotted_time
619
649
  time = @allotted_time
620
- time ||= title_slide.allotted_time if title_slide
650
+ if time.nil? and title_slide
651
+ time = title_slide.allotted_time
652
+ if time.nil?
653
+ start_time = title_slide.start_time
654
+ end_time = title_slide.end_time
655
+ if start_time and end_time
656
+ start_time = Time.parse(start_time)
657
+ end_time = Time.parse(end_time)
658
+ time = end_time - start_time
659
+ end
660
+ end
661
+ end
621
662
  Utils.ensure_time(time)
622
663
  end
623
664
 
@@ -633,6 +674,22 @@ module Rabbit
633
674
  @limit_time = nil
634
675
  end
635
676
 
677
+ def apply_timer
678
+ return unless title_slide
679
+
680
+ start_time = title_slide.start_time
681
+ end_time = title_slide.end_time
682
+ return if start_time.nil?
683
+ return if end_time.nil?
684
+
685
+ start_time = Time.parse(start_time)
686
+ end_time = Time.parse(end_time)
687
+ return unless (start_time..end_time).cover?(Time.now)
688
+
689
+ @allotted_time = end_time - start_time
690
+ @limit_time = end_time
691
+ end
692
+
636
693
  def font_resolution
637
694
  INTERNAL_DPI * @font_resolution_ratio
638
695
  end
@@ -688,7 +745,6 @@ module Rabbit
688
745
 
689
746
  def clear
690
747
  clear_comments
691
- reset_timer
692
748
  stop_auto_redraw_timer
693
749
  clear_slides
694
750
  clear_index_slides
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2012-2013 Kouhei Sutou <kou@cozmixng.org>
1
+ # Copyright (C) 2012-2019 Kouhei Sutou <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
@@ -16,10 +16,10 @@
16
16
 
17
17
  require "yaml"
18
18
 
19
- require "rabbit/console"
20
19
  require "rabbit/author-configuration"
21
- require "rabbit/slide-configuration"
20
+ require "rabbit/console"
22
21
  require "rabbit/path-manipulatable"
22
+ require "rabbit/slide-configuration"
23
23
  require "rabbit/source-generator"
24
24
 
25
25
  module Rabbit
@@ -34,17 +34,45 @@ module Rabbit
34
34
  end
35
35
  end
36
36
 
37
+ class Data < Struct.new(:title,
38
+ :allotted_time,
39
+ :slide_conf,
40
+ :author_conf)
41
+ def available_markup_languages
42
+ {
43
+ :markdown => "Markdown",
44
+ :rd => "RD",
45
+ :hiki => "Hiki",
46
+ :pdf => "PDF",
47
+ }
48
+ end
49
+
50
+ def default_markup_language
51
+ :rd
52
+ end
53
+
54
+ def markup_language
55
+ author_conf.markup_language || default_markup_language
56
+ end
57
+
58
+ def save
59
+ author_conf.save
60
+ end
61
+ end
62
+
37
63
  def initialize
38
- @title = nil
39
- @allotted_time = nil
40
- @slide_conf = nil
41
- @author_conf = nil
64
+ @use_gui = true
65
+ @data = Data.new
42
66
  @logger = nil
43
67
  end
44
68
 
45
69
  def run(arguments)
46
70
  parse_command_line_arguments(arguments)
47
71
 
72
+ if @use_gui
73
+ return false unless show_gui
74
+ end
75
+
48
76
  validate
49
77
  unless @validation_errors.empty?
50
78
  messages = (@validation_errors + [_("See --help for example")])
@@ -53,7 +81,7 @@ module Rabbit
53
81
  end
54
82
 
55
83
  run_command
56
- @author_conf.save
84
+ @data.save
57
85
  true
58
86
  end
59
87
 
@@ -68,10 +96,10 @@ module Rabbit
68
96
  def setup_options(parser, options)
69
97
  @options = options
70
98
  @logger = @options.default_logger
71
- @author_conf = AuthorConfiguration.new(@logger)
72
- @author_conf.load
73
- @slide_conf = SlideConfiguration.new(@logger)
74
- @slide_conf.author = @author_conf
99
+ @data.author_conf = AuthorConfiguration.new(@logger)
100
+ @data.author_conf.load
101
+ @data.slide_conf = SlideConfiguration.new(@logger)
102
+ @data.slide_conf.author = @data.author_conf
75
103
 
76
104
  format = _("Usage: %s COMMAND [OPTIONS]\n" \
77
105
  " e.g.: %s new \\\n" \
@@ -92,6 +120,13 @@ module Rabbit
92
120
  parser.separator(_(" new: create a new slide"))
93
121
  parser.separator(_(" change: change an existing slide"))
94
122
 
123
+ parser.separator("")
124
+ parser.separator(_("User interface"))
125
+ parser.on("--no-use-gui",
126
+ _("Don't use GUI")) do |boolean|
127
+ @use_gui = boolean
128
+ end
129
+
95
130
  parser.separator("")
96
131
  parser.separator(_("Slide information"))
97
132
 
@@ -99,7 +134,7 @@ module Rabbit
99
134
  _("Slide ID"),
100
135
  _("(e.g.: %s)") % "--id=rubykaigi2012",
101
136
  _("(must)")) do |id|
102
- @slide_conf.id = id
137
+ @data.slide_conf.id = id
103
138
  end
104
139
 
105
140
  messages = [
@@ -109,30 +144,38 @@ module Rabbit
109
144
  ]
110
145
  parser.on("--base-name=NAME",
111
146
  *messages) do |base_name|
112
- @slide_conf.base_name = base_name
147
+ @data.slide_conf.base_name = base_name
113
148
  end
114
149
 
115
- available_markup_languages = [:rd, :hiki, :markdown]
116
- label = "[" + available_markup_languages.join(", ") + "]"
150
+ available_markup_languages = @data.available_markup_languages
151
+ label = "[" + available_markup_languages.keys.join(", ") + "]"
117
152
  messages = [
118
153
  _("Markup language for the new slide"),
119
154
  _("(e.g.: %s)") % "--markup-language=rd",
120
155
  _("(available markup languages: %s)") % label,
121
156
  ]
122
- if @author_conf.markup_language
123
- messages << _("(default: %s)") % @author_conf.markup_language
157
+ if @data.author_conf.markup_language
158
+ messages << _("(default: %s)") % @data.author_conf.markup_language
124
159
  end
125
160
  messages << _("(optional)")
126
- parser.on("--markup-language=LANGUAGE", available_markup_languages,
161
+ parser.on("--markup-language=LANGUAGE", available_markup_languages.keys,
127
162
  *messages) do |language|
128
- @author_conf.markup_language = language
163
+ @data.author_conf.markup_language = language
129
164
  end
130
165
 
131
166
  parser.on("--title=TITLE",
132
167
  _("Title of the new slide"),
133
168
  _("(e.g.: %s)") % _("--title=\"Rabbit Introduction\""),
134
169
  _("(optional)")) do |title|
135
- @title = title
170
+ @data.title = title
171
+ end
172
+
173
+ parser.on("--licenses=LICENSE,LICENSE,...",
174
+ Array,
175
+ _("License of the new slide"),
176
+ _("(e.g.: %s)") % "--licenses=CC-BY-SA-4.0,GFDL-1.3-or-later",
177
+ _("(optional)")) do |licenses|
178
+ @data.slide_conf.licenses.concat(licenses)
136
179
  end
137
180
 
138
181
  parser.on("--tags=TAG,TAG,...",
@@ -140,21 +183,39 @@ module Rabbit
140
183
  _("Tags of the new slide"),
141
184
  _("(e.g.: %s)") % "--tags=rabbit,presentation,ruby",
142
185
  _("(optional)")) do |tags|
143
- @slide_conf.tags.concat(tags)
186
+ @data.slide_conf.tags.concat(tags)
144
187
  end
145
188
 
146
189
  parser.on("--allotted-time=TIME",
147
190
  _("Allotted time in presentaion"),
148
191
  _("(e.g.: %s)") % "--allotted-time=5m",
149
192
  _("(optional)")) do |allotted_time|
150
- @allotted_time = allotted_time
193
+ @data.allotted_time = allotted_time
151
194
  end
152
195
 
153
- parser.on("--presentation-date=DATE",
196
+ parser.on("--presentation-date=DATE", Date,
154
197
  _("Presentation date with the new slide"),
155
- _("(e.g.: %s)") % "--presentation-date=2012/06/29",
198
+ _("(e.g.: %s)") % "--presentation-date=2012-06-29",
156
199
  _("(optional)")) do |date|
157
- @slide_conf.presentation_date = date
200
+ @data.slide_conf.presentation_date = date
201
+ end
202
+
203
+ presentation_start_time_example =
204
+ "--presentation-start-time=2012-06-29T10:30:00+0900"
205
+ parser.on("--presentation-start-time=TIME", Time,
206
+ _("Presentation start time"),
207
+ _("(e.g.: %s)") % presentation_start_time_example,
208
+ _("(optional)")) do |time|
209
+ @data.slide_conf.presentation_start_time = time
210
+ end
211
+
212
+ presentation_end_time_example =
213
+ "--presentation-end-time=2012-06-29T11:00:00+0900"
214
+ parser.on("--presentation-end-time=TIME", Time,
215
+ _("Presentation end time"),
216
+ _("(e.g.: %s)") % presentation_end_time_example,
217
+ _("(optional)")) do |time|
218
+ @data.slide_conf.presentation_end_time = time
158
219
  end
159
220
 
160
221
  parser.separator(_("Your information"))
@@ -163,26 +224,26 @@ module Rabbit
163
224
  _("Author name of the new slide"),
164
225
  _("(e.g.: %s)") % "--name=\"Kouhei Sutou\"",
165
226
  ]
166
- if @author_conf.name
167
- messages << _("(default: %s)") % @author_conf.name
227
+ if @data.author_conf.name
228
+ messages << _("(default: %s)") % @data.author_conf.name
168
229
  end
169
230
  messages << _("(optional)")
170
231
  parser.on("--name=NAME",
171
232
  *messages) do |name|
172
- @author_conf.name = name
233
+ @data.author_conf.name = name
173
234
  end
174
235
 
175
236
  messages = [
176
237
  _("Author e-mail of the new slide"),
177
238
  _("(e.g.: %s)") % "--email=kou@cozmixng.org",
178
239
  ]
179
- if @author_conf.email
180
- messages << _("(default: %s)") % @author_conf.email
240
+ if @data.author_conf.email
241
+ messages << _("(default: %s)") % @data.author_conf.email
181
242
  end
182
243
  messages << _("(optional)")
183
244
  parser.on("--email=EMAIL",
184
245
  *messages) do |email|
185
- @author_conf.email = email
246
+ @data.author_conf.email = email
186
247
  end
187
248
 
188
249
  messages = [
@@ -190,13 +251,13 @@ module Rabbit
190
251
  _("It is used to publish your slide to %s") % "RubyGems.org",
191
252
  _("(e.g.: %s)") % "--rubygems-user=kou",
192
253
  ]
193
- if @author_conf.rubygems_user
194
- messages << _("(default: %s)") % @author_conf.rubygems_user
254
+ if @data.author_conf.rubygems_user
255
+ messages << _("(default: %s)") % @data.author_conf.rubygems_user
195
256
  end
196
257
  messages << _("(optional)")
197
258
  parser.on("--rubygems-user=USER",
198
259
  *messages) do |user|
199
- @author_conf.rubygems_user = user
260
+ @data.author_conf.rubygems_user = user
200
261
  end
201
262
 
202
263
  messages = [
@@ -204,13 +265,13 @@ module Rabbit
204
265
  _("It is used to publish your slide to %s") % "SlideShare",
205
266
  _("(e.g.: %s)") % "--slideshare-user=kou",
206
267
  ]
207
- if @author_conf.slideshare_user
208
- messages << _("(default: %s)") % @author_conf.slideshare_user
268
+ if @data.author_conf.slideshare_user
269
+ messages << _("(default: %s)") % @data.author_conf.slideshare_user
209
270
  end
210
271
  messages << _("(optional)")
211
272
  parser.on("--slideshare-user=USER",
212
273
  *messages) do |user|
213
- @author_conf.slideshare_user = user
274
+ @data.author_conf.slideshare_user = user
214
275
  end
215
276
 
216
277
  messages = [
@@ -218,13 +279,13 @@ module Rabbit
218
279
  _("It is used to publish your slide to %s") % "Speaker Deck",
219
280
  _("(e.g.: %s)") % "--speaker-deck-user=kou",
220
281
  ]
221
- if @author_conf.speaker_deck_user
222
- messages << _("(default: %s)") % @author_conf.speaker_deck_user
282
+ if @data.author_conf.speaker_deck_user
283
+ messages << _("(default: %s)") % @data.author_conf.speaker_deck_user
223
284
  end
224
285
  messages << _("(optional)")
225
286
  parser.on("--speaker-deck-user=USER",
226
287
  *messages) do |user|
227
- @author_conf.speaker_deck_user = user
288
+ @data.author_conf.speaker_deck_user = user
228
289
  end
229
290
  end
230
291
 
@@ -240,6 +301,109 @@ module Rabbit
240
301
  ["new", "change"]
241
302
  end
242
303
 
304
+ class TextMapper
305
+ def initialize(data)
306
+ @data = data
307
+ end
308
+
309
+ def attach(entry)
310
+ entry.signal_connect(:notify) do |_widget, param_spec|
311
+ if param_spec.name == "text"
312
+ if valid?(_widget.text)
313
+ _widget.style_context.remove_class(Gtk::STYLE_CLASS_ERROR)
314
+ else
315
+ _widget.style_context.add_class(Gtk::STYLE_CLASS_ERROR)
316
+ end
317
+ end
318
+ end
319
+ entry.text = value if value
320
+ end
321
+
322
+ def apply(entry)
323
+ apply_value(entry.text)
324
+ end
325
+ end
326
+
327
+ class SlideIDMapper < TextMapper
328
+ private
329
+ def valid?(value)
330
+ not value.empty?
331
+ end
332
+
333
+ def value
334
+ @data.slide_conf.id
335
+ end
336
+
337
+ def apply_value(value)
338
+ @data.slide_conf.id = value
339
+ end
340
+ end
341
+
342
+ class SlideBaseNameMapper < TextMapper
343
+ private
344
+ def valid?(value)
345
+ not value.empty?
346
+ end
347
+
348
+ def value
349
+ @data.slide_conf.base_name
350
+ end
351
+
352
+ def apply_value(value)
353
+ @data.slide_conf.base_name = value
354
+ end
355
+ end
356
+
357
+ class SlideMarkupLanguageMapper
358
+ def initialize(data)
359
+ @data = data
360
+ end
361
+
362
+ def attach(combo_box)
363
+ combo_box = combo_box
364
+ @data.available_markup_languages.each do |key, value|
365
+ combo_box.append(key.to_s, value)
366
+ end
367
+ combo_box.active_id = @data.author_conf.markup_language
368
+ end
369
+
370
+ def apply(combo_box)
371
+ id = combo_box.active_id
372
+ id = id.to_sym if id
373
+ @data.author_conf.markup_language = id
374
+ end
375
+ end
376
+
377
+ def build_gui_mappers
378
+ {
379
+ "slide-id" => SlideIDMapper.new(@data),
380
+ "slide-base-name" => SlideBaseNameMapper.new(@data),
381
+ "slide-markup-language" => SlideMarkupLanguageMapper.new(@data),
382
+ }
383
+ end
384
+
385
+ def show_gui
386
+ require "rabbit/gtk"
387
+
388
+ mappers = build_gui_mappers
389
+
390
+ builder = Gtk::Builder.new(path: File.join(__dir__, "rabbit-slide.ui"))
391
+ mappers.each do |id, mapper|
392
+ mapper.attach(builder[id])
393
+ end
394
+
395
+ dialog = builder["dialog"]
396
+ case dialog.run
397
+ when Gtk::ResponseType::CANCEL, Gtk::ResponseType::DELETE_EVENT
398
+ false
399
+ else
400
+ mappers.each do |id, mapper|
401
+ mapper.apply(builder[id])
402
+ end
403
+ true
404
+ end
405
+ end
406
+
243
407
  def validate
244
408
  @validation_errors = []
245
409
  validate_command
@@ -260,13 +424,13 @@ module Rabbit
260
424
  end
261
425
 
262
426
  def validate_id
263
- if @slide_conf.id.nil?
427
+ if @data.slide_conf.id.nil?
264
428
  @validation_errors << (_("%s is missing") % "--id")
265
429
  end
266
430
  end
267
431
 
268
432
  def validate_base_name
269
- if @slide_conf.base_name.nil?
433
+ if @data.slide_conf.base_name.nil?
270
434
  @validation_errors << (_("%s is missing") % "--base-name")
271
435
  end
272
436
  end
@@ -288,9 +452,9 @@ module Rabbit
288
452
  def merge_config_yaml
289
453
  existing_slide_conf = SlideConfiguration.new(@logger)
290
454
  existing_slide_conf.load
291
- existing_slide_conf.merge!(@slide_conf.to_hash)
292
- @slide_conf = existing_slide_conf
293
- @author_conf = @slide_conf.author
455
+ existing_slide_conf.merge!(@data.slide_conf.to_hash)
456
+ @data.slide_conf = existing_slide_conf
457
+ @data.author_conf = @data.slide_conf.author
294
458
  end
295
459
 
296
460
  def generate_directory
@@ -320,8 +484,8 @@ EOD
320
484
  def generate_dot_rabbit
321
485
  create_file(".rabbit") do |dot_rabbit|
322
486
  options = []
323
- if @author_conf.markup_language.nil? and @allotted_time
324
- options << "--allotted-time #{@allotted_time}"
487
+ if @data.author_conf.markup_language.nil? and @data.allotted_time
488
+ options << "--allotted-time #{@data.allotted_time}"
325
489
  end
326
490
  options << slide_path
327
491
  dot_rabbit.puts(options.join("\n"))
@@ -329,7 +493,7 @@ EOD
329
493
  end
330
494
 
331
495
  def generate_slide_configuration
332
- @slide_conf.save(base_directory)
496
+ @data.slide_conf.save(base_directory)
333
497
  end
334
498
 
335
499
  def generate_readme
@@ -339,11 +503,11 @@ EOD
339
503
  end
340
504
 
341
505
  def readme_content
342
- markup_language = @author_conf.markup_language || :rd
506
+ markup_language = @data.markup_language
343
507
  generator = Rabbit::SourceGenerator.find(markup_language)
344
508
 
345
509
  content = ""
346
- title = @title || _("TODO: SLIDE TITLE")
510
+ title = @data.title || _("TODO: SLIDE TITLE")
347
511
  content << generator.heading(1, title)
348
512
  content << "\n\n"
349
513
  content << _("TODO: SLIDE DESCRIPTION")
@@ -364,12 +528,12 @@ EOD
364
528
  content << "\n\n"
365
529
  content << generator.heading(3, _("Install"))
366
530
  content << "\n\n"
367
- install_command = "gem install #{@slide_conf.gem_name}"
531
+ install_command = "gem install #{@data.slide_conf.gem_name}"
368
532
  content << generator.preformatted_line(install_command)
369
533
  content << "\n\n"
370
534
  content << generator.heading(3, _("Show"))
371
535
  content << "\n\n"
372
- show_command = "rabbit #{@slide_conf.gem_name}.gem"
536
+ show_command = "rabbit #{@data.slide_conf.gem_name}.gem"
373
537
  content << generator.preformatted_line(show_command)
374
538
  content << "\n\n"
375
539
  end
@@ -386,7 +550,7 @@ Rabbit::Task::Slide.new do |task|
386
550
  spec = task.spec
387
551
  # spec.files += Dir.glob("doc/**/*.*")
388
552
  # spec.files -= Dir.glob("private/**/*.*")
389
- # spec.add_runtime_dependency("YOUR THEME")
553
+ # spec.add_runtime_dependency("rabbit-theme-YOUR-THEME")
390
554
  end
391
555
 
392
556
  desc "Tag #{spec.version}"
@@ -407,11 +571,11 @@ end
407
571
  end
408
572
 
409
573
  def slide_path
410
- "#{@slide_conf.base_name}.#{slide_source_extension}"
574
+ "#{@data.slide_conf.base_name}.#{slide_source_extension}"
411
575
  end
412
576
 
413
577
  def slide_source_extension
414
- case @author_conf.markup_language
578
+ case @data.author_conf.markup_language
415
579
  when :rd
416
580
  "rab"
417
581
  when :hiki
@@ -424,7 +588,7 @@ end
424
588
  end
425
589
 
426
590
  def readme_extension
427
- case @author_conf.markup_language
591
+ case @data.author_conf.markup_language
428
592
  when :rd
429
593
  "rd"
430
594
  when :hiki
@@ -437,7 +601,7 @@ end
437
601
  end
438
602
 
439
603
  def slide_source
440
- generator = Rabbit::SourceGenerator.find(@author_conf.markup_language)
604
+ generator = Rabbit::SourceGenerator.find(@data.markup_language)
441
605
  return nil if generator.nil?
442
606
 
443
607
  source = ""
@@ -455,15 +619,36 @@ end
455
619
  end
456
620
 
457
621
  def slide_source_metadata(source, generator)
458
- presentation_date = @slide_conf.presentation_date
622
+ presentation_date = @data.slide_conf.presentation_date
623
+ presentation_date_default = Time.now
624
+ allotted_time_default = "5m"
625
+ allotted_time =
626
+ Utils.ensure_time(@data.allotted_time || allotted_time_default)
627
+ start_time = @data.slide_conf.presentation_start_time
628
+ end_time = @data.slide_conf.presentation_end_time
629
+ if presentation_date
630
+ start_time ||= presentation_date
631
+ end_time ||= presentation_date + allotted_time
632
+ presentation_date = presentation_date.strftime("%Y-%m-%d")
633
+ end
634
+ start_time = start_time.iso8601 if start_time
635
+ end_time = end_time.iso8601 if end_time
636
+ start_time_default = presentation_date_default
637
+ end_time_default = start_time_default + allotted_time
459
638
  slide_metadata = [
460
- ["subtitle", nil, _("SUBTITLE")],
461
- ["author", @author_conf.name, _("AUTHOR")],
462
- ["institution", nil, _("INSTITUTION")],
463
- ["content-source", nil, _("EVENT NAME")],
464
- ["date", presentation_date, Time.now.strftime("%Y-%m-%d")],
465
- ["allotted-time", @allotted_time, "5m"],
466
- ["theme", nil, "default"],
639
+ ["subtitle", nil, _("SUBTITLE")],
640
+ ["author", @data.author_conf.name, _("AUTHOR")],
641
+ ["institution", nil, _("INSTITUTION")],
642
+ ["content-source", nil, _("EVENT NAME")],
643
+ [
644
+ "date",
645
+ presentation_date,
646
+ presentation_date_default.strftime("%Y-%m-%d"),
647
+ ],
648
+ ["allotted-time", @data.allotted_time, "5m"],
649
+ ["start-time", start_time, start_time_default.iso8601],
650
+ ["end-time", end_time, end_time_default.iso8601],
651
+ ["theme", nil, "default"],
467
652
  ]
468
653
  slide_metadata.each do |key, value, default_value|
469
654
  item = generator.definition_list_item(key, value || default_value)
@@ -501,7 +686,7 @@ end
501
686
  when "change"
502
687
  "."
503
688
  else
504
- @slide_conf.id
689
+ @data.slide_conf.id
505
690
  end
506
691
  end
507
692