glimmer 0.1.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.
- data/COPYING.LGPL +504 -0
- data/README +27 -0
- data/samples/contactmanager/contact.rb +12 -0
- data/samples/contactmanager/contact_manager.rb +65 -0
- data/samples/contactmanager/contact_manager_presenter.rb +23 -0
- data/samples/contactmanager/contact_repository.rb +27 -0
- data/samples/hello_world.rb +26 -0
- data/samples/login.rb +97 -0
- data/samples/tictactoe/tic_tac_toe.rb +67 -0
- data/samples/tictactoe/tic_tac_toe_board.rb +149 -0
- data/src/command_handler.rb +11 -0
- data/src/command_handler_chain_factory.rb +23 -0
- data/src/command_handler_chain_link.rb +22 -0
- data/src/command_handlers.rb +26 -0
- data/src/command_handlers/bind_command_handler.rb +29 -0
- data/src/command_handlers/data_binding_command_handler.rb +64 -0
- data/src/command_handlers/models/model_observer.rb +25 -0
- data/src/command_handlers/models/observable_array.rb +46 -0
- data/src/command_handlers/models/observable_model.rb +35 -0
- data/src/command_handlers/models/r_runnable.rb +14 -0
- data/src/command_handlers/models/r_shell.rb +27 -0
- data/src/command_handlers/models/r_widget.rb +146 -0
- data/src/command_handlers/models/r_widget_listener.rb +12 -0
- data/src/command_handlers/models/r_widget_packages.rb +9 -0
- data/src/command_handlers/models/table_items_updater.rb +39 -0
- data/src/command_handlers/models/widget_observer.rb +23 -0
- data/src/command_handlers/shell_command_handler.rb +18 -0
- data/src/command_handlers/swt_constant_command_handler.rb +22 -0
- data/src/command_handlers/table_column_properties_data_binding_command_handler.rb +24 -0
- data/src/command_handlers/table_items_data_binding_command_handler.rb +30 -0
- data/src/command_handlers/widget_command_handler.rb +26 -0
- data/src/command_handlers/widget_listener_command_handler.rb +35 -0
- data/src/command_handlers/widget_method_command_handler.rb +22 -0
- data/src/glimmer.rb +45 -0
- data/src/parent.rb +8 -0
- data/src/shine.rb +24 -0
- data/src/swt.rb +10 -0
- data/src/xml.rb +10 -0
- data/src/xml_command_handlers.rb +18 -0
- data/src/xml_command_handlers/html_command_handler.rb +49 -0
- data/src/xml_command_handlers/models/depth_first_search_iterator.rb +20 -0
- data/src/xml_command_handlers/models/name_space_visitor.rb +21 -0
- data/src/xml_command_handlers/models/node.rb +83 -0
- data/src/xml_command_handlers/models/node_visitor.rb +12 -0
- data/src/xml_command_handlers/models/xml_visitor.rb +62 -0
- data/src/xml_command_handlers/xml_command_handler.rb +22 -0
- data/src/xml_command_handlers/xml_name_space_command_handler.rb +34 -0
- data/src/xml_command_handlers/xml_tag_command_handler.rb +26 -0
- data/src/xml_command_handlers/xml_text_command_handler.rb +22 -0
- data/test/glimmer_constant_test.rb +36 -0
- data/test/glimmer_data_binding_test.rb +236 -0
- data/test/glimmer_listeners_test.rb +61 -0
- data/test/glimmer_shine_data_binding_test.rb +88 -0
- data/test/glimmer_table_data_binding_test.rb +135 -0
- data/test/glimmer_test.rb +233 -0
- data/test/observable_model_test.rb +27 -0
- data/test/r_widget_test.rb +52 -0
- data/test/samples/contactmanager/contact_manager_presenter_test.rb +60 -0
- data/test/samples/tictactoe/tic_tac_toe_test.rb +265 -0
- data/test/xml/glimmer_xml_test.rb +163 -0
- metadata +126 -0
data/README
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Glimmer - a JRuby DSL that enables easy and efficient authoring of user-interfaces
|
2
|
+
using the robust platform-independent Eclipse SWT library. Glimmer comes with built-in
|
3
|
+
data-binding support to greatly facilitate synchronizing UI with domain models.
|
4
|
+
|
5
|
+
Copyright (C) 2007 Annas Al Maleh
|
6
|
+
Licensed under the LGPL. See /COPYING.LGPL for more details.
|
7
|
+
|
8
|
+
Instructions for use with stand-alone SWT:
|
9
|
+
1. Download the "SWT binary and source" archive from the Eclipse site and follow their instructions.
|
10
|
+
http://download.eclipse.org/eclipse/downloads/drops/R-3.3.1.1-200710231652/details.php#SWT
|
11
|
+
2. Have your program require the swt.rb file
|
12
|
+
3. Create a class that includes the Glimmer module and you will be able to write Glimmer syntax
|
13
|
+
|
14
|
+
Instructions for use with Eclipse:
|
15
|
+
1. Download and setup Eclipse 3.3 or 3.2
|
16
|
+
2. Download and setup jRuby 1.0.2
|
17
|
+
3. Modify Java launch command in jRuby script/batch file to include SWT libraries in both:
|
18
|
+
a. Classpath; must include %ECLIPSE_HOME%/plugins/org.eclipse.swt*.jar
|
19
|
+
For example with Eclipse 3.2 on Windows, we add the following:
|
20
|
+
-cp "%CLASSPATH%;%ECLIPSE_HOME%\plugins\org.eclipse.swt.win32.win32.x86_3.2.0.v3232m.jar;%ECLIPSE_HOME%\plugins\org.eclipse.swt_3.2.0.v3232o.jar"
|
21
|
+
b. java.library.path; must point to %ECLIPSE_HOME%/plugins/org.eclipse.swt* folder
|
22
|
+
For example, with Eclipse 3.2 on Windows, we add the following:
|
23
|
+
-Djava.library.path="%ECLIPSE_HOME%\plugins\org.eclipse.swt.win32.win32.x86_3.2.0.v3232m"
|
24
|
+
4. Have your program require the glimmer.rb file
|
25
|
+
5. Create a class that includes the Glimmer module and you will be able to write Glimmer syntax
|
26
|
+
|
27
|
+
Check samples folder for examples on how to write Glimmer programs.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Copyright (C) 2007-2008 Annas Al Maleh
|
2
|
+
# Licensed under the LGPL. See /COPYING.LGPL for more details.
|
3
|
+
|
4
|
+
class Contact
|
5
|
+
attr_accessor :first_name, :last_name, :email
|
6
|
+
|
7
|
+
def initialize(attribute_map)
|
8
|
+
@first_name = attribute_map[:first_name]
|
9
|
+
@last_name = attribute_map[:last_name]
|
10
|
+
@email = attribute_map[:email]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Copyright (C) 2007-2008 Annas Al Maleh
|
2
|
+
# Licensed under the LGPL. See /COPYING.LGPL for more details.
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + "/contact_manager_presenter"
|
5
|
+
require File.dirname(__FILE__) + "/../../src/swt"
|
6
|
+
|
7
|
+
class RWidget
|
8
|
+
include_package 'org.eclipse.jface.viewers'
|
9
|
+
end
|
10
|
+
|
11
|
+
class ContactManager
|
12
|
+
extend Glimmer
|
13
|
+
|
14
|
+
include_package 'org.eclipse.swt'
|
15
|
+
include_package 'org.eclipse.swt.widgets'
|
16
|
+
include_package 'org.eclipse.swt.layout'
|
17
|
+
include_package 'org.eclipse.jface.viewers'
|
18
|
+
|
19
|
+
contact_manager_presenter = ContactManagerPresenter.new
|
20
|
+
|
21
|
+
shell {
|
22
|
+
text "Contact Manager"
|
23
|
+
composite {
|
24
|
+
composite {
|
25
|
+
layout GridLayout.new(2, false)
|
26
|
+
label {text "First &Name: "}
|
27
|
+
text {
|
28
|
+
text bind(contact_manager_presenter, :first_name)
|
29
|
+
}
|
30
|
+
label {text "&Last Name: "}
|
31
|
+
text {
|
32
|
+
text bind(contact_manager_presenter, :last_name)
|
33
|
+
}
|
34
|
+
label {text "&Email: "}
|
35
|
+
text {
|
36
|
+
text bind(contact_manager_presenter, :email)
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
table {
|
41
|
+
layout_data GridData.new(fill, fill, true, true)
|
42
|
+
table_column {
|
43
|
+
text "First Name"
|
44
|
+
width 80
|
45
|
+
}
|
46
|
+
table_column {
|
47
|
+
text "Last Name"
|
48
|
+
width 80
|
49
|
+
}
|
50
|
+
table_column {
|
51
|
+
text "Email"
|
52
|
+
width 120
|
53
|
+
}
|
54
|
+
items bind(contact_manager_presenter, :results), column_properties(:first_name, :last_name, :email)
|
55
|
+
}
|
56
|
+
|
57
|
+
button {
|
58
|
+
text "&Find"
|
59
|
+
on_widget_selected {
|
60
|
+
contact_manager_presenter.find
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}.open
|
65
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright (C) 2007-2008 Annas Al Maleh
|
2
|
+
# Licensed under the LGPL. See /COPYING.LGPL for more details.
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + "/contact_repository"
|
5
|
+
|
6
|
+
class ContactManagerPresenter
|
7
|
+
attr_accessor :results
|
8
|
+
@@contact_attributes = [:first_name, :last_name, :email]
|
9
|
+
@@contact_attributes.each {|attribute_name| attr_accessor attribute_name}
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@contact_repository = ContactRepository.new
|
13
|
+
@results = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def find
|
17
|
+
filter_map = Hash.new
|
18
|
+
@@contact_attributes.each do |attribute_name|
|
19
|
+
filter_map[attribute_name] = self.send(attribute_name) if self.send(attribute_name)
|
20
|
+
end
|
21
|
+
self.results=@contact_repository.find(filter_map)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Copyright (C) 2007-2008 Annas Al Maleh
|
2
|
+
# Licensed under the LGPL. See /COPYING.LGPL for more details.
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + "/contact"
|
5
|
+
|
6
|
+
class ContactRepository
|
7
|
+
def initialize
|
8
|
+
@contacts = [
|
9
|
+
Contact.new(:first_name => "Anne", :last_name => "Sweeney", :email => "anne@sweeny.com"),
|
10
|
+
Contact.new(:first_name => "Beatrice", :last_name => "Jung", :email => "beatrice@jung.com"),
|
11
|
+
Contact.new(:first_name => "Frank", :last_name => "Deelio", :email => "frank@deelio.com"),
|
12
|
+
Contact.new(:first_name => "franky", :last_name => "miller", :email => "frank@miller.com"),
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
def find(attribute_filter_map)
|
17
|
+
@contacts.find_all do |contact|
|
18
|
+
match = true
|
19
|
+
attribute_filter_map.keys.each do |attribute_name|
|
20
|
+
contact_value = contact.send(attribute_name).downcase
|
21
|
+
filter_value = attribute_filter_map[attribute_name].downcase
|
22
|
+
match = false unless contact_value.match(filter_value)
|
23
|
+
end
|
24
|
+
match
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Copyright (C) 2007-2008 Annas Al Maleh
|
2
|
+
# Licensed under the LGPL. See /COPYING.LGPL for more details.
|
3
|
+
|
4
|
+
require "java"
|
5
|
+
require File.dirname(__FILE__) + "/../src/swt"
|
6
|
+
|
7
|
+
class HelloWorld
|
8
|
+
include_package 'org.eclipse.swt'
|
9
|
+
include_package 'org.eclipse.swt.layout'
|
10
|
+
|
11
|
+
include Glimmer
|
12
|
+
|
13
|
+
def launch
|
14
|
+
@shell = shell {
|
15
|
+
text "SWT"
|
16
|
+
composite {
|
17
|
+
label {
|
18
|
+
text "Hello World!"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
@shell.open
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
HelloWorld.new.launch
|
data/samples/login.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Copyright (C) 2007-2008 Annas Al Maleh
|
2
|
+
# Licensed under the LGPL. See /COPYING.LGPL for more details.
|
3
|
+
|
4
|
+
require "java"
|
5
|
+
require "observer"
|
6
|
+
require File.dirname(__FILE__) + "/../src/swt"
|
7
|
+
|
8
|
+
#Presents login screen data
|
9
|
+
class LoginPresenter
|
10
|
+
|
11
|
+
attr_accessor :user_name
|
12
|
+
attr_accessor :password
|
13
|
+
attr_accessor :status
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@user_name = ""
|
17
|
+
@password = ""
|
18
|
+
@status = "Logged Out"
|
19
|
+
end
|
20
|
+
|
21
|
+
def status=(status)
|
22
|
+
@status = status
|
23
|
+
|
24
|
+
#TODO add feature to bind dependent properties to master property
|
25
|
+
notify_observers("logged_in")
|
26
|
+
notify_observers("logged_out")
|
27
|
+
end
|
28
|
+
|
29
|
+
def logged_in
|
30
|
+
self.status == "Logged In"
|
31
|
+
end
|
32
|
+
|
33
|
+
def logged_out
|
34
|
+
!self.logged_in
|
35
|
+
end
|
36
|
+
|
37
|
+
def login
|
38
|
+
self.user_name = ""
|
39
|
+
self.password = ""
|
40
|
+
self.status = "Logged In"
|
41
|
+
end
|
42
|
+
|
43
|
+
def logout
|
44
|
+
self.user_name = ""
|
45
|
+
self.password = ""
|
46
|
+
self.status = "Logged Out"
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
#Login screen
|
52
|
+
class Login
|
53
|
+
include_package 'org.eclipse.swt'
|
54
|
+
include_package 'org.eclipse.swt.layout'
|
55
|
+
|
56
|
+
include Glimmer
|
57
|
+
|
58
|
+
def launch
|
59
|
+
presenter = LoginPresenter.new
|
60
|
+
@shell = shell {
|
61
|
+
text "Login"
|
62
|
+
composite {
|
63
|
+
layout GridLayout.new(2, false) #two columns with differing widths
|
64
|
+
|
65
|
+
label { text "Username:" } # goes in column 1
|
66
|
+
text { # goes in column 2
|
67
|
+
text bind(presenter, :user_name)
|
68
|
+
enabled bind(presenter, :logged_out)
|
69
|
+
}
|
70
|
+
|
71
|
+
label { text "Password:" }
|
72
|
+
text(SWT::PASSWORD | SWT::BORDER) {
|
73
|
+
text bind(presenter, :password)
|
74
|
+
enabled bind(presenter, :logged_out)
|
75
|
+
}
|
76
|
+
|
77
|
+
label { text "Status:" }
|
78
|
+
label { text bind(presenter, :status) }
|
79
|
+
|
80
|
+
button {
|
81
|
+
text "Login"
|
82
|
+
enabled bind(presenter, :logged_out)
|
83
|
+
on_widget_selected { presenter.login }
|
84
|
+
}
|
85
|
+
|
86
|
+
button {
|
87
|
+
text "Logout"
|
88
|
+
enabled bind(presenter, :logged_in)
|
89
|
+
on_widget_selected { presenter.logout }
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
@shell.open
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
Login.new.launch
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Copyright (C) 2007-2008 Nick Malnick and Annas Al Maleh
|
2
|
+
# Licensed under the LGPL. See /COPYING.LGPL for more details.
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + "/../../src/swt"
|
5
|
+
require File.dirname(__FILE__) + "/tic_tac_toe_board"
|
6
|
+
|
7
|
+
|
8
|
+
class TicTacToe
|
9
|
+
|
10
|
+
include_package 'org.eclipse.swt'
|
11
|
+
include_package 'org.eclipse.swt.widgets'
|
12
|
+
include_package 'org.eclipse.swt.layout'
|
13
|
+
|
14
|
+
include Glimmer
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@tic_tac_toe_board = TicTacToeBoard.new
|
18
|
+
@main =
|
19
|
+
@shell = shell {
|
20
|
+
text "Tic-Tac-Toe"
|
21
|
+
composite {
|
22
|
+
layout GridLayout.new(3,true)
|
23
|
+
(1..3).each { |row_number|
|
24
|
+
(1..3).each { |column_number|
|
25
|
+
button { |button_parent|
|
26
|
+
layout_data GridData.new(fill, fill, true, true)
|
27
|
+
text bind(@tic_tac_toe_board.box(row_number, column_number), :sign)
|
28
|
+
enabled bind(@tic_tac_toe_board.box(row_number, column_number), :empty)
|
29
|
+
on_widget_selected {
|
30
|
+
@tic_tac_toe_board.mark_box(row_number, column_number)
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
@tic_tac_toe_board.extend(ObservableModel) #make board an observable model
|
38
|
+
@tic_tac_toe_board.add_observer("game_status", self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def update(game_status)
|
42
|
+
display_win_message if game_status == TicTacToeBoard::WIN
|
43
|
+
display_draw_message if game_status == TicTacToeBoard::DRAW
|
44
|
+
end
|
45
|
+
|
46
|
+
def display_win_message()
|
47
|
+
display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
|
48
|
+
end
|
49
|
+
|
50
|
+
def display_draw_message()
|
51
|
+
display_game_over_message("Draw!")
|
52
|
+
end
|
53
|
+
|
54
|
+
def display_game_over_message(message)
|
55
|
+
message_box = MessageBox.new(@shell.widget)
|
56
|
+
message_box.setText("Game Over")
|
57
|
+
message_box.setMessage(message)
|
58
|
+
message_box.open
|
59
|
+
@tic_tac_toe_board.reset
|
60
|
+
end
|
61
|
+
|
62
|
+
def open
|
63
|
+
@main.open
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
TicTacToe.new.open
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# Copyright (C) 2007-2008 Nick Malnick and Annas Al Maleh
|
2
|
+
# Licensed under the LGPL. See /COPYING.LGPL for more details.
|
3
|
+
|
4
|
+
class TicTacToeBox
|
5
|
+
EMPTY = ""
|
6
|
+
attr_accessor :sign, :empty
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
reset
|
10
|
+
end
|
11
|
+
|
12
|
+
def mark_box(sign)
|
13
|
+
self.sign = sign
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
self.sign = EMPTY
|
18
|
+
end
|
19
|
+
|
20
|
+
def sign=(sign_symbol)
|
21
|
+
@sign = sign_symbol
|
22
|
+
self.empty = sign == EMPTY
|
23
|
+
end
|
24
|
+
|
25
|
+
def marked
|
26
|
+
! empty
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class TicTacToeBoard
|
31
|
+
DRAW = :draw
|
32
|
+
IN_PROGRESS = :in_progress
|
33
|
+
WIN = :win
|
34
|
+
attr :winning_sign
|
35
|
+
attr_accessor :game_status
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
|
39
|
+
build_grid
|
40
|
+
@winning_sign = TicTacToeBox::EMPTY
|
41
|
+
@game_status = IN_PROGRESS
|
42
|
+
end
|
43
|
+
|
44
|
+
#row and column numbers are 1-based
|
45
|
+
def mark_box(row_number, column_number)
|
46
|
+
box(row_number, column_number).mark_box(current_sign)
|
47
|
+
game_over? #updates winning sign
|
48
|
+
end
|
49
|
+
|
50
|
+
def current_sign
|
51
|
+
@current_sign = @sign_state_machine[@current_sign]
|
52
|
+
end
|
53
|
+
|
54
|
+
def box(row_number, column_number)
|
55
|
+
@grid[row_number-1][column_number-1]
|
56
|
+
end
|
57
|
+
|
58
|
+
def game_over?
|
59
|
+
win? or draw?
|
60
|
+
end
|
61
|
+
|
62
|
+
def win?
|
63
|
+
win = (row_win? or column_win? or diagonal_win?)
|
64
|
+
self.game_status=WIN if win
|
65
|
+
win
|
66
|
+
end
|
67
|
+
|
68
|
+
def reset
|
69
|
+
(1..3).each do |row_number|
|
70
|
+
(1..3).each do |column_number|
|
71
|
+
box(row_number, column_number).reset
|
72
|
+
end
|
73
|
+
end
|
74
|
+
@winning_sign = TicTacToeBox::EMPTY
|
75
|
+
@current_sign = nil
|
76
|
+
self.game_status=IN_PROGRESS
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def build_grid
|
82
|
+
@grid = []
|
83
|
+
3.times do |row_index| #0-based
|
84
|
+
@grid << []
|
85
|
+
3.times { @grid[row_index] << TicTacToeBox.new }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def row_win?
|
90
|
+
(1..3).each do |row_number|
|
91
|
+
if row_has_same_sign(row_number)
|
92
|
+
@winning_sign = box(row_number, 1).sign
|
93
|
+
return true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
false
|
97
|
+
end
|
98
|
+
|
99
|
+
def column_win?
|
100
|
+
(1..3).each do |column_number|
|
101
|
+
if column_has_same_sign(column_number)
|
102
|
+
@winning_sign = box(1, column_number).sign
|
103
|
+
return true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
false
|
107
|
+
end
|
108
|
+
|
109
|
+
#needs refactoring if we ever decide to make the board size dynamic
|
110
|
+
def diagonal_win?
|
111
|
+
if (box(1,1).sign == box(2,2).sign) and (box(2,2).sign == box(3,3).sign) and box(1,1).marked
|
112
|
+
@winning_sign = box(1,1).sign
|
113
|
+
return true
|
114
|
+
end
|
115
|
+
if (box(3,1).sign == box(2,2).sign) and (box(2,2).sign == box(1,3).sign) and box(3,1).marked
|
116
|
+
@winning_sign = box(3,1).sign
|
117
|
+
return true
|
118
|
+
end
|
119
|
+
false
|
120
|
+
end
|
121
|
+
|
122
|
+
def draw?
|
123
|
+
@board_full = true
|
124
|
+
3.times do |x|
|
125
|
+
3.times do |y|
|
126
|
+
@board_full = false if box(x, y).empty
|
127
|
+
end
|
128
|
+
end
|
129
|
+
self.game_status = DRAW if @board_full
|
130
|
+
@board_full
|
131
|
+
end
|
132
|
+
|
133
|
+
def row_has_same_sign(number)
|
134
|
+
row_sign = box(number, 1).sign
|
135
|
+
[2, 3].each do |column|
|
136
|
+
return false unless row_sign == (box(number, column).sign)
|
137
|
+
end
|
138
|
+
true if box(number, 1).marked
|
139
|
+
end
|
140
|
+
|
141
|
+
def column_has_same_sign(number)
|
142
|
+
column_sign = box(1, number).sign
|
143
|
+
[2, 3].each do |row|
|
144
|
+
return false unless column_sign == (box(row, number).sign)
|
145
|
+
end
|
146
|
+
true if box(1, number).marked
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|