smagacor 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +62 -0
- data/Rakefile +86 -71
- data/TODO +19 -2
- data/VERSION +1 -1
- data/data/smagacor/smagacor-logo.png +0 -0
- data/data/smagacor/sokoban/crate.png +0 -0
- data/data/smagacor/sokoban/floor.png +0 -0
- data/data/smagacor/sokoban/game.info +7 -0
- data/data/smagacor/sokoban/levels/loma.lvl +288 -0
- data/data/smagacor/sokoban/levels/mas_microban.lvl +1812 -0
- data/data/smagacor/sokoban/levels/mas_sasquatch.lvl +891 -0
- data/data/smagacor/sokoban/levels/microban.lvl +1834 -0
- data/data/smagacor/sokoban/levels/sasquatch.lvl +846 -0
- data/data/smagacor/sokoban/levels/sasquatch_III.lvl +903 -0
- data/data/smagacor/sokoban/levels/sasquatch_IV.lvl +812 -0
- data/data/smagacor/sokoban/levels/sasquatch_V.lvl +868 -0
- data/data/smagacor/sokoban/levels/sasquatch_VI.lvl +902 -0
- data/data/smagacor/sokoban/levels/sasquatch_VII.lvl +898 -0
- data/data/smagacor/sokoban/man.png +0 -0
- data/data/smagacor/sokoban/sokoban.png +0 -0
- data/data/smagacor/sokoban/sokobanui.rb +597 -0
- data/data/smagacor/sokoban/storage.png +0 -0
- data/data/smagacor/sokoban/wall.png +0 -0
- data/data/smagacor/tictactoe/game.info +1 -1
- data/data/smagacor/tictactoe/tictactoe.png +0 -0
- data/data/smagacor/tictactoe/tictactoe.rb +295 -206
- data/data/smagacor/tictactoe/x.png +0 -0
- data/lib/smagacor/listener.rb +50 -0
- data/lib/smagacor/smagacor-ui.rb +208 -127
- data/lib/smagacor/{controller.rb → util.rb} +106 -7
- metadata +68 -45
- data/install.rb +0 -21
Binary file
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Listener
|
2
|
+
|
3
|
+
# Adds a new message listener for the object. The message +msgName+
|
4
|
+
# will be dispatched to either the given +callableObject+ (has to respond
|
5
|
+
# to +call+) or the given block. If both are specified the +callableObject+
|
6
|
+
# is used.
|
7
|
+
def add_msg_listener( msgName, callableObject = nil, &block )
|
8
|
+
return unless defined?( @msgNames ) && @msgNames.has_key?( msgName )
|
9
|
+
|
10
|
+
if !callableObject.nil?
|
11
|
+
raise NoMethodError, "listener needs to respond to 'call'" unless callableObject.respond_to? :call
|
12
|
+
@msgNames[msgName].push callableObject
|
13
|
+
elsif !block.nil?
|
14
|
+
@msgNames[msgName].push block
|
15
|
+
else
|
16
|
+
raise "you have to provide a callback object or a block"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Removes the given object from the dispatcher queue of the message +msgName+.
|
21
|
+
def del_msg_listener( msgName, object )
|
22
|
+
@msgNames[msgName].delete object if defined? @msgNames
|
23
|
+
end
|
24
|
+
|
25
|
+
#######
|
26
|
+
private
|
27
|
+
#######
|
28
|
+
|
29
|
+
# Adds a new message target called +msgName+
|
30
|
+
def add_msg_name( msgName )
|
31
|
+
@msgNames = {} unless defined? @msgNames
|
32
|
+
@msgNames[msgName] = [] unless @msgNames.has_key? msgName
|
33
|
+
end
|
34
|
+
|
35
|
+
# Deletes the message target +msgName+.
|
36
|
+
def del_msg_name( msgName )
|
37
|
+
@msgNames.delete msgName if defined? @msgNames
|
38
|
+
end
|
39
|
+
|
40
|
+
# Dispatches the message +msgName+ to all listeners for this message,
|
41
|
+
# providing the given arguments
|
42
|
+
def dispatch_msg( msgName, *args )
|
43
|
+
if defined? @msgNames and @msgNames.has_key? msgName
|
44
|
+
@msgNames[msgName].each do |obj|
|
45
|
+
obj.call( *args )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/lib/smagacor/smagacor-ui.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
#--
|
3
3
|
#
|
4
|
-
# $Id: smagacor-ui.rb
|
4
|
+
# $Id: smagacor-ui.rb 362 2005-11-26 17:56:46Z thomas $
|
5
5
|
#
|
6
6
|
# smagacor - a collection of small games in ruby
|
7
7
|
# Copyright (C) 2004 Thomas Leitner
|
@@ -19,196 +19,276 @@
|
|
19
19
|
#
|
20
20
|
#++
|
21
21
|
#
|
22
|
+
|
23
|
+
require 'Qt'
|
22
24
|
require 'logger'
|
23
|
-
require '
|
24
|
-
require '
|
25
|
-
require 'smagacor/controller'
|
25
|
+
require 'ostruct'
|
26
|
+
require 'smagacor/util'
|
26
27
|
|
27
|
-
include Fox
|
28
28
|
|
29
29
|
module Smagacor
|
30
30
|
|
31
|
-
#
|
32
|
-
class
|
31
|
+
# Used to identify a game in the list view
|
32
|
+
class GameMenuItem < Qt::ListViewItem
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
attr_reader :game_info
|
35
|
+
|
36
|
+
def initialize( parent, gameinfo )
|
37
|
+
super( parent, gameinfo.name )
|
38
|
+
@game_info = gameinfo
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
def init_game_list( switcher, controller )
|
43
|
-
each_child do |child|
|
44
|
-
removeChild( child )
|
45
|
-
child.destroy
|
46
|
-
end
|
47
|
-
controller.load_games
|
48
|
-
controller.games.each do |game|
|
49
|
-
@categories[game.category] ||= CategoryShutterItem.new( self, game.category )
|
50
|
-
btn = GameShutterButton.new( @categories[game.category].content, game.name )
|
51
|
-
btn.tipText = game.description
|
52
|
-
btn.helpText = game.description
|
53
|
-
btn.icon = SmagacorWindow.load_image( getApp(), File.join( game.directory, game.icon ) )
|
54
|
-
btn.connect( SEL_COMMAND ) { switcher.select_game( game ) }
|
55
|
-
end
|
41
|
+
def rtti
|
42
|
+
1001
|
56
43
|
end
|
57
44
|
|
58
45
|
end
|
59
46
|
|
47
|
+
# Widget for listing all installed games.
|
48
|
+
class GameMenu < Qt::ListView
|
60
49
|
|
61
|
-
|
62
|
-
class CategoryShutterItem < FXShutterItem
|
50
|
+
slots 'toggleShown()'
|
63
51
|
|
64
|
-
#
|
65
|
-
def initialize( p
|
66
|
-
super( p
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
52
|
+
# Returns a default version of the class.
|
53
|
+
def initialize( p )
|
54
|
+
super( p )
|
55
|
+
@categories = {}
|
56
|
+
setRootIsDecorated( true )
|
57
|
+
addColumn( "Games" )
|
58
|
+
setSorting( 0 )
|
59
|
+
setColumnWidthMode( 0, Qt::ListView::Maximum )
|
60
|
+
setShowToolTips( true )
|
61
|
+
setResizeMode( Qt::ListView::LastColumn )
|
62
|
+
setFixedWidth( 250 )
|
63
|
+
init_game_list
|
71
64
|
end
|
72
65
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
66
|
+
def init_game_list
|
67
|
+
clear
|
68
|
+
Config.load_games
|
69
|
+
Config.games.each do |game|
|
70
|
+
@categories[game.category] ||= Qt::ListViewItem.new( self, game.category )
|
71
|
+
item = GameMenuItem.new( @categories[game.category], game )
|
72
|
+
item.setPixmap( 0, Qt::Pixmap.new( File.join( game.directory, game.icon ) ) )
|
73
|
+
end
|
74
|
+
end
|
78
75
|
|
79
|
-
|
80
|
-
|
81
|
-
super( p, name, nil, nil, 0, BUTTON_TOOLBAR|TEXT_BELOW_ICON|FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT )
|
82
|
-
self.backColor = p.backColor
|
83
|
-
self.textColor = FXRGB(255, 255, 255)
|
76
|
+
def toggleShown
|
77
|
+
if isShown then hide else show end
|
84
78
|
end
|
85
79
|
|
86
80
|
end
|
87
81
|
|
82
|
+
class GameView < Qt::WidgetStack
|
83
|
+
|
84
|
+
slots 'select_game(QListViewItem*)', 'about()'
|
85
|
+
|
86
|
+
attr_reader :cur_game_data
|
88
87
|
|
89
|
-
|
90
|
-
|
88
|
+
# Small description of Smagacor, for the about view.
|
89
|
+
DESCRIPTION = "<p><img src=\"smagacor\" /><br /><br /><b>Smagacor #{::Smagacor::VERSION.join('.')}</b><br />
|
90
|
+
<br />
|
91
|
+
Smagacor is a collection of some small games.<br />
|
92
|
+
It provides an easy interface for adding new games and has<br />
|
93
|
+
a pleasing :-) appearance.<br />
|
94
|
+
<br />
|
95
|
+
Select a game from the menu on the left side!<br />
|
96
|
+
And have fun with Smagacor!!!<br />
|
97
|
+
<br />
|
98
|
+
<a href=\"http://smagacor.rubyforge.org\">smagacor.rubyforge.org</a>"
|
91
99
|
|
92
|
-
|
93
|
-
|
94
|
-
|
100
|
+
def initialize( p )
|
101
|
+
super( p )
|
102
|
+
@loaded = {}
|
103
|
+
Qt::MimeSourceFactory.defaultFactory.setImage( 'smagacor', Qt::Image.new( Config.get_file( 'smagacor.png' ) ) )
|
104
|
+
aboutPage = Qt::Label.new( DESCRIPTION, self )
|
105
|
+
aboutPage.setAlignment( Qt::AlignVCenter | Qt::AlignCenter )
|
106
|
+
@aboutId = addWidget( aboutPage )
|
107
|
+
@cur_game_data = nil
|
95
108
|
end
|
96
109
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
110
|
+
def select_game( item )
|
111
|
+
return if item.nil? || item.rtti < 1000
|
112
|
+
gi = item.game_info
|
113
|
+
|
114
|
+
if @cur_game_data
|
115
|
+
save_game_state( @cur_game_data )
|
116
|
+
self.parent.parent.menuBar.removeItem( @cur_game_data.menu_id ) if @cur_game_data.menu_id
|
104
117
|
end
|
105
|
-
|
118
|
+
|
119
|
+
data = OpenStruct.new
|
120
|
+
unless @loaded.has_key?( gi )
|
106
121
|
begin
|
107
|
-
require File.join(
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
122
|
+
require File.join( gi.directory, gi.file )
|
123
|
+
data.game_info = gi
|
124
|
+
data.game_obj = gi.interface_class.new( self, gi )
|
125
|
+
data.undo_manager = UndoManager.new
|
126
|
+
data.game_obj.set_undo_manager( data.undo_manager )
|
127
|
+
data.menu = data.game_obj.menu
|
128
|
+
data.widget_id = addWidget( data.game_obj.game_widget )
|
129
|
+
@loaded[gi] = data
|
112
130
|
rescue StandardError => e
|
113
|
-
|
114
|
-
|
115
|
-
|
131
|
+
Qt::MessageBox.critical( self, "Error loading game",
|
132
|
+
"Could not load the game #{gi.name}\nError: #{e.message}\n#{e.backtrace.join("\n")}",
|
133
|
+
Qt::MessageBox::Ok | Qt::MessageBox::Default, Qt::MessageBox::NoButton )
|
134
|
+
data = nil
|
116
135
|
end
|
136
|
+
else
|
137
|
+
data = @loaded[gi]
|
138
|
+
end
|
139
|
+
|
140
|
+
unless data.nil?
|
141
|
+
load_game_state( data )
|
142
|
+
data.menu_id = self.parent.parent.menuBar.insertItem( data.game_info.name, data.menu ) if data.menu
|
143
|
+
self.parent.parent.undoManager = data.undo_manager
|
144
|
+
raiseWidget( @loaded[item.game_info].widget_id )
|
145
|
+
@cur_game_data = data
|
117
146
|
end
|
118
|
-
|
147
|
+
end
|
148
|
+
|
149
|
+
def about
|
150
|
+
raiseWidget( @aboutId )
|
151
|
+
end
|
152
|
+
|
153
|
+
#######
|
154
|
+
private
|
155
|
+
#######
|
156
|
+
|
157
|
+
def load_game_state( game_data )
|
158
|
+
end
|
159
|
+
|
160
|
+
def save_game_state( game_data )
|
161
|
+
|
119
162
|
end
|
120
163
|
|
121
164
|
end
|
122
165
|
|
123
166
|
|
124
167
|
# Log window for viewing the log statements (information, error descriptions, etc ).
|
125
|
-
class LogWindow <
|
168
|
+
class LogWindow < Qt::Dialog
|
169
|
+
|
170
|
+
attr_reader :logdev
|
171
|
+
|
172
|
+
class Logdev
|
173
|
+
|
174
|
+
def initialize( window )
|
175
|
+
@window = window
|
176
|
+
end
|
177
|
+
|
178
|
+
def write( message )
|
179
|
+
@window.write( message )
|
180
|
+
end
|
181
|
+
|
182
|
+
def close(); end
|
183
|
+
|
184
|
+
end
|
126
185
|
|
127
186
|
# Create a LogWindow
|
128
187
|
def initialize( p )
|
129
|
-
super( p
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
188
|
+
super( p )
|
189
|
+
setMinimumSize( 400, 400 )
|
190
|
+
setCaption( "Log Window" )
|
191
|
+
|
192
|
+
@log = Qt::TextEdit.new( self )
|
193
|
+
@log.setTextFormat( Qt::LogText )
|
194
|
+
button = Qt::PushButton.new( "Close", self )
|
195
|
+
connect( button, SIGNAL('clicked()'), self, SLOT('hide()') )
|
196
|
+
|
197
|
+
verticalLayout = Qt::VBoxLayout.new( self )
|
198
|
+
verticalLayout.addWidget( @log )
|
199
|
+
verticalLayout.addWidget( button )
|
200
|
+
@logdev = Logdev.new( self )
|
134
201
|
end
|
135
202
|
|
136
203
|
# Invoked by the logger library for writing log messages. The +message+ is appended to log.
|
137
204
|
def write( message )
|
138
|
-
@log.
|
139
|
-
@log.makePositionVisible( @log.text.length )
|
205
|
+
@log.append( message )
|
140
206
|
end
|
141
207
|
|
142
|
-
# Invoked by the logger library for closing the log device. Does nothing.
|
143
|
-
def close() end
|
144
|
-
|
145
208
|
end
|
146
209
|
|
147
210
|
|
148
211
|
# Main window for Smagacor.
|
149
|
-
class SmagacorWindow <
|
212
|
+
class SmagacorWindow < Qt::MainWindow
|
150
213
|
|
151
|
-
|
152
|
-
DESCRIPTION = "\n\nSmagacor #{::Smagacor::VERSION.join('.')}
|
214
|
+
slots 'undo()', 'redo()'
|
153
215
|
|
154
|
-
|
155
|
-
It provides an easy interface for adding new games and has
|
156
|
-
a pleasing :-) appearance.
|
216
|
+
attr_reader :undoManager
|
157
217
|
|
158
|
-
|
159
|
-
|
218
|
+
# Create the main window
|
219
|
+
def initialize( app )
|
220
|
+
super()
|
221
|
+
setCaption( 'Smagacor Game Collection' )
|
222
|
+
setIcon( Qt::Pixmap.new( Config.get_file( 'smagacor-logo.png' ) ) )
|
223
|
+
setIconText( 'Smagacor Game Collection' )
|
160
224
|
|
161
|
-
|
225
|
+
@logwindow = LogWindow.new( self )
|
226
|
+
logger.set_log_dev( @logwindow.logdev )
|
162
227
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
img.create
|
168
|
-
img
|
169
|
-
end
|
228
|
+
statusBar = Qt::StatusBar.new( self )
|
229
|
+
|
230
|
+
mainWidget = Qt::Widget.new( self )
|
231
|
+
setCentralWidget( mainWidget )
|
170
232
|
|
171
|
-
|
172
|
-
def initialize( app, controller )
|
173
|
-
super( app, "Smagacor Game Collection", nil, nil, DECOR_ALL, 100, 100, 800, 600 )
|
174
|
-
@controller = controller
|
233
|
+
mainLayout = Qt::HBoxLayout.new( mainWidget )
|
175
234
|
|
176
|
-
|
177
|
-
|
235
|
+
gamelist = GameMenu.new( mainWidget )
|
236
|
+
mainLayout.addWidget( gamelist )
|
178
237
|
|
179
|
-
|
238
|
+
gameview = GameView.new( mainWidget )
|
239
|
+
mainLayout.addWidget( gameview, 1 )
|
180
240
|
|
181
|
-
|
182
|
-
FXMenuCommand.new( filemenu, "Quit\tCtl-Q", nil, getApp(), FXApp::ID_QUIT )
|
183
|
-
FXMenuTitle.new( menubar, "&File", nil, filemenu )
|
241
|
+
connect( gamelist, SIGNAL('doubleClicked(QListViewItem*, const QPoint&, int)'), gameview, SLOT('select_game(QListViewItem*)') )
|
184
242
|
|
185
|
-
|
186
|
-
|
187
|
-
|
243
|
+
quitAction = Qt::Action.new( "&Quit", Qt::KeySequence.new( CTRL+Key_Q ), self )
|
244
|
+
connect( quitAction, SIGNAL('activated()'), app, SLOT("quit()") )
|
245
|
+
@undoAction = Qt::Action.new( "&Undo", Qt::KeySequence.new( CTRL+Key_Z ), self )
|
246
|
+
@undoAction.setEnabled( false )
|
247
|
+
connect( @undoAction, SIGNAL('activated()'), self, SLOT("undo()") )
|
248
|
+
@redoAction = Qt::Action.new( "&Redo", Qt::KeySequence.new( CTRL+Key_R ), self )
|
249
|
+
@redoAction.setEnabled( false )
|
250
|
+
connect( @redoAction, SIGNAL('activated()'), self, SLOT("redo()") )
|
251
|
+
showLogWindowAction = Qt::Action.new( "Log Window...", Qt::KeySequence.new( CTRL+Key_L ), self )
|
252
|
+
connect( showLogWindowAction, SIGNAL('activated()'), @logwindow, SLOT("show()") )
|
253
|
+
showGameListAction = Qt::Action.new( "Toogle game list", Qt::KeySequence.new( CTRL+Key_G ), self )
|
254
|
+
connect( showGameListAction, SIGNAL('activated()'), gamelist, SLOT("toggleShown()") )
|
255
|
+
aboutAction = Qt::Action.new( "About Smagacor", Qt::KeySequence.new( CTRL+Key_A ), self )
|
256
|
+
connect( aboutAction, SIGNAL('activated()'), gameview, SLOT("about()") )
|
188
257
|
|
189
|
-
|
190
|
-
|
191
|
-
FXMenuCommand.new( helpmenu, "About Smagacor\tCtl-A" ).connect( SEL_COMMAND ) { @switcher.current = 0 }
|
192
|
-
FXMenuTitle.new( menubar, "&Help", nil, helpmenu )
|
258
|
+
filemenu = Qt::PopupMenu.new( self )
|
259
|
+
quitAction.addTo( filemenu )
|
193
260
|
|
194
|
-
|
261
|
+
editmenu = Qt::PopupMenu.new( self )
|
262
|
+
@undoAction.addTo( editmenu )
|
263
|
+
@redoAction.addTo( editmenu )
|
195
264
|
|
196
|
-
|
265
|
+
helpmenu = Qt::PopupMenu.new( self )
|
266
|
+
showLogWindowAction.addTo( helpmenu )
|
267
|
+
showGameListAction.addTo( helpmenu )
|
268
|
+
aboutAction.addTo( helpmenu )
|
197
269
|
|
198
|
-
|
199
|
-
|
200
|
-
|
270
|
+
self.menuBar.insertItem( "&File", filemenu )
|
271
|
+
self.menuBar.insertItem( "&Edit", editmenu )
|
272
|
+
self.menuBar.insertItem( "&Help", helpmenu )
|
273
|
+
end
|
274
|
+
|
275
|
+
def undoManager=( manager )
|
276
|
+
@undoManager.del_msg_listener( :possible_actions, method(:activateUndoRedo) ) if @undoManager
|
277
|
+
@undoManager = manager
|
278
|
+
@undoManager.add_msg_listener( :possible_actions, method(:activateUndoRedo) ) if @undoManager
|
279
|
+
end
|
201
280
|
|
202
|
-
|
281
|
+
def activateUndoRedo( actions )
|
282
|
+
@undoAction.setEnabled( actions.include?( :undo ) )
|
283
|
+
@redoAction.setEnabled( actions.include?( :redo ) )
|
203
284
|
end
|
204
285
|
|
205
|
-
def
|
206
|
-
|
207
|
-
@shutter.width = 150
|
208
|
-
show
|
286
|
+
def undo
|
287
|
+
@undoManager.undo
|
209
288
|
end
|
210
289
|
|
211
|
-
def
|
290
|
+
def redo
|
291
|
+
@undoManager.redo
|
212
292
|
end
|
213
293
|
|
214
294
|
end
|
@@ -219,10 +299,11 @@ smagacor.rubyforge.org"
|
|
219
299
|
|
220
300
|
# Builds the application and runs it.
|
221
301
|
def start
|
222
|
-
app =
|
223
|
-
|
224
|
-
app.
|
225
|
-
|
302
|
+
app = Qt::Application.new( ARGV )
|
303
|
+
main = SmagacorWindow.new( app )
|
304
|
+
app.setMainWidget( main )
|
305
|
+
main.show
|
306
|
+
app.exec
|
226
307
|
end
|
227
308
|
|
228
309
|
end
|