glimmer-dsl-libui 0.2.19 → 0.2.23

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,145 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require_relative 'cell'
23
+
24
+ class TicTacToe
25
+ class Board
26
+ DRAW = :draw
27
+ IN_PROGRESS = :in_progress
28
+ WIN = :win
29
+ attr :winning_sign
30
+ attr_accessor :game_status
31
+
32
+ def initialize
33
+ @sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
34
+ build_grid
35
+ @winning_sign = Cell::EMPTY
36
+ @game_status = IN_PROGRESS
37
+ end
38
+
39
+ #row and column numbers are 1-based
40
+ def mark(row, column)
41
+ self[row, column].mark(current_sign)
42
+ game_over? #updates winning sign
43
+ end
44
+
45
+ def current_sign
46
+ @current_sign = @sign_state_machine[@current_sign]
47
+ end
48
+
49
+ def [](row, column)
50
+ @grid[row-1][column-1]
51
+ end
52
+
53
+ def game_over?
54
+ win? or draw?
55
+ end
56
+
57
+ def win?
58
+ win = (row_win? or column_win? or diagonal_win?)
59
+ self.game_status=WIN if win
60
+ win
61
+ end
62
+
63
+ def reset!
64
+ (1..3).each do |row|
65
+ (1..3).each do |column|
66
+ self[row, column].reset!
67
+ end
68
+ end
69
+ @winning_sign = Cell::EMPTY
70
+ @current_sign = nil
71
+ self.game_status=IN_PROGRESS
72
+ end
73
+
74
+ private
75
+
76
+ def build_grid
77
+ @grid = []
78
+ 3.times do |row_index| #0-based
79
+ @grid << []
80
+ 3.times { @grid[row_index] << Cell.new }
81
+ end
82
+ end
83
+
84
+ def row_win?
85
+ (1..3).each do |row|
86
+ if row_has_same_sign(row)
87
+ @winning_sign = self[row, 1].sign
88
+ return true
89
+ end
90
+ end
91
+ false
92
+ end
93
+
94
+ def column_win?
95
+ (1..3).each do |column|
96
+ if column_has_same_sign(column)
97
+ @winning_sign = self[1, column].sign
98
+ return true
99
+ end
100
+ end
101
+ false
102
+ end
103
+
104
+ #needs refactoring if we ever decide to make the board size dynamic
105
+ def diagonal_win?
106
+ if (self[1, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[3, 3].sign) and self[1, 1].marked
107
+ @winning_sign = self[1, 1].sign
108
+ return true
109
+ end
110
+ if (self[3, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[1, 3].sign) and self[3, 1].marked
111
+ @winning_sign = self[3, 1].sign
112
+ return true
113
+ end
114
+ false
115
+ end
116
+
117
+ def draw?
118
+ @board_full = true
119
+ 3.times do |x|
120
+ 3.times do |y|
121
+ @board_full = false if self[x, y].empty
122
+ end
123
+ end
124
+ self.game_status = DRAW if @board_full
125
+ @board_full
126
+ end
127
+
128
+ def row_has_same_sign(number)
129
+ row_sign = self[number, 1].sign
130
+ [2, 3].each do |column|
131
+ return false unless row_sign == (self[number, column].sign)
132
+ end
133
+ true if self[number, 1].marked
134
+ end
135
+
136
+ def column_has_same_sign(number)
137
+ column_sign = self[1, number].sign
138
+ [2, 3].each do |row|
139
+ return false unless column_sign == (self[row, number].sign)
140
+ end
141
+ true if self[1, number].marked
142
+ end
143
+
144
+ end
145
+ end
@@ -0,0 +1,48 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ class TicTacToe
23
+ class Cell
24
+ EMPTY = ""
25
+ attr_accessor :sign, :empty
26
+
27
+ def initialize
28
+ reset!
29
+ end
30
+
31
+ def mark(sign)
32
+ self.sign = sign
33
+ end
34
+
35
+ def reset!
36
+ self.sign = EMPTY
37
+ end
38
+
39
+ def sign=(sign_symbol)
40
+ @sign = sign_symbol
41
+ self.empty = sign == EMPTY
42
+ end
43
+
44
+ def marked
45
+ !empty
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,85 @@
1
+ require 'glimmer-dsl-libui'
2
+
3
+ require_relative "tic_tac_toe/board"
4
+
5
+ class TicTacToe
6
+ include Glimmer
7
+
8
+ def initialize
9
+ @tic_tac_toe_board = Board.new
10
+ end
11
+
12
+ def launch
13
+ create_gui
14
+ register_observers
15
+ @main_window.show
16
+ end
17
+
18
+ def register_observers
19
+ Glimmer::DataBinding::Observer.proc do |game_status|
20
+ display_win_message if game_status == Board::WIN
21
+ display_draw_message if game_status == Board::DRAW
22
+ end.observe(@tic_tac_toe_board, :game_status)
23
+
24
+ 3.times.map do |row|
25
+ 3.times.map do |column|
26
+ Glimmer::DataBinding::Observer.proc do |sign|
27
+ @cells[row][column].string = sign
28
+ end.observe(@tic_tac_toe_board[row + 1, column + 1], :sign) # board model is 1-based
29
+ end
30
+ end
31
+ end
32
+
33
+ def create_gui
34
+ @main_window = window('Tic-Tac-Toe', 180, 180) {
35
+ resizable false
36
+
37
+ @cells = []
38
+ vertical_box {
39
+ padded false
40
+
41
+ 3.times.map do |row|
42
+ @cells << []
43
+ horizontal_box {
44
+ padded false
45
+
46
+ 3.times.map do |column|
47
+ area {
48
+ path {
49
+ square(0, 0, 60)
50
+
51
+ stroke :black, thickness: 2
52
+ }
53
+ text(23, 19) {
54
+ @cells[row] << string('') {
55
+ font family: 'Arial', size: OS.mac? ? 20 : 16
56
+ }
57
+ }
58
+ on_mouse_up do
59
+ @tic_tac_toe_board.mark(row + 1, column + 1) # board model is 1-based
60
+ end
61
+ }
62
+ end
63
+ }
64
+ end
65
+ }
66
+ }
67
+ end
68
+
69
+ def display_win_message
70
+ display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
71
+ end
72
+
73
+ def display_draw_message
74
+ display_game_over_message("Draw!")
75
+ end
76
+
77
+ def display_game_over_message(message_text)
78
+ Glimmer::LibUI.queue_main do
79
+ msg_box('Game Over', message_text)
80
+ @tic_tac_toe_board.reset!
81
+ end
82
+ end
83
+ end
84
+
85
+ TicTacToe.new.launch
Binary file
@@ -78,6 +78,7 @@ module Glimmer
78
78
  when 'on_destroy'
79
79
  on_destroy(&listener)
80
80
  else
81
+ default_behavior_listener = nil
81
82
  if listener_name == 'on_closing'
82
83
  default_behavior_listener = Proc.new do
83
84
  return_value = listener.call(self)
@@ -90,9 +91,45 @@ module Glimmer
90
91
  end
91
92
  end
92
93
  end
93
- super(listener_name, &default_behavior_listener)
94
+ super(listener_name, &(default_behavior_listener || listener))
94
95
  end
95
96
  end
97
+
98
+ def content_size(*args)
99
+ if args.empty?
100
+ width = Fiddle::Pointer.malloc(8)
101
+ height = Fiddle::Pointer.malloc(8)
102
+ ::LibUI.window_content_size(@libui, width, height)
103
+ width = width[0, 8].unpack1('i')
104
+ height = height[0, 8].unpack1('i')
105
+ [width, height]
106
+ else
107
+ args = args.first if args.size == 1 && args.first.is_a?(Array)
108
+ super
109
+ @width = args[0]
110
+ @height = args[1]
111
+ end
112
+ end
113
+ alias content_size= content_size
114
+ alias set_content_size content_size
115
+
116
+ def resizable(value = nil)
117
+ if value.nil?
118
+ @resizable = true if @resizable.nil?
119
+ @resizable
120
+ else
121
+ @resizable = value
122
+ if !@resizable && !@resizable_listener_registered
123
+ handle_listener('on_content_size_changed') do
124
+ set_content_size(@width, @height) unless @resizable
125
+ end
126
+ @resizable_listener_registered = true
127
+ end
128
+ end
129
+ end
130
+ alias resizable? resizable
131
+ alias resizable= resizable
132
+ alias set_resizable resizable
96
133
 
97
134
  private
98
135
 
@@ -107,6 +144,8 @@ module Glimmer
107
144
  construction_args[2] = DEFAULT_HEIGHT if construction_args.size == 2
108
145
  construction_args[3] = DEFAULT_HAS_MENUBAR if construction_args.size == 3
109
146
  construction_args[3] = Glimmer::LibUI.boolean_to_integer(construction_args[3]) if construction_args.size == 4 && (construction_args[3].is_a?(TrueClass) || construction_args[3].is_a?(FalseClass))
147
+ @width = construction_args[1]
148
+ @height = construction_args[2]
110
149
  @libui = ControlProxy.new_control(@keyword, construction_args)
111
150
  @libui.tap do
112
151
  handle_listener('on_closing') do
data/lib/glimmer/libui.rb CHANGED
@@ -26,12 +26,12 @@ module Glimmer
26
26
  class << self
27
27
  include Glimmer::FiddleConsumer
28
28
 
29
- def integer_to_boolean(int, allow_nil: true)
30
- int.nil? ? (allow_nil ? nil : false) : ((int.is_a?(TrueClass) || int.is_a?(FalseClass)) ? int : (int.is_a?(Integer) ? int == 1 : (allow_nil ? nil : false)))
29
+ def integer_to_boolean(int, allow_nil: true, allow_boolean: true)
30
+ int.nil? ? (allow_nil ? nil : false) : (allow_boolean && (int.is_a?(TrueClass) || int.is_a?(FalseClass)) ? int : (int.is_a?(Integer) ? int == 1 : (allow_nil ? nil : false)))
31
31
  end
32
32
 
33
- def boolean_to_integer(bool, allow_nil: true)
34
- bool.nil? ? (allow_nil ? nil : 0) : (bool.is_a?(Integer) ? bool : (bool.is_a?(TrueClass) || bool.is_a?(FalseClass) ? (bool == true ? 1 : 0) : (allow_nil ? nil : 0)))
33
+ def boolean_to_integer(bool, allow_nil: true, allow_integer: true)
34
+ bool.nil? ? (allow_nil ? nil : 0) : (allow_integer && bool.is_a?(Integer) ? bool : (bool.is_a?(TrueClass) || bool.is_a?(FalseClass) ? (bool == true ? 1 : 0) : (allow_nil ? nil : 0)))
35
35
  end
36
36
 
37
37
  def degrees_to_radians(degrees)
@@ -100,11 +100,39 @@ module Glimmer
100
100
  enum_symbol_values(enum_name).keys
101
101
  end
102
102
 
103
+ def enum_names
104
+ [
105
+ :align,
106
+ :at,
107
+ :attribute_type,
108
+ :draw_brush_type,
109
+ :draw_fill_mode,
110
+ :draw_line_cap,
111
+ :draw_line_join,
112
+ :draw_text_align,
113
+ :ext_key,
114
+ :modifier,
115
+ :table_model_column,
116
+ :table_value_type,
117
+ :text_italic,
118
+ :text_stretch,
119
+ :text_weight,
120
+ :underline,
121
+ :underline_color
122
+ ]
123
+ end
124
+
103
125
  # Returns ruby underscored symbols for enum values starting with enum name (camelcase, e.g. 'ext_key')
104
126
  def enum_symbol_values(enum_name)
105
127
  enum_name = enum_name.to_s.underscore.to_sym
106
128
  @enum_symbols ||= {}
107
- @enum_symbols[enum_name] ||= ::LibUI.constants.select { |c| c.to_s.start_with?(enum_name.to_s.camelcase(:upper)) }.map { |c| [c.to_s.underscore.sub("#{enum_name}_", '').to_sym, ::LibUI.const_get(c)] }.to_h
129
+ @enum_symbols[enum_name] ||= ::LibUI.constants.select do |c|
130
+ c.to_s.match(/#{enum_name.to_s.camelcase(:upper)}[A-Z]/)
131
+ end.map do |c|
132
+ [c.to_s.underscore.sub("#{enum_name}_", '').to_sym, ::LibUI.const_get(c)]
133
+ end.reject do |key, value|
134
+ enum_name == :underline && key.to_s.start_with?('color')
135
+ end.to_h
108
136
  end
109
137
 
110
138
  def enum_value_to_symbol(enum_name, enum_value)
@@ -145,7 +173,7 @@ module Glimmer
145
173
  # If block returns true at any point, the timer continues for another repetition regardless of `repeat:` keyword arg value
146
174
  def timer(time_in_seconds = 0.1, repeat: true, &block)
147
175
  closure = fiddle_closure_block_caller(4, [0]) do
148
- result = boolean_to_integer(block.call)
176
+ result = boolean_to_integer(block.call, allow_integer: false)
149
177
  repeat -= 1 if repeat.is_a?(Integer)
150
178
  if result.nil?
151
179
  if (repeat == true || (repeat.is_a?(Integer) && repeat > 0))
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-libui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.19
4
+ version: 0.2.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-04 00:00:00.000000000 Z
11
+ date: 2021-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -252,11 +252,21 @@ files:
252
252
  - examples/method_based_custom_keyword.rb
253
253
  - examples/midi_player.rb
254
254
  - examples/simple_notepad.rb
255
+ - examples/snake.rb
256
+ - examples/snake/model/apple.rb
257
+ - examples/snake/model/game.rb
258
+ - examples/snake/model/snake.rb
259
+ - examples/snake/model/vertebra.rb
260
+ - examples/snake/presenter/cell.rb
261
+ - examples/snake/presenter/grid.rb
255
262
  - examples/tetris.rb
256
263
  - examples/tetris/model/block.rb
257
264
  - examples/tetris/model/game.rb
258
265
  - examples/tetris/model/past_game.rb
259
266
  - examples/tetris/model/tetromino.rb
267
+ - examples/tic_tac_toe.rb
268
+ - examples/tic_tac_toe/board.rb
269
+ - examples/tic_tac_toe/cell.rb
260
270
  - examples/timer.rb
261
271
  - glimmer-dsl-libui.gemspec
262
272
  - icons/glimmer.png