Glimmer Parking Sample
Tags: ruby, gui, dsl, desktop
Published: 2021-08-03 18:44:11

[Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) 4.20.13.13 added a new [Parking elaborate sample](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#parking) that acts as a building's parking booking system at its entrance.

![Glimmer Parking Floor 4](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-swt/master/images/glimmer-parking-floor4.png)

It leverages the [Canvas Shape DSL](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-shape-dsl) and [Canvas Transform DSL](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-transform-dsl). Also, it does not rely on data-binding for everything despite that being the flagship feature of Glimmer DSL for SWT. Glimmer aims to be pragmatic, not forcing data-binding when there are other practical approaches. The sample takes a hybrid approach, using data-binding where practical (changing parking spot color when booked) and relying on plain old observers to destroy/rebuild canvas shapes on floor changes.

```ruby
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#parking

require 'glimmer-dsl-swt'

require_relative 'parking/model/parking_presenter'
      
class Parking
  include Glimmer::UI::CustomShell
    
  FLOOR_COUNT = 4
  
  before_body do
    @parking_spots = Model::ParkingSpot::LETTERS.clone
    @parking_presenter = Model::ParkingPresenter.new(FLOOR_COUNT)
  end

  body {
    shell(:no_resize) {
      row_layout(:vertical) {
        center true
      }
    
      text 'Parking'
    
      label {
        text 'Select an available spot to park'
        font height: 30
      }
      label {
        text 'Floor:'
        font height: 20
      }
      spinner {
        minimum 1
        maximum FLOOR_COUNT
        font height: 20
        selection <=> [@parking_presenter, :selected_floor]
        
        on_widget_selected do
          @parking_spots = Model::ParkingSpot::LETTERS.clone
          @canvas.dispose_shapes
          @canvas.content {
            parking_floor
          }
        end
      }
      @canvas = canvas {
        layout_data {
          width 600
          height 600
        }
        
        background :dark_gray
        
        parking_floor
      }
    }
  }
  
  def parking_floor
    parking_quad(67.5, 0, 125)
    parking_quad(67.5, 0, 125) { |shp|
      shp.rotate(90)
    }
    parking_quad(67.5, 0, 125) { |shp|
      shp.rotate(180)
    }
    parking_quad(67.5, 0, 125) { |shp|
      shp.rotate(270)
    }
  end
        
  def parking_quad(location_x, location_y, length, &block)
    distance = (1.0/3)*length
    parking_spot(location_x, location_y, length, &block)
    parking_spot(location_x + distance, location_y, length, &block)
    parking_spot(location_x + 2*distance, location_y, length, &block)
    parking_spot(location_x + 3*distance, location_y, length, &block)
  end
      
  def parking_spot(location_x, location_y, length, &block)
    parking_spot_letter = @parking_spots.shift
    height = length
    width = (2.0/3)*length
    shape(location_x, location_y) { |the_shape|
      line_width (1.0/15)*length
      foreground :white
  
      block&.call(the_shape)
    
      rectangle(location_x, location_y, width, height) {
        background <= [
          @parking_presenter.floors[@parking_presenter.selected_floor - 1].parking_spots[parking_spot_letter],
          :booked,
          on_read: ->(b) {b ? :red : :dark_gray}
        ]
        
        text {
          x :default
          y :default
          string parking_spot_letter
          font height: 20
        }
        
        on_mouse_up do
          begin
            @parking_presenter.floors[@parking_presenter.selected_floor - 1].book!(parking_spot_letter)
            message_box {
              text 'Parking Booked!'
              message "Floor #{@parking_presenter.selected_floor} Parking Spot #{parking_spot_letter} Is Booked!"
            }.open
          rescue => e
            # No Op if already booked
          end
        end
      }
    
      line(location_x, location_y, location_x, location_y + height)
      line(location_x, location_y, location_x + width, location_y)
      line(location_x + width, location_y, location_x + width, location_y + height)
      
    }
  end
end
  
Parking.launch
```

Parking Floor 1

![Parking](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-swt/master/images/glimmer-parking.png)

Parking Floor 4

![Parking Floor 4](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-swt/master/images/glimmer-parking-floor4.png)

Clicking available parking spot M triggers a booking!

![Parking Booked](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-swt/master/images/glimmer-parking-booked.png)

Happy [Glimmering](https://github.com/AndyObtiva/glimmer-dsl-swt)!