home *** CD-ROM | disk | FTP | other *** search
- # -*- coding: utf-8 -*-
- import sys
- from gettext import gettext as _
- import traceback
- import gobject
- import gtk
-
- import gtkui
- import glchess.ui
- import glchess.chess
- import glchess.game
-
- # Optionally use OpenGL support
- openGLErrors = []
- haveGLDepthSupport = True
- haveGLAccumSupport = True
- try:
- import OpenGL.GL
- except:
- # Translators: Error message displayed when 3D mode is not available due to no Python OpenGL libraries
- openGLErrors.append(_('No Python OpenGL support'))
- try:
- import gtk.gtkgl
- import gtk.gdkgl
- except:
- # Translators: Error message displayed when 3D mode is not available due to no Python GTKGLExt libraries
- openGLErrors.append(_('No Python GTKGLExt support'))
- else:
- display_mode = (gtk.gdkgl.MODE_RGB | gtk.gdkgl.MODE_DEPTH | gtk.gdkgl.MODE_DOUBLE | gtk.gdkgl.MODE_ACCUM)
- try:
- glConfig = gtk.gdkgl.Config(mode = display_mode)
- except gtk.gdkgl.NoMatches:
- display_mode &= ~gtk.gdkgl.MODE_DOUBLE
- display_mode &= ~gtk.gdkgl.MODE_ACCUM
- haveGLAccumSupport = False
- haveGLDepthSupport = False
- try:
- glConfig = gtk.gdkgl.Config(mode = display_mode)
- except gtk.gdkgl.NoMatches:
- # Translators: Error message displayed when 3D mode is not available due to their 3D drivers not being able to provide a suitable display mode
- openGLErrors.append(_('OpenGL libraries do not support required display mode'))
- haveGLSupport = len(openGLErrors) == 0
-
- __all__ = ['GtkView']
-
- class GtkViewArea(gtk.DrawingArea):
- """Custom widget to render an OpenGL scene"""
- # The view this widget is rendering
- view = None
-
- # Pixmaps to use for double buffering
- pixmap = None
- dynamicPixmap = None
-
- # Flag to show if this scene is to be rendered using OpenGL
- renderGL = False
-
- # TODO...
- __glDrawable = None
-
- def __init__(self, view):
- """
- """
- gtk.DrawingArea.__init__(self)
-
- self.view = view
-
- # Allow notification of button presses
- self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.BUTTON_MOTION_MASK)
-
- # Make openGL drawable
- if haveGLSupport:
- gtk.gtkgl.widget_set_gl_capability(self, glConfig)# FIXME:, share_list=glContext)
-
- # Connect signals
- self.connect('realize', self.__init)
- self.connect('configure_event', self.__configure)
- self.connect('expose_event', self.__expose)
- self.connect('button_press_event', self.__button_press)
- self.connect('button_release_event', self.__button_release)
-
- # Public methods
-
- def redraw(self):
- """Request this widget is redrawn"""
- # If the window is visible prepare it for redrawing
- area = gtk.gdk.Rectangle(0, 0, self.allocation.width, self.allocation.height)
- if self.window is not None:
- self.window.invalidate_rect(area, False)
-
- def setRenderGL(self, renderGL):
- """Enable OpenGL rendering"""
- if not haveGLSupport:
- renderGL = False
-
- if self.renderGL == renderGL:
- return
- self.renderGL = renderGL
- self.redraw()
-
- # Private methods
-
- def __startGL(self):
- """Get the OpenGL context"""
- if not self.renderGL:
- return
-
- assert(self.__glDrawable is None)
-
- # Obtain a reference to the OpenGL drawable
- # and rendering context.
- glDrawable = gtk.gtkgl.widget_get_gl_drawable(self)
- glContext = gtk.gtkgl.widget_get_gl_context(self)
-
- # Check were able to get context
- if glDrawable is None or glContext is None:
- return
-
- # OpenGL begin (can fail)
- if not glDrawable.gl_begin(glContext):
- return
-
- self.__glDrawable = glDrawable
-
- if not self.view.ui.openGLInfoPrinted:
- vendor = OpenGL.GL.glGetString(OpenGL.GL.GL_VENDOR)
- renderer = OpenGL.GL.glGetString(OpenGL.GL.GL_RENDERER)
- version = OpenGL.GL.glGetString(OpenGL.GL.GL_VERSION)
- extensions = OpenGL.GL.glGetString(OpenGL.GL.GL_EXTENSIONS)
- print 'Using OpenGL:'
- print 'VENDOR=%s' % vendor
- print 'RENDERER=%s' % renderer
- print 'VERSION=%s' % version
- print 'EXTENSIONS=%s' % extensions
- self.view.ui.openGLInfoPrinted = True
-
- def __endGL(self):
- """Free the OpenGL context"""
- if self.__glDrawable is None or not self.renderGL:
- return
- self.__glDrawable.gl_end()
- self.__glDrawable = None
-
- def __init(self, widget):
- """Gtk+ signal"""
- if self.view.feedback is not None:
- self.view.feedback.reshape(widget.allocation.width, widget.allocation.height)
-
- def __configure(self, widget, event):
- """Gtk+ signal"""
- self.pixmap = gtk.gdk.Pixmap(widget.window, event.width, event.height)
- self.dynamicPixmap = gtk.gdk.Pixmap(widget.window, event.width, event.height)
- self.__startGL()
- if self.view.feedback is not None:
- self.view.feedback.reshape(event.width, event.height)
- self.__endGL()
-
- def __expose(self, widget, event):
- """Gtk+ signal"""
- if self.renderGL:
- self.__startGL()
- if self.__glDrawable is None:
- return
-
- # Get the scene rendered
- try:
- if self.view.feedback is not None:
- self.view.feedback.renderGL()
- except OpenGL.GL.GLerror, e:
- print 'Rendering Error: ' + str(e)
- traceback.print_exc(file = sys.stdout)
-
- # Paint this
- if self.__glDrawable.is_double_buffered():
- self.__glDrawable.swap_buffers()
- else:
- OpenGL.GL.glFlush()
-
- self.__endGL()
-
- else:
- context = self.pixmap.cairo_create()
- if self.view.feedback is not None:
- self.view.feedback.renderCairoStatic(context)
-
- # Copy the background to render the dynamic elements on top
- self.dynamicPixmap.draw_drawable(widget.get_style().white_gc, self.pixmap, 0, 0, 0, 0, -1, -1)
- context = self.dynamicPixmap.cairo_create()
-
- # Set a clip region for the expose event
- context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
- context.clip()
-
- # Render the dynamic elements
- if self.view.feedback is not None:
- self.view.feedback.renderCairoDynamic(context)
-
- # Draw the window
- widget.window.draw_drawable(widget.get_style().white_gc, self.dynamicPixmap,
- event.area.x, event.area.y,
- event.area.x, event.area.y, event.area.width, event.area.height)
-
- def __button_press(self, widget, event):
- """Gtk+ signal"""
- self.__startGL()
- if self.view.feedback is not None:
- self.view.feedback.select(event.x, event.y)
- self.__endGL()
-
- def __button_release(self, widget, event):
- """Gtk+ signal"""
- self.__startGL()
- if self.view.feedback is not None:
- self.view.feedback.deselect(event.x, event.y)
- self.__endGL()
-
- class GtkView(glchess.ui.ViewController):
- """
- """
- def __init__(self, ui, feedback, moveFormat = 'human', showComments = False):
- """Constructor for a view.
-
- 'feedback' is the feedback object for this view (extends ui.ViewFeedback).
- 'moveFormat' is the format name to display moves in (string).
- """
- self.ui = ui
- self.feedback = feedback
- self.moveFormat = moveFormat
- self.showComments = showComments
- self.editingComment = False
- self.hasFile = False
- self.selectedMove = -1
- self.requireAttention = False
- self.gameResult = None
- self.whiteTime = None
- self.blackTime = None
- self.title = ''
- self.needsSaving = False
-
- # The GTK+ elements
- self.gui = gtkui.loadGladeFile('chess_view.glade', 'chess_view')
- self.gui.signal_autoconnect(self)
- self.widget = self.gui.get_widget('chess_view')
-
- self.viewWidget = GtkViewArea(self)
- self.gui.get_widget('view_container').add(self.viewWidget)
-
- self.ui.setTooltipStyle(self.gui.get_widget('info_panel'))
-
- # Make a model for navigation (move object, number, description)
- model = gtk.ListStore(gobject.TYPE_PYOBJECT, int, str)
- iter = model.append()
- # Translators: Move History Combo: Go to the start of the game
- model.set(iter, 0, None, 1, 0, 2, _('Game Start'))
- self.moveModel = model
-
- # Tabs are enabled to make editing the UI easier
- self.gui.get_widget('comment_notebook').set_show_tabs(False)
-
- self.updateInfoPanel()
-
- self.widget.show()
- self.viewWidget.show_all()
-
- self.ui.updateTitle()
-
- def updateInfoPanel(self):
- """
- """
- showPanel = False
-
- panel = self.gui.get_widget('info_panel')
- titleLabel = self.gui.get_widget('panel_title_label')
- descriptionLabel = self.gui.get_widget('panel_description_label')
-
- move = self._getCurrentMove()
- if self.gameResult is not None:
- (title, description) = self.gameResult
- titleLabel.set_markup('<big><b>%s</b></big>' % title)
- descriptionLabel.set_markup('<i>%s</i>' % description)
- showPanel = True
-
- editToggle = self.gui.get_widget('comment_edit_toggle')
- if self.showComments:
- # Show the comments
- if move is None:
- titleLabel.set_markup('<big><b>%s</b></big>' % _('Game Start'))
- else:
- titleLabel.set_markup('<big><b>%s</b></big>' % self.generateMoveString(move))
-
- # Translators: Comment text when move has no comment
- comment = _('No comment')
- if move is not None and len(move.comment) > 0:
- comment = move.comment
-
- descriptionLabel.set_markup('<i>%s</i>' % comment)
- editToggle.show()
- showPanel = True
- else:
- editToggle.hide()
-
- if showPanel:
- panel.show()
- else:
- panel.hide()
-
- def setShowComments(self, showComments):
- """Enable comments on this view.
-
- 'showComments' is true when move comments are visible.
- """
- self.showComments = showComments
- self.updateInfoPanel()
-
- def setMoveFormat(self, format):
- """Set the format to display the moves in.
-
- 'format' is the format name to use (e.g. 'human', 'san'. Defaults to 'human')
- """
- self.moveFormat = format
-
- # Update the move list
- iter = self.moveModel.get_iter_first()
- while iter is not None:
- move = self.moveModel.get_value(iter, 0)
- if move is not None:
- string = self.generateMoveString(move)
- self.moveModel.set(iter, 2, string)
- iter = self.moveModel.iter_next(iter)
-
- # Extended methods
-
- def setTitle(self, title):
- """Extends glchess.ui.ViewController"""
- self.title = title
- if self.ui.view is self:
- self.ui.updateTitle()
-
- def setNeedsSaving(self, needsSaving):
- """Extends glchess.ui.ViewController"""
- if self.needsSaving == needsSaving:
- return
- self.needsSaving = needsSaving
- if self.ui.view is self:
- self.ui.updateTitle()
-
- def render(self):
- """Extends glchess.ui.ViewController"""
- self.viewWidget.redraw()
-
- def setWhiteTime(self, total, current):
- """Extends glchess.ui.ViewController"""
- self.whiteTime = (total, current)
- if self.ui.view is self:
- self.ui.setTimers(self.whiteTime, self.blackTime)
-
- def setBlackTime(self, total, current):
- """Extends glchess.ui.ViewController"""
- self.blackTime = (total, current)
- if self.ui.view is self:
- self.ui.setTimers(self.whiteTime, self.blackTime)
-
- def setHasFile(self, hasFile):
- """Extends glchess.ui.ViewController"""
- self.hasFile = hasFile
- self.ui._updateViewButtons()
-
- def setAttention(self, requiresAttention):
- """Extends glchess.ui.ViewController"""
- if self.requireAttention == requiresAttention:
- return
- self.requireAttention = requiresAttention
- if requiresAttention:
- self.ui._incAttentionCounter(1)
- else:
- self.ui._incAttentionCounter(-1)
-
- def generateMoveString(self, move):
- """
- """
- moveNumber = (move.number - 1) / 2 + 1
- WHITE = glchess.chess.board.WHITE
- BLACK = glchess.chess.board.BLACK
- colour = {0: BLACK, 1: WHITE}[move.number % 2]
-
- # Note SAN format is intentionally not translated
- if self.moveFormat == 'san':
- if move.number % 2 == 0:
- format = '%(movenum)2i. ... %(move_san)s'
- else:
- format = '%(movenum)2i. %(move_san)s'
- return format % {'movenum': moveNumber, 'move_san': glchess.chess.translate_notation(move.sanMove)}
-
- # Note FAN format is intentionally not translated
- if self.moveFormat == 'fan':
- if move.number % 2 == 0:
- format = '%(movenum)2i. ... %(move_san)s'
- else:
- format = '%(movenum)2i. %(move_san)s'
- return format % {'movenum': moveNumber, 'move_san': glchess.chess.translate_figurine_notation(colour, move.sanMove)}
-
- # Note LAN format is intentionally not translated
- if self.moveFormat == 'lan':
- if move.number % 2 == 0:
- format = '%(movenum)2i. ... %(move_can)s'
- else:
- format = '%(movenum)2i. %(move_can)s'
- return format % {'movenum': moveNumber, 'move_can': glchess.chess.translate_notation(move.canMove)}
-
- PAWN = glchess.chess.board.PAWN
- ROOK = glchess.chess.board.ROOK
- KNIGHT = glchess.chess.board.KNIGHT
- BISHOP = glchess.chess.board.BISHOP
- QUEEN = glchess.chess.board.QUEEN
- KING = glchess.chess.board.KING
-
- if move.sanMove.startswith('O-O-O'):
- # Translators: Human Move String: Description of the white player making a long castle
- description = {WHITE: _('White castles long'),
- # Translators: Human Move String: Description of the black player making a long castle
- BLACK: _('Black castles long')}[colour]
- elif move.sanMove.startswith('O-O'):
- # Translators: Human Move String: Description of the white player making a short castle
- description = {WHITE: _('White castles short'),
- # Translators: Human Move String: Description of the black player making a short castle
- BLACK: _('Black castles short')}[colour]
- else:
- # Note there are no move formats for pieces taking kings and this is not allowed in Chess rules
- # Translators: Human Move String: Description of a white pawn moving from %(start)s to %(end)s, e.g. 'c2 to c4'
- descriptions = {(WHITE, PAWN, None): _('White pawn moves from %(start)s to %(end)s'),
- (WHITE, PAWN, PAWN): _('White pawn at %(start)s takes the black pawn at %(end)s'),
- (WHITE, PAWN, ROOK): _('White pawn at %(start)s takes the black rook at %(end)s'),
- (WHITE, PAWN, KNIGHT): _('White pawn at %(start)s takes the black knight at %(end)s'),
- (WHITE, PAWN, BISHOP): _('White pawn at %(start)s takes the black bishop at %(end)s'),
- (WHITE, PAWN, QUEEN): _('White pawn at %(start)s takes the black queen at %(end)s'),
- # Translators: Human Move String: Description of a white rook moving from %(start)s to %(end)s, e.g. 'a1 to a5'
- (WHITE, ROOK, None): _('White rook moves from %(start)s to %(end)s'),
- (WHITE, ROOK, PAWN): _('White rook at %(start)s takes the black pawn at %(end)s'),
- (WHITE, ROOK, ROOK): _('White rook at %(start)s takes the black rook at %(end)s'),
- (WHITE, ROOK, KNIGHT): _('White rook at %(start)s takes the black knight at %(end)s'),
- (WHITE, ROOK, BISHOP): _('White rook at %(start)s takes the black bishop at %(end)s'),
- (WHITE, ROOK, QUEEN): _('White rook at %(start)s takes the black queen at %(end)s'),
- # Translators: Human Move String: Description of a white knight moving from %(start)s to %(end)s, e.g. 'b1 to c3'
- (WHITE, KNIGHT, None): _('White knight moves from %(start)s to %(end)s'),
- (WHITE, KNIGHT, PAWN): _('White knight at %(start)s takes the black pawn at %(end)s'),
- (WHITE, KNIGHT, ROOK): _('White knight at %(start)s takes the black rook at %(end)s'),
- (WHITE, KNIGHT, KNIGHT): _('White knight at %(start)s takes the black knight at %(end)s'),
- (WHITE, KNIGHT, BISHOP): _('White knight at %(start)s takes the black bishop at %(end)s'),
- (WHITE, KNIGHT, QUEEN): _('White knight at %(start)s takes the black queen at %(end)s'),
- # Translators: Human Move String: Description of a white bishop moving from %(start)s to %(end)s, e.g. 'f1 to b5'
- (WHITE, BISHOP, None): _('White bishop moves from %(start)s to %(end)s'),
- (WHITE, BISHOP, PAWN): _('White bishop at %(start)s takes the black pawn at %(end)s'),
- (WHITE, BISHOP, ROOK): _('White bishop at %(start)s takes the black rook at %(end)s'),
- (WHITE, BISHOP, KNIGHT): _('White bishop at %(start)s takes the black knight at %(end)s'),
- (WHITE, BISHOP, BISHOP): _('White bishop at %(start)s takes the black bishop at %(end)s'),
- (WHITE, BISHOP, QUEEN): _('White bishop at %(start)s takes the black queen at %(end)s'),
- # Translators: Human Move String: Description of a white queen moving from %(start)s to %(end)s, e.g. 'd1 to d4'
- (WHITE, QUEEN, None): _('White queen moves from %(start)s to %(end)s'),
- (WHITE, QUEEN, PAWN): _('White queen at %(start)s takes the black pawn at %(end)s'),
- (WHITE, QUEEN, ROOK): _('White queen at %(start)s takes the black rook at %(end)s'),
- (WHITE, QUEEN, KNIGHT): _('White queen at %(start)s takes the black knight at %(end)s'),
- (WHITE, QUEEN, BISHOP): _('White queen at %(start)s takes the black bishop at %(end)s'),
- (WHITE, QUEEN, QUEEN): _('White queen at %(start)s takes the black queen at %(end)s'),
- # Translators: Human Move String: Description of a white king moving from %(start)s to %(end)s, e.g. 'e1 to f1'
- (WHITE, KING, None): _('White king moves from %(start)s to %(end)s'),
- (WHITE, KING, PAWN): _('White king at %(start)s takes the black pawn at %(end)s'),
- (WHITE, KING, ROOK): _('White king at %(start)s takes the black rook at %(end)s'),
- (WHITE, KING, KNIGHT): _('White king at %(start)s takes the black knight at %(end)s'),
- (WHITE, KING, BISHOP): _('White king at %(start)s takes the black bishop at %(end)s'),
- (WHITE, KING, QUEEN): _('White king at %(start)s takes the black queen at %(end)s'),
- # Translators: Human Move String: Description of a black pawn moving from %(start)s to %(end)s, e.g. 'c8 to c6'
- (BLACK, PAWN, None): _('Black pawn moves from %(start)s to %(end)s'),
- (BLACK, PAWN, PAWN): _('Black pawn at %(start)s takes the white pawn at %(end)s'),
- (BLACK, PAWN, ROOK): _('Black pawn at %(start)s takes the white rook at %(end)s'),
- (BLACK, PAWN, KNIGHT): _('Black pawn at %(start)s takes the white knight at %(end)s'),
- (BLACK, PAWN, BISHOP): _('Black pawn at %(start)s takes the white bishop at %(end)s'),
- (BLACK, PAWN, QUEEN): _('Black pawn at %(start)s takes the white queen at %(end)s'),
- # Translators: Human Move String: Description of a black rook moving from %(start)s to %(end)s, e.g. 'a8 to a4'
- (BLACK, ROOK, None): _('Black rook moves from %(start)s to %(end)s'),
- (BLACK, ROOK, PAWN): _('Black rook at %(start)s takes the white pawn at %(end)s'),
- (BLACK, ROOK, ROOK): _('Black rook at %(start)s takes the white rook at %(end)s'),
- (BLACK, ROOK, KNIGHT): _('Black rook at %(start)s takes the white knight at %(end)s'),
- (BLACK, ROOK, BISHOP): _('Black rook at %(start)s takes the white bishop at %(end)s'),
- (BLACK, ROOK, QUEEN): _('Black rook at %(start)s takes the white queen at %(end)s'),
- # Translators: Human Move String: Description of a black knight moving from %(start)s to %(end)s, e.g. 'b8 to c6'
- (BLACK, KNIGHT, None): _('Black knight moves from %(start)s to %(end)s'),
- (BLACK, KNIGHT, PAWN): _('Black knight at %(start)s takes the white pawn at %(end)s'),
- (BLACK, KNIGHT, ROOK): _('Black knight at %(start)s takes the white rook at %(end)s'),
- (BLACK, KNIGHT, KNIGHT): _('Black knight at %(start)s takes the white knight at %(end)s'),
- (BLACK, KNIGHT, BISHOP): _('Black knight at %(start)s takes the white bishop at %(end)s'),
- (BLACK, KNIGHT, QUEEN): _('Black knight at %(start)s takes the white queen at %(end)s'),
- # Translators: Human Move String: Description of a black bishop moving from %(start)s to %(end)s, e.g. 'f8 to b3'
- (BLACK, BISHOP, None): _('Black bishop moves from %(start)s to %(end)s'),
- (BLACK, BISHOP, PAWN): _('Black bishop at %(start)s takes the white pawn at %(end)s'),
- (BLACK, BISHOP, ROOK): _('Black bishop at %(start)s takes the white rook at %(end)s'),
- (BLACK, BISHOP, KNIGHT): _('Black bishop at %(start)s takes the white knight at %(end)s'),
- (BLACK, BISHOP, BISHOP): _('Black bishop at %(start)s takes the white bishop at %(end)s'),
- (BLACK, BISHOP, QUEEN): _('Black bishop at %(start)s takes the white queen at %(end)s'),
- # Translators: Human Move String: Description of a black queen moving from %(start)s to %(end)s, e.g. 'd8 to d5'
- (BLACK, QUEEN, None): _('Black queen moves from %(start)s to %(end)s'),
- (BLACK, QUEEN, PAWN): _('Black queen at %(start)s takes the white pawn at %(end)s'),
- (BLACK, QUEEN, ROOK): _('Black queen at %(start)s takes the white rook at %(end)s'),
- (BLACK, QUEEN, KNIGHT): _('Black queen at %(start)s takes the white knight at %(end)s'),
- (BLACK, QUEEN, BISHOP): _('Black queen at %(start)s takes the white bishop at %(end)s'),
- (BLACK, QUEEN, QUEEN): _('Black queen at %(start)s takes the white queen at %(end)s'),
- # Translators: Human Move String: Description of a black king moving from %(start)s to %(end)s, e.g. 'e8 to f8'
- (BLACK, KING, None): _('Black king moves from %(start)s to %(end)s'),
- (BLACK, KING, PAWN): _('Black king at %(start)s takes the white pawn at %(end)s'),
- (BLACK, KING, ROOK): _('Black king at %(start)s takes the white rook at %(end)s'),
- (BLACK, KING, KNIGHT): _('Black king at %(start)s takes the white knight at %(end)s'),
- (BLACK, KING, BISHOP): _('Black king at %(start)s takes the white bishop at %(end)s'),
- (BLACK, KING, QUEEN): _('Black king at %(start)s takes the white queen at %(end)s')}
-
- pieceType = move.piece.getType()
- if move.victim is not None:
- victimType = move.victim.getType()
- else:
- victimType = None
- start = glchess.chess.translate_coordinate(move.start)
- end = glchess.chess.translate_coordinate(move.end)
-
- description = descriptions[colour, pieceType, victimType] % {'start': start, 'end': end}
-
- CHECK = 'CHECK'
- CHECKMATE = 'CHECKMATE'
- STALEMATE = 'STALEMATE'
- status = None
- if move.opponentInCheck:
- if move.opponentCanMove:
- status = CHECK
- else:
- status = CHECKMATE
- elif not move.opponentCanMove:
- status = STALEMATE
-
- # Translators: Human Move String: White player has made move %(description) and the opponent is in check
- formatString = {(WHITE, CHECK): _('%(movenum)2iw. %(description)s (Check)'),
- # Translators: Human Move String: White player has made move %(description) and the opponent is in checkmate
- (WHITE, CHECKMATE): _('%(movenum)2iw. %(description)s (Checkmate)'),
- # Translators: Human Move String: White player has made move %(description) and the opponent is in stalemate
- (WHITE, STALEMATE): _('%(movenum)2iw. %(description)s (Stalemate)'),
- # Translators: Human Move String: White player has made move %(description) and the opponent is not in check or mate
- (WHITE, None): _('%(movenum)2iw. %(description)s'),
- # Translators: Human Move String: Black player has made move %(description) and the opponent is in check
- (BLACK, CHECK): _('%(movenum)2ib. %(description)s (Check)'),
- # Translators: Human Move String: Black player has made move %(description) and the opponent is in checkmate
- (BLACK, CHECKMATE): _('%(movenum)2ib. %(description)s (Checkmate)'),
- # Translators: Human Move String: Black player has made move %(description) and the opponent is in stalemate
- (BLACK, STALEMATE): _('%(movenum)2ib. %(description)s (Stalemate)'),
- # Translators: Human Move String: Black player has made move %(description) and the opponent is not in check or mate
- (BLACK, None): _('%(movenum)2ib. %(description)s')}[colour, status]
-
- # FIXME: Promotion
-
- return formatString % {'movenum': moveNumber, 'description': description}
-
- def addMove(self, move):
- """Extends glchess.ui.ViewController"""
- # FIXME: Make a '@ui' player who watches for these itself?
- iter = self.moveModel.append()
- string = self.generateMoveString(move)
- self.moveModel.set(iter, 0, move, 1, move.number, 2, string)
-
- # If is the current view and tracking the game select this
- if self.selectedMove == -1:
- # If editing comments don't stay on current move
- if self.editingComment:
- self._setMoveNumber(move.number - 1)
- return
-
- self.ui._updateViewButtons()
-
- def undoMove(self):
- """Extends glchess.ui.ViewController"""
- iter = self.moveModel.iter_nth_child(None, len(self.moveModel) - 1)
- self.moveModel.remove(iter)
- self.selectedMove = -1
- self.ui._updateViewButtons()
-
- def endGame(self, game):
- # Translators: Message displayed when a player wins. The %s is substituted with the winning player's name
- format = _('%s wins')
-
- # If game completed show this in the GUI
- if game.result is glchess.game.RESULT_WHITE_WINS:
- title = format % game.getWhite().getName()
- elif game.result is glchess.game.RESULT_BLACK_WINS:
- title = format % game.getBlack().getName()
- else:
- # Translators: Message displayed when a game is drawn
- title = _('Game is drawn')
-
- description = ''
- if game.rule is glchess.game.RULE_CHECKMATE:
- # Translators: Message displayed when the game ends due to a player being checkmated
- description = _('Opponent is in check and cannot move (checkmate)')
- elif game.rule is glchess.game.RULE_STALEMATE:
- # Translators: Message displayed when the game terminates due to a stalemate
- description = _('Opponent cannot move (stalemate)')
- elif game.rule is glchess.game.RULE_FIFTY_MOVES:
- # Translators: Message displayed when the game is drawn due to the fifty move rule
- description = _('No piece has been taken or pawn moved in the last fifty moves')
- elif game.rule is glchess.game.RULE_TIMEOUT:
- # Translators: Message displayed when the game ends due to one player's clock stopping
- description = _('Opponent has run out of time')
- elif game.rule is glchess.game.RULE_THREE_FOLD_REPETITION:
- # Translators: Message displayed when the game is drawn due to the three-fold-repitition rule
- description = _('The same board state has occured three times (three fold repetition)')
- elif game.rule is glchess.game.RULE_INSUFFICIENT_MATERIAL:
- # Translators: Message displayed when the game is drawn due to the insufficient material rule
- description = _('Neither player can cause checkmate (insufficient material)')
- elif game.rule is glchess.game.RULE_RESIGN:
- if game.result is glchess.game.RESULT_WHITE_WINS:
- # Translators: Message displayed when the game ends due to the black player resigning
- description = _('The black player has resigned')
- elif game.result is glchess.game.RESULT_BLACK_WINS:
- # Translators: Message displayed when the game ends due to the white player resigning
- description = _('The white player has resigned')
- else:
- assert(False)
- elif game.rule is glchess.game.RULE_ABANDONMENT:
- # Translators: Message displayed when a game is abandoned
- description = _('The game has been abandoned')
- elif game.rule is glchess.game.RULE_DEATH:
- # Translators: Message displayed when the game ends due to a player dying
- description = _('One of the players has died')
-
- self.gameResult = (title, description)
- self.updateInfoPanel()
- self.ui._updateViewButtons()
-
- def close(self):
- """Extends glchess.ui.ViewController"""
- if self.requireAttention:
- self.ui._incAttentionCounter(-1)
- self.ui._removeView(self)
-
- # Public methods
-
- def _getCurrentMove(self):
- if self.selectedMove == -1:
- iter = self.moveModel.get_iter_from_string(str(len(self.moveModel) - 1))
- else:
- iter = self.moveModel.get_iter_from_string(str(self.selectedMove))
- return self.moveModel.get_value(iter, 0)
-
- def _getModel(self):
- """
- """
- return (self.moveModel, self.selectedMove)
-
- def _setMoveNumber(self, moveNumber):
- """Set the move number this view requests.
-
- 'moveNumber' is the move number to use (integer).
- """
- self.selectedMove = moveNumber
- if self.feedback is not None:
- self.feedback.setMoveNumber(moveNumber)
- self.updateInfoPanel()
-
- # Callbacks
-
- def _on_comment_edit_button_toggled(self, widget):
- """Gtk+ callback"""
- label = self.gui.get_widget('panel_description_label')
- entry = self.gui.get_widget('comment_text')
- buffer = entry.get_buffer()
-
- move = self._getCurrentMove()
-
- # FIXME
- if move is None:
- return
-
- self.editingComment = widget.get_active()
- if self.editingComment:
- buffer.set_text(move.comment)
- entry.grab_focus()
- page = 1
- else:
- comment = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())
-
- # FIXME: This should be notified so the game is considered modified for saving purposes
- # self.feedback.setComment(move, comment)
-
- move.comment = comment
- label.set_text(comment)
- buffer.set_text('')
- page = 0
- self.gui.get_widget('comment_notebook').set_current_page(page)
-