AndyObtiva/glimmer-dsl-swt

View on GitHub
samples/elaborate/timer.rb

Summary

Maintainability
B
5 hrs
Test Coverage
require 'glimmer-dsl-swt'
require 'os'

class Timer
  include Glimmer::UI::CustomShell
  
  import 'javax.sound.sampled'

  FILE_SOUND_ALARM = File.expand_path(File.join('timer', 'sounds', 'alarm1.wav'), __dir__)
  COMMAND_KEY = OS.mac? ? :command : :ctrl
      
  ## Add options like the following to configure CustomShell by outside consumers
  #
  # options :title, :background_color
  # option :width, default: 320
  # option :height, default: 240

  attr_accessor :countdown, :min, :sec

  ## Use before_body block to pre-initialize variables to use in body
  #
  #
  before_body do
    Display.setAppName('Glimmer Timer')
    
    @display = display {
      on_about do
        display_about_dialog
      end
      
      on_preferences do
        display_about_dialog
      end
    }

    @min = 0
    @sec = 0
  end

  ## Use after_body block to setup observers for widgets in body
  #
  after_body do
    Thread.new do
      loop do
        sleep(1)
        if @countdown
          sync_exec do
            @countdown_time = Time.new(1, 1, 1, 0, min, sec)
            @countdown_time -= 1
            self.min = @countdown_time.min
            self.sec = @countdown_time.sec
            if @countdown_time.min <= 0 && @countdown_time.sec <= 0
              stop_countdown
              play_countdown_done_sound
            end
          end
        end
      end
    end
  end

  ## Add widget content inside custom shell body
  ## Top-most widget must be a shell or another custom shell
  #
  body {
    shell {
      grid_layout # 1 column
      
      # Replace example content below with custom shell content
      minimum_size (OS.windows? ? 214 : 200), 114
      text "Glimmer Timer"

      timer_menu_bar
      
      countdown_group
    }
  }
  
  def timer_menu_bar
    menu_bar {
      menu {
        text '&Action'
        
        menu_item {
          text '&Start'
          accelerator COMMAND_KEY, 's'
          enabled <= [self, :countdown, on_read: :!]
          
          on_widget_selected do
            start_countdown
          end
        }
        
        menu_item {
          text 'St&op'
          enabled <= [self, :countdown]
          accelerator COMMAND_KEY, 'o'
          
          on_widget_selected do
            stop_countdown
          end
        }
        
        unless OS.mac?
          menu_item(:separator)
          menu_item {
            text 'E&xit'
            accelerator :alt, :f4
            
            on_widget_selected do
              exit(0)
            end
          }
        end
      }
      
      menu {
        text '&Help'
                    
        menu_item {
          text '&About'
          accelerator COMMAND_KEY, :shift, 'a'
          
          on_widget_selected do
            display_about_dialog
          end
        }
      }
    }
  end
  
  def countdown_group
    group {
      # has grid layout with 1 column by default
      text 'Countdown'
      font height: 20

      countdown_group_field_composite
      
      countdown_group_button_composite
    }
  end
  
  def countdown_group_field_composite
    composite {
      row_layout {
        margin_width 0
        margin_height 0
      }
      @min_spinner = spinner {
        text_limit 2
        digits 0
        maximum 59
        selection <=> [self, :min]
        enabled <= [self, :countdown, on_read: :!]
        
        on_widget_default_selected do
          start_countdown
        end
      }
      label {
        text ':'
        font(height: 18) if OS.mac?
      }
      @sec_spinner = spinner {
        text_limit 2
        digits 0
        maximum 59
        selection <=> [self, :sec]
        enabled <= [self, :countdown, on_read: :!]
        
        on_widget_default_selected do
          start_countdown
        end
      }
    }
  end
  
  def countdown_group_button_composite
    composite {
      row_layout {
        margin_width 0
        margin_height 0
      }
      @start_button = button {
        text '&Start'
        enabled <= [self, :countdown, on_read: :!]
        
        on_widget_selected do
          start_countdown
        end
        
        on_key_pressed do |event|
          start_countdown if event.keyCode == swt(:cr)
        end
      }
      @stop_button = button {
        text 'St&op'
        enabled <= [self, :countdown]
        
        on_widget_selected do
          stop_countdown
        end
        
        on_key_pressed do |event|
          stop_countdown if event.keyCode == swt(:cr)
        end
      }
    }
  end

  def display_about_dialog
    message_box(body_root) {
      text 'About'
      message "Glimmer Timer\n\nCopyright (c) 2007-2024 Andy Maleh"
    }.open
  end
  
  def start_countdown
    self.countdown = true
    @stop_button.swt_widget.set_focus
  end

  def stop_countdown
    self.countdown = false
    @min_spinner.swt_widget.set_focus
  end

  def play_countdown_done_sound
    begin
      file_or_stream = java.io.File.new(FILE_SOUND_ALARM)
      audio_stream = AudioSystem.get_audio_input_stream(file_or_stream)
      clip = AudioSystem.clip
      clip.open(audio_stream)
      clip.start
    rescue => e
      Glimmer::Config.logger.error e.full_message
    end
  end
end

Timer.launch