# #-- # # $Id: smagacor-ui.rb 195 2005-02-09 13:16:44Z thomas $ # # smagacor - a collection of small games in ruby # Copyright (C) 2004 Thomas Leitner # # This program is free software; you can redistribute it and/or modify it under the terms of the GNU # General Public License as published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along with this program; if not, # write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #++ # require 'logger' require 'fox' require 'fox/colors' require 'smagacor/controller' include Fox module Smagacor # Widget for listing all installed games. class GameMenuShutter < FXShutter # Returns a default version of the class. def initialize( p ) super( p, nil, 0, FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y ) @categories = {} end # Initializes the list of games. The +switcher+ parameter has to be an object of class # GameSwitcher. The method uses the list of games supplied by the +controller+ object. def init_game_list( switcher, controller ) each_child do |child| removeChild( child ) child.destroy end controller.load_games controller.games.each do |game| @categories[game.category] ||= CategoryShutterItem.new( self, game.category ) btn = GameShutterButton.new( @categories[game.category].content, game.name ) btn.tipText = game.description btn.helpText = game.description btn.icon = SmagacorWindow.load_image( getApp(), File.join( game.directory, game.icon ) ) btn.connect( SEL_COMMAND ) { switcher.select_game( game ) } end end end # Widget for creating category shutter items easily. class CategoryShutterItem < FXShutterItem # Create a new category shutter item for category +text+ with +icon+. def initialize( p, text, icon=nil, opts=0 ) super( p, text, icon, opts|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10 ) button.padTop = 2 button.padBottom = 2 self.helpText = text self.tipText = text end end # Widget for creating buttons for games easily. class GameShutterButton < FXButton # Create a new game button for the game +name+. def initialize( p, name ) super( p, name, nil, nil, 0, BUTTON_TOOLBAR|TEXT_BELOW_ICON|FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT ) self.backColor = p.backColor self.textColor = FXRGB(255, 255, 255) end end # Game switcher widget. Used to display the different games in the space. class GameSwitcher < FXSwitcher # Create a new switcher. def initializer( p ) super( p, FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y ) end # Selects the specified +game+ [GameInfo] for playing. If the game has been selected earlier, # the widget only displays the game area. Otherwise the information in +game+ is used for # loading the necessary game files and for creating the game widget. def select_game( game ) game_index = 0 children.each_with_index do |child, index| game_index = index if child.userData == game end if game_index == 0 begin require File.join( game.directory, game.file ) content = game.get_class_object.new( self, game ) content.create content.userData = game game_index = children.length - 1 rescue StandardError => e FXMessageBox.new( self, "Error loading game", "Could not load the game #{game.name}\nError: #{e.message}\n#{e.backtrace.join("\n")}", nil, MBOX_OK ).execute end end self.current = game_index end end # Log window for viewing the log statements (information, error descriptions, etc ). class LogWindow < FXDialogBox # Create a LogWindow def initialize( p ) super( p, "Log Window", DECOR_ALL, 0, 0, 600, 400 ) vertical = FXVerticalFrame.new( self, LAYOUT_SIDE_TOP|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y ) @log = FXText.new( vertical, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y ) @log.editable = false FXButton.new( vertical, "Close", nil, self, ID_ACCEPT, FRAME_RAISED|LAYOUT_FILL_X ) end # Invoked by the logger library for writing log messages. The +message+ is appended to log. def write( message ) @log.appendText( message ) @log.makePositionVisible( @log.text.length ) end # Invoked by the logger library for closing the log device. Does nothing. def close() end end # Main window for Smagacor. class SmagacorWindow < FXMainWindow # Small description of Smagacor, for the about view. DESCRIPTION = "\n\nSmagacor #{::Smagacor::VERSION.join('.')} Smagacor is a collection of some small games. It provides an easy interface for adding new games and has a pleasing :-) appearance. Select a game from the menu on the left side! And have fun with Smagacor!!! smagacor.rubyforge.org" # Used to load *.png images into FXPNGIcon objects. def self.load_image( app, file ) img = FXPNGIcon.new( app, nil, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP ) FXFileStream.open( file, FXStreamLoad ) {|str| img.loadPixels(str) } img.create img end # Create the main window, using +app+ [FXApplication] and +controller+ [Controller]. def initialize( app, controller ) super( app, "Smagacor Game Collection", nil, nil, DECOR_ALL, 100, 100, 800, 600 ) @controller = controller @logwindow = LogWindow.new( app ) logger.set_log_dev( @logwindow ) menubar = FXMenubar.new( self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X ) filemenu = FXMenuPane.new( self ) FXMenuCommand.new( filemenu, "Quit\tCtl-Q", nil, getApp(), FXApp::ID_QUIT ) FXMenuTitle.new( menubar, "&File", nil, filemenu ) editmenu = FXMenuPane.new( self ) FXMenuCommand.new( editmenu, "Undo\tCtl-Z" ).connect( SEL_COMMAND, method( :onUndo ) ) FXMenuTitle.new( menubar, "&Edit", nil, editmenu ) helpmenu = FXMenuPane.new( self ) FXMenuCommand.new( helpmenu, "Log Window...\tCtl-L" ).connect( SEL_COMMAND ) { @logwindow.show } FXMenuCommand.new( helpmenu, "About Smagacor\tCtl-A" ).connect( SEL_COMMAND ) { @switcher.current = 0 } FXMenuTitle.new( menubar, "&Help", nil, helpmenu ) status = FXStatusbar.new( self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER ) splitter = FXSplitter.new( self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_TRACKING ) @shutter = GameMenuShutter.new( splitter ) @switcher = GameSwitcher.new( splitter ) @shutter.init_game_list( @switcher, controller ) FXLabel.new( @switcher, DESCRIPTION, SmagacorWindow.load_image( getApp(), controller.get_file( 'smagacor.png' ) ), ICON_ABOVE_TEXT ) end def create super @shutter.width = 150 show end def onUndo( sender, sel, event ) end end # Wraps the creation of the Smagacor Application. class SmagacorUI # Builds the application and runs it. def start app = FXApp.new( "Smagacor Game Collection", "Smagacor Game Collection" ) window = SmagacorWindow.new( app, Controller.new ) app.create app.run end end end