glimmer-dsl-swt 4.18.1.0 → 4.18.2.3

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.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -30,7 +30,8 @@ module Glimmer
30
30
  args.size > 0 and
31
31
  parent.respond_to?(:set_attribute) and
32
32
  parent.respond_to?(:has_attribute?) and
33
- parent.has_attribute?(keyword, *args)
33
+ parent.has_attribute?(keyword, *args) and
34
+ !(parent.respond_to?(:swt_widget) && parent.swt_widget.class == org.eclipse.swt.widgets.Canvas && keyword == 'image')
34
35
  end
35
36
 
36
37
  def interpret(parent, keyword, *args, &block)
@@ -39,7 +39,7 @@ module Glimmer
39
39
  end
40
40
 
41
41
  def interpret(parent, keyword, *args, &block)
42
- Glimmer::SWT::Custom::Shape.new(parent, keyword, *args)
42
+ Glimmer::SWT::Custom::Shape.new(parent, keyword, *args, &block)
43
43
  end
44
44
 
45
45
  def add_content(parent, &block)
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -57,11 +57,11 @@ module Glimmer
57
57
  lines = `gem search -d #{gem_prefix}`.split("\n")
58
58
  gems = lines.slice_before {|l| l.match(REGEX_GEM_LINE) }.to_a
59
59
  gems = gems.map do |gem|
60
- {
60
+ {
61
61
  name: gem[0].match(REGEX_GEM_LINE)[1],
62
62
  version: gem[0].match(REGEX_GEM_LINE)[2],
63
63
  author: gem[1].strip,
64
- description: gem[4..-1].map(&:strip).join(' ')
64
+ description: gem[4..-1]&.map(&:strip)&.join(' ').to_s
65
65
  }
66
66
  end.select do |gem|
67
67
  query.nil? || "#{gem[:name]} #{gem[:author]} #{gem[:description]}".downcase.include?(query.to_s.downcase)
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -27,7 +27,7 @@ module Glimmer
27
27
  module Package
28
28
  class << self
29
29
  attr_accessor :javapackager_extra_args
30
- alias jpackage_extra_args :javapackager_extra_args
30
+ alias jpackage_extra_args javapackager_extra_args
31
31
 
32
32
  def clean
33
33
  require 'fileutils'
@@ -48,7 +48,7 @@ module Glimmer
48
48
  FileUtils.mkdir_p('vendor/jars')
49
49
  command = "lock_jars --vendor-dir vendor/jars"
50
50
  puts command
51
- system command
51
+ system command
52
52
  end
53
53
 
54
54
  def config
@@ -78,18 +78,18 @@ module Glimmer
78
78
  else
79
79
  puts 'Warbler executable "warble" is missing!'
80
80
  end
81
- end
81
+ end
82
82
  end
83
83
 
84
84
  def jar
85
85
  FileUtils.mkdir_p('dist')
86
86
  puts "Generating JAR with Warbler..."
87
87
  system "jruby -S gem install warbler -v2.0.5 --no-document" unless warbler_exists?
88
- system('warble')
88
+ system('warble')
89
89
  end
90
90
 
91
91
  def native(native_type=nil, native_extra_args)
92
- puts "Generating native executable with javapackager/jpackage..."
92
+ puts "Generating native executable with javapackager/jpackage..."
93
93
  java_version = `java -version`
94
94
  puts "WARNING! Glimmer Packaging Pre-Requisite Java Version 1.8.0_241 Is Not Found!" unless java_version.include?('1.8.0_241')
95
95
  require 'facets/string/titlecase'
@@ -125,7 +125,7 @@ module Glimmer
125
125
  command += " #{ENV['JAVAPACKAGER_EXTRA_ARGS']} " if ENV['JAVAPACKAGER_EXTRA_ARGS']
126
126
  command += " #{native_extra_args} " if native_extra_args
127
127
  puts command
128
- system command
128
+ system command
129
129
  end
130
130
 
131
131
  private
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -42,6 +42,7 @@ module Glimmer
42
42
  *.gem
43
43
  *.rbc
44
44
  /.config
45
+ /.mvn/
45
46
  /coverage/
46
47
  /InstalledFiles
47
48
  /pkg/
@@ -97,9 +98,9 @@ module Glimmer
97
98
  .gladiator
98
99
 
99
100
  # Glimmer
100
- dist
101
- packages
102
- vendor/jars
101
+ /dist/
102
+ /packages/
103
+ /vendor/jars/
103
104
  MULTI_LINE_STRING
104
105
 
105
106
  GEMFILE = <<~MULTI_LINE_STRING
@@ -113,7 +114,6 @@ module Glimmer
113
114
 
114
115
  group :development do
115
116
  gem 'rspec', '~> 3.5.0'
116
- gem 'git-glimmer', '1.7.0'
117
117
  gem 'juwelier', '2.4.9'
118
118
  gem 'warbler', '2.0.5'
119
119
  gem 'simplecov', '>= 0'
@@ -133,12 +133,12 @@ module Glimmer
133
133
  gem_summary = human_name(app_name)
134
134
  return puts("The directory '#{gem_name}' already exists. Please either remove or pick a different name.") if Dir.exist?(gem_name)
135
135
  system "jruby -S gem install juwelier -v2.4.9 --no-document" unless juwelier_exists?
136
- system "jruby -r git-glimmer -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
136
+ system "jruby -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
137
137
  return puts('Your Git user.name and/or github.user are missing! Please add in for Juwelier to help Glimmer with Scaffolding.') if `git config --get github.user`.strip.empty? && `git config --get user.name`.strip.empty?
138
138
  cd gem_name
139
139
  rm_rf 'lib'
140
140
  write '.gitignore', GITIGNORE
141
- write '.ruby-version', RUBY_VERSION
141
+ write '.ruby-version', RUBY_VERSION
142
142
  write '.ruby-gemset', app_name
143
143
  write 'VERSION', '1.0.0'
144
144
  write 'LICENSE.txt', "Copyright (c) #{Time.now.year} #{app_name}"
@@ -178,7 +178,7 @@ module Glimmer
178
178
  system "bundle"
179
179
  system "rspec --init"
180
180
  else
181
- system "bash -c '#{RVM_FUNCTION}\n cd .\n bundle\n rspec --init\n'"
181
+ system "bash -c '#{RVM_FUNCTION}\n cd .\n bundle\n rspec --init\n'"
182
182
  end
183
183
  write 'spec/spec_helper.rb', spec_helper_file
184
184
  if OS.windows?
@@ -191,7 +191,7 @@ module Glimmer
191
191
  else
192
192
  system "glimmer run"
193
193
  end
194
- end
194
+ end
195
195
  end
196
196
 
197
197
  def custom_shell(custom_shell_name, namespace, shell_type = nil, shell_options = {})
@@ -231,11 +231,11 @@ module Glimmer
231
231
  end
232
232
  return puts("The directory '#{gem_name}' already exists. Please either remove or pick a different name.") if Dir.exist?(gem_name)
233
233
  system "jruby -S gem install juwelier -v2.4.9 --no-document" unless juwelier_exists?
234
- system "jruby -r git-glimmer -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
234
+ system "jruby -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
235
235
  return puts('Your Git user.name and/or github.user are missing! Please add in for Juwelier to help Glimmer with Scaffolding.') if `git config --get github.user`.strip.empty? && `git config --get user.name`.strip.empty?
236
236
  cd gem_name
237
237
  write '.gitignore', GITIGNORE
238
- write '.ruby-version', RUBY_VERSION
238
+ write '.ruby-version', RUBY_VERSION
239
239
  write '.ruby-gemset', gem_name
240
240
  write 'VERSION', '1.0.0'
241
241
  write 'Gemfile', GEMFILE
@@ -256,7 +256,7 @@ module Glimmer
256
256
  system "rspec --init"
257
257
  else
258
258
  system "bash -c '#{RVM_FUNCTION}\n cd .\n bundle\n rspec --init\n'"
259
- end
259
+ end
260
260
  write 'spec/spec_helper.rb', spec_helper_file
261
261
 
262
262
  mkdir_p 'package/windows'
@@ -283,7 +283,7 @@ module Glimmer
283
283
  system "open packages/bundles/#{human_name(custom_shell_name).gsub(' ', '\ ')}.app" if OS.mac?
284
284
  else
285
285
  system "glimmer run"
286
- end
286
+ end
287
287
  end
288
288
  puts "Finished creating #{gem_name} Ruby gem."
289
289
  puts 'Edit Rakefile to configure gem details.'
@@ -305,11 +305,11 @@ module Glimmer
305
305
 
306
306
  return puts("The directory '#{gem_name}' already exists. Please either remove or pick a different name.") if Dir.exist?(gem_name)
307
307
  system "jruby -S gem install juwelier -v2.4.9 --no-document" unless juwelier_exists?
308
- system "jruby -r git-glimmer -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
308
+ system "jruby -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
309
309
  return puts('Your Git user.name and/or github.user are missing! Please add in for Juwelier to help Glimmer with Scaffolding.') if `git config --get github.user`.strip.empty? && `git config --get user.name`.strip.empty?
310
310
  cd gem_name
311
311
  write '.gitignore', GITIGNORE
312
- write '.ruby-version', RUBY_VERSION
312
+ write '.ruby-version', RUBY_VERSION
313
313
  write '.ruby-gemset', gem_name
314
314
  write 'VERSION', '1.0.0'
315
315
  write 'Gemfile', GEMFILE
@@ -397,9 +397,9 @@ module Glimmer
397
397
  class #{class_name(app_name)}
398
398
  include Glimmer
399
399
 
400
- APP_ROOT = File.expand_path('../..', __FILE__)
400
+ APP_ROOT = File.expand_path('../..', __FILE__)
401
401
  VERSION = File.read(File.join(APP_ROOT, 'VERSION'))
402
- LICENSE = File.read(File.join(APP_ROOT, 'LICENSE.txt'))
402
+ LICENSE = File.read(File.join(APP_ROOT, 'LICENSE.txt'))
403
403
 
404
404
  def open
405
405
  app_view.open
@@ -443,7 +443,7 @@ module Glimmer
443
443
 
444
444
  launcher = Glimmer::Launcher.new([runner] + ARGV)
445
445
  launcher.launch
446
- end
446
+ end
447
447
  MULTI_LINE_STRING
448
448
  end
449
449
 
@@ -482,7 +482,7 @@ module Glimmer
482
482
 
483
483
  launcher = Glimmer::Launcher.new([runner] + ARGV)
484
484
  launcher.launch
485
- end
485
+ end
486
486
  MULTI_LINE_STRING
487
487
  end
488
488
 
@@ -502,15 +502,15 @@ module Glimmer
502
502
  end
503
503
  spec_pattern_line_index = lines.index(lines.detect {|l| l.include?('spec.pattern =') })
504
504
  lines.insert(spec_pattern_line_index+1, " spec.ruby_opts = [Glimmer::Launcher.jruby_os_specific_options]")
505
- lines << "\nrequire 'glimmer/rake_task'\n"
505
+ lines << "\nrequire 'glimmer/rake_task'\n"
506
506
  file_content = lines.join("\n")
507
507
  if custom_shell_name
508
- file_content << <<~MULTI_LINE_STRING
508
+ file_content << <<~MULTI_LINE_STRING
509
509
  Glimmer::RakeTask::Package.javapackager_extra_args =
510
510
  " -name '#{human_name(custom_shell_name)}'" +
511
511
  " -title '#{human_name(custom_shell_name)}'" +
512
512
  " -Bmac.CFBundleName='#{human_name(custom_shell_name)}'" +
513
- " -Bmac.CFBundleIdentifier='org.#{namespace ? compact_name(namespace) : compact_name(custom_shell_name)}.application.#{compact_name(custom_shell_name).camelcase(:upper)}'"
513
+ " -Bmac.CFBundleIdentifier='org.#{namespace ? compact_name(namespace) : compact_name(custom_shell_name)}.application.#{compact_name(custom_shell_name).camelcase(:upper)}'"
514
514
  # " -BlicenseType=" +
515
515
  # " -Bmac.category=" +
516
516
  # " -Bmac.signing-key-developer-id-app="
@@ -575,8 +575,8 @@ module Glimmer
575
575
  if %i[gem app desktopify].include?(shell_type)
576
576
  custom_shell_file_content += <<-MULTI_LINE_STRING
577
577
  before_body {
578
- Display.setAppName('#{shell_type == :gem ? human_name(custom_shell_name) : human_name(namespace)}')
579
- Display.setAppVersion(VERSION)
578
+ Display.app_name = '#{shell_type == :gem ? human_name(custom_shell_name) : human_name(namespace)}'
579
+ Display.app_version = VERSION
580
580
  @display = display {
581
581
  on_about {
582
582
  display_about_dialog
@@ -600,7 +600,7 @@ module Glimmer
600
600
  ## Use after_body block to setup observers for widgets in body
601
601
  #
602
602
  # after_body {
603
- #
603
+ #
604
604
  # }
605
605
 
606
606
  ## Add widget content inside custom shell body
@@ -616,10 +616,10 @@ module Glimmer
616
616
  MULTI_LINE_STRING
617
617
 
618
618
  if shell_type == :desktopify
619
- custom_shell_file_content += <<-MULTI_LINE_STRING
619
+ custom_shell_file_content += <<-MULTI_LINE_STRING
620
620
  browser {
621
- url "#{shell_options[:website]}"
622
- }
621
+ url "#{shell_options[:website]}"
622
+ }
623
623
  MULTI_LINE_STRING
624
624
  else
625
625
  custom_shell_file_content += <<-MULTI_LINE_STRING
@@ -628,7 +628,7 @@ module Glimmer
628
628
  text bind(self, :greeting)
629
629
  font height: 40
630
630
  layout_data :fill, :center, true, true
631
- }
631
+ }
632
632
  MULTI_LINE_STRING
633
633
  end
634
634
 
@@ -690,7 +690,7 @@ module Glimmer
690
690
  text 'Greeting'
691
691
  font style: :bold
692
692
  [
693
- 'Hello, World!',
693
+ 'Hello, World!',
694
694
  'Howdy, Partner!'
695
695
  ].each do |greeting_text|
696
696
  button(:radio) {
@@ -733,19 +733,19 @@ module Glimmer
733
733
  #
734
734
  #
735
735
  # before_body {
736
- #
736
+ #
737
737
  # }
738
738
 
739
739
  ## Use after_body block to setup observers for widgets in body
740
740
  #
741
741
  # after_body {
742
- #
742
+ #
743
743
  # }
744
744
 
745
745
  ## Add widget content under custom widget body
746
746
  ##
747
- ## If you want to add a shell as the top-most widget,
748
- ## consider creating a custom shell instead
747
+ ## If you want to add a shell as the top-most widget,
748
+ ## consider creating a custom shell instead
749
749
  ## (Glimmer::UI::CustomShell offers shell convenience methods, like show and hide)
750
750
  #
751
751
  body {
@@ -28,68 +28,127 @@ module Glimmer
28
28
  class Animation
29
29
  include Properties # TODO rename to Properties
30
30
 
31
- attr_reader :parent, :options, :frame_index
31
+ class << self
32
+ def schedule_frame_animation(animation, &frame_animation_block)
33
+ frame_animation_queue(animation).prepend(frame_animation_block)
34
+ swt_display.async_exec do
35
+ frame_animation_queue(next_animation)&.pop&.call
36
+ end
37
+ end
38
+
39
+ def next_animation
40
+ animation = nil
41
+ while frame_animation_queues.values.reduce(:+)&.any? && (animation.nil? || frame_animation_queue(animation).last.nil?)
42
+ animation = frame_animation_queues.keys[next_animation_index]
43
+ frame_animation_queues.delete(animation) if frame_animation_queues.values.reduce(:+)&.any? && !animation.nil? && frame_animation_queue(animation).empty?
44
+ end
45
+ animation
46
+ end
47
+
48
+ def next_animation_index
49
+ next_schedule_index % frame_animation_queues.keys.size
50
+ end
51
+
52
+ def next_schedule_index
53
+ unless defined? @@next_schedule_index
54
+ @@next_schedule_index = 0
55
+ else
56
+ @@next_schedule_index += 1
57
+ end
58
+ end
59
+
60
+ def frame_animation_queues
61
+ unless defined? @@frame_animation_queues
62
+ @@frame_animation_queues = {}
63
+ end
64
+ @@frame_animation_queues
65
+ end
66
+
67
+ def frame_animation_queue(animation)
68
+ frame_animation_queues[animation] ||= []
69
+ end
70
+
71
+ def swt_display
72
+ unless defined? @@swt_display
73
+ @@swt_display = DisplayProxy.instance.swt_display
74
+ end
75
+ @@swt_display
76
+ end
77
+ end
78
+
79
+ attr_reader :parent, :options, :frame_index, :cycle
32
80
  alias current_frame_index frame_index
33
- attr_accessor :frame_block, :every, :cycle, :cycle_count, :frame_count, :started
81
+ attr_accessor :frame_block, :every, :cycle_count, :frame_count, :started, :duration_limit
82
+ alias started? started
34
83
  # TODO consider supporting an async: false option
35
84
 
36
85
  def initialize(parent)
37
86
  @parent = parent
38
87
  @started = true
39
88
  @frame_index = 0
89
+ @cycle_count_index = 0
90
+ @start_number = 0 # denotes the number of starts (increments on every start)
91
+ self.class.swt_display # ensures initializing variable to set from GUI thread
40
92
  end
41
93
 
42
94
  def post_add_content
43
95
  @parent.on_widget_disposed { stop }
44
- start if @started
96
+ start if started?
45
97
  end
46
-
98
+
99
+ # Starts an animation that is indefinite or has never been started before (i.e. having `started: false` option).
100
+ # Otherwise, resumes a stopped animation that has not been completed.
47
101
  def start
48
- swt_display = Glimmer::SWT::DisplayProxy.instance.swt_display
49
- return if swt_display.is_disposed?
102
+ return if @start_number > 0 && started?
103
+ @start_number += 1
104
+ @started = true
105
+ @start_time = Time.now
106
+ @original_start_time = @start_time if @duration.nil?
107
+ # TODO track when finished in a variable for finite animations (whether by frame count, cycle count, or duration limit)
50
108
  Thread.new do
51
- frame_rendering_block = lambda do
52
- block_args = [@frame_index]
53
- block_args << @cycle[@frame_index % @cycle.length] if @cycle.is_a?(Array)
54
- swt_display.async_exec do
55
- @parent.clear_shapes
56
- @parent.content {
57
- frame_block.call(*block_args)
58
- }
59
- end
60
- @frame_index += 1
61
- sleep(every) if every.is_a?(Numeric)
62
- end
63
-
109
+ start_number = @start_number
64
110
  if cycle_count.is_a?(Integer) && cycle.is_a?(Array)
65
111
  (cycle_count * cycle.length).times do
66
- break if break_condition?
67
- begin
68
- frame_rendering_block.call
69
- rescue => e
70
- Glimmer::Config.logger.error {e}
71
- break
72
- end
112
+ break unless draw_frame(start_number)
73
113
  end
74
114
  else
75
115
  loop do
76
- break if break_condition?
77
- begin
78
- frame_rendering_block.call
79
- rescue => e
80
- Glimmer::Config.logger.error {e}
81
- break
82
- end
116
+ # this code has to be duplicated to break from a loop (break keyword only works when literally in a loop block)
117
+ break unless draw_frame(start_number)
83
118
  end
84
119
  end
85
- @started = false
86
120
  end
87
121
  end
88
122
 
89
123
  def stop
124
+ return if stopped?
90
125
  @started = false
126
+ @duration = (Time.now - @start_time) + @duration.to_f if duration_limited? && !@start_time.nil?
127
+ end
128
+
129
+ # Restarts an animation (whether indefinite or not and whether stopped or not)
130
+ def restart
131
+ @original_start_time = @start_time = nil
132
+ @duration = nil
133
+ @frame_index = 0
134
+ @cycle_count_index = 0
135
+ stop
136
+ start
137
+ end
138
+
139
+ def stopped?
140
+ !started?
91
141
  end
92
142
 
143
+ def finite?
144
+ frame_count_limited? || cycle_limited? || duration_limited?
145
+ end
146
+
147
+ def infinite?
148
+ !finite?
149
+ end
150
+ alias indefinite? infinite?
151
+
93
152
  def has_attribute?(attribute_name, *args)
94
153
  respond_to?(ruby_attribute_setter(attribute_name)) && respond_to?(ruby_attribute_getter(attribute_name))
95
154
  end
@@ -102,11 +161,79 @@ module Glimmer
102
161
  send(ruby_attribute_getter(attribute_name))
103
162
  end
104
163
 
164
+ def cycle=(*args)
165
+ if args.size == 1
166
+ if args.first.is_a?(Array)
167
+ @cycle = args.first
168
+ else
169
+ @cycle = [args.first]
170
+ end
171
+ elsif args.size > 1
172
+ @cycle = args
173
+ end
174
+ end
175
+
176
+ def cycle_enabled?
177
+ @cycle.is_a?(Array)
178
+ end
179
+
180
+ def cycle_limited?
181
+ cycle_enabled? && @cycle_count.is_a?(Integer)
182
+ end
183
+
184
+ def duration_limited?
185
+ @duration_limit.is_a?(Integer)
186
+ end
187
+
188
+ def frame_count_limited?
189
+ @frame_count.is_a?(Integer)
190
+ end
191
+
192
+ def surpassed_duration_limit?
193
+ duration_limited? && ((Time.now - @start_time) > (@duration_limit - @duration.to_f))
194
+ end
195
+
196
+ def within_duration_limit?
197
+ !surpassed_duration_limit?
198
+ end
199
+
105
200
  private
106
201
 
107
- def break_condition?
108
- !@started || (@frame_count.is_a?(Integer) && @frame_index == @frame_count)
202
+ # Returns true on success of painting a frame and false otherwise
203
+ def draw_frame(start_number)
204
+ return false if stopped? ||
205
+ start_number != @start_number ||
206
+ (frame_count_limited? && @frame_index == @frame_count) ||
207
+ (cycle_limited? && @cycle_count_index == @cycle_count) ||
208
+ surpassed_duration_limit?
209
+ block_args = [@frame_index]
210
+ block_args << @cycle[@frame_index % @cycle.length] if cycle_enabled?
211
+ current_frame_index = @frame_index
212
+ current_cycle_count_index = @cycle_count_index
213
+ self.class.schedule_frame_animation(self) do
214
+ if started? && start_number == @start_number && within_duration_limit?
215
+ @parent.clear_shapes
216
+ @parent.content {
217
+ frame_block.call(*block_args)
218
+ }
219
+ @parent.redraw
220
+ else
221
+ if stopped? && @frame_index > current_frame_index
222
+ @started = false
223
+ @frame_index = current_frame_index
224
+ @cycle_count_index = current_cycle_count_index
225
+ end
226
+ end
227
+ end
228
+ @frame_index += 1
229
+ @cycle_count_index += 1 if cycle_limited? && (@frame_index % @cycle&.length&.to_i) == 0
230
+ sleep(every) if every.is_a?(Numeric)
231
+ true
232
+ rescue => e
233
+ Glimmer::Config.logger.error {e}
234
+ false
109
235
  end
236
+
110
237
  end
111
238
 
112
239
  end