world_display.py :  » IDE » RUR » rurple1.0rc3 » rur_py » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » IDE » RUR 
RUR » rurple1.0rc3 » rur_py » world_display.py
""" RUR-PLE: Roberge's Used Robot - a Python Learning Environment
    world_display.py - Displays "world" with "robot" and allow
                      keyboard-based interactions
    Version 0.8.7
    Author: Andre Roberge    Copyright  2005
    andre.roberge@gmail.com
"""
# 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 Library 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.

import wx
from world_creation import Visible_world
from robot_factory import Used_robot,New_improved_robot
import dialogs

class WorldGUI(wx.ScrolledWindow):
    def __init__(self, parent, id = -1, size = wx.DefaultSize):
        wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size,
                                  style=wx.SUNKEN_BORDER)
        self.SetBackgroundColour("WHITE")
        self.world = Visible_world()
        self.editor = False  #
        self.InitialiseVariables()
        self.MakePopupMenu()
        self.bindEvents()
        self.SetFocus()

    def InitialiseVariables(self):
        # Create the world image
        self.world.updateImage = False
        self.world.DoDrawing()
        # Initialize the buffer bitmap.  No real DC is needed at this point.
        self.buffer = wx.EmptyBitmap(self.world.maxWidth, self.world.maxHeight)
        self.drawImage()

        # Set the size of the total window, of which only a small part
        # will be displayed; apparently SetVirtualSize needs
        # a single (tuple) argument, which explains the double (( )).
        self.SetVirtualSize((self.world.maxWidth, self.world.maxHeight))

        # Set the scrolling rate; use same value in both horizontal and
        # vertical directions.
        scrollRate = self.world.tile_narrow + self.world.tile_wide
        self.SetScrollRate(scrollRate, scrollRate)
        # yPos below set so that we are at the bottom of the scrolledWindow
        self.SetScrollbars(1, 1, self.world.maxWidth,
                           self.world.maxHeight, yPos=self.world.maxHeight)
        # allow for testing "new and improved" robot
        self.newRobot = False

    def bindEvents(self):
        wx.EVT_PAINT(self, self.OnPaint)
        wx.EVT_LEFT_DOWN(self, self.OnLeftDown) # for "drawing"
        wx.EVT_CHAR(self, self.MyKeys) # to test Robot actions
        wx.EVT_IDLE(self, self.OnIdle)
        wx.EVT_RIGHT_UP(self, self.OnRightUp)

    def OnIdle(self, event=None):
        """
        Do any needed updating on Idle time ...
        """
        if self.world.updateImage:
            self.drawImage()
        self.world.updateImage = False

    def OnPaint(self, event=None):
        try:
            dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)
        except:
            dc = wx.BufferedPaintDC(self, self.buffer) # before wxPython 2.5.4.1

    def isActive(self, event):
        xView, yView = self.GetViewStart()
        xDelta, yDelta = self.GetScrollPixelsPerUnit()
        self.x, self.y = event.GetPositionTuple()
        self.x += xView*xDelta
        self.y += yView*yDelta
        # Test to see if in "active" zone i.e. inside world borders
        if (self.x > self.world.xOffset and
           self.y > self.world.yTopOffset and
           self.y < self.world.maxHeight - self.world.yOffset and
           self.x < self.world.maxWidth - self.world.right_scroller_space):
            return True
        else:
            return False

    def OnLeftDown(self, event):
        """Called when the left mouse button is pressed and build
           or remove walls."""
        self.SetFocus()
        if self.isActive(event):
            col, row = self.world.CalculatePosition(self.x, self.y)
            self.world.ChangeWall(col, row)
            if self.world.updateImage:
                self.drawImage()
                self.Refresh()
        else:
            pass   # added for clarity; we are on the outside

    def MakePopupMenu(self):
        """Make a menu for beepers that can be popped up later;
        this menu will offer the possibility of
        putting a given number of beepers
        at the current location (street/avenue intersection)."""
        menu = wx.Menu()
        self._beeperChoice = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, \
                          11, 12, 13, 14, 15, 20, 40, 60, 80, 99]
        maxNumberOfBeepers = len(self._beeperChoice)
        # This version is revised from 0.9.1 to avoid "hard-wired"
        # IDs in appending the menu and let wxPython decide on suitable
        # values.  The previous version caused problems on MacOS.
        # Note that OnMenuSetBeepers() had to be modified as well.
        self.popID = []
        for index, beepers in enumerate(self._beeperChoice):
            self.popID.append(wx.NewId())
            menu.Append(self.popID[index], str(beepers))
            self.Bind(wx.EVT_MENU, self.OnMenuSetBeepers,
                      id=self.popID[index])
        self.menu = menu

    def OnMenuSetBeepers(self, event):
        self._num = self._beeperChoice[self.popID.index(event.GetId())]

    def OnRightUp(self, event):
        """called when the right mouse button is released,
        will call the popup menu, offering the possibility of
        putting a given number of beepers
        at the current location (street/avenue intersection)."""
        if self.isActive(event):
            col, row = self.world.CalculatePosition(self.x, self.y)
            if row%2:
                if col%2:
                    pt = event.GetPosition()
                    self.PopupMenu(self.menu, pt)
                    av = (col+1)/2
                    st = (row+1)/2
                    self.world.setBeepers((av, st), self._num)
                    if self.world.updateImage:
                        self.drawImage()
                        self.Refresh()
        else:
            pass   # added for clarity; we are on the outside

    def MyKeys(self, event):
        message = """
            F5: Help (i.e. this message)

Editing world:
            lower case e: toggle in/out of edit walls mode
            Left mouse button: add or remove walls (if in edit walls mode)
            Right mouse button: put beepers at intersection

Robot actions:
            Up arrow:     move robot forward
            Left arrow:   turn robot left
            lower case p: pick_beeper
            upper case P: put_beeper

            Errors will occur if you attempt to move through a wall,
            put a beeper when you carry none,
            or try to pick up a beeper where there is none.

For testing only (future features):
            F7: creates New_improved_robot
            Right arrow:   turn robot right (only New_improved_robot)
            F8: creates Used_robot (default)"""
        code = event.GetKeyCode()
        if code == wx.WXK_UP:           # up arrow
            if 'robot' in self.world.robot_dict:
                try:
                    self.world.MoveRobot('robot') # may raise an exception
                    self.scrollWorld('robot')
                except dialogs.HitWallException, mesg:
                    dialogs.DialogHitWallError(mesg)
        elif code == wx.WXK_LEFT:       # left arrow
            self.world.TurnRobotLeft('robot')
        elif code == 112:            # p - lower case
            if 'robot' in self.world.robot_dict:
                try:
                    self.world.robot_dict['robot'].pick_beeper()
                    if self.editor:
                        self.editor.DestroyChildren()
                        wx.StaticText(self.editor, -1, self.UpdateEditor(), (10, 10))
                except dialogs.PickBeeperException, mesg:
                    dialogs.DialogPickBeeperError(mesg)
        elif code == 80:             # P - upper case
            if 'robot' in self.world.robot_dict:
                try:
                    self.world.robot_dict['robot'].put_beeper()
                    if self.editor:
                        self.editor.DestroyChildren()
                        wx.StaticText(self.editor, -1, self.UpdateEditor(), (10, 10))
                except dialogs.PutBeeperException, mesg:
                    dialogs.DialogPutBeeperError(mesg)
        elif code == 101:            # e - lower case
            if self.world.editWalls:
                self.world.editWalls = False
                self.world.DoDrawing()
            else:
                self.world.editWalls = True
                self.world.DoDrawing()
        elif code == wx.WXK_F5:
            dialogs.rurMessageDialog(message, "Help :-)")
        elif code == wx.WXK_F7:
            self.world.robot_dict['robot'] = New_improved_robot(parent = self.world)
            self.world.DoDrawing()
            self.newRobot = True
        elif code == wx.WXK_F8:
            self.world.robot_dict['robot'] = Used_robot(parent = self.world)
            self.world.DoDrawing()
            self.newRobot = False
        elif code == wx.WXK_RIGHT:       # right arrow
            if self.newRobot:         # only New_improved_robot can turn right.
                self.world.TurnRobotRight('robot')
            else:
                pass
        else:
            pass
        if self.world.updateImage:
            self.drawImage()
            self.Refresh()
    #- end of MyKeys()-----------------------------------------

    def scrollWorld(self, name):
        '''Determines if window needs scrolling and does necessary.'''
        # determine robot image bounding box
        x0, y0 = self.world.robot_image_origin
        x1, y1 = self.world.robot_dict[name]._image_size
        x1 += x0
        y1 += y0

        # marginal space around robot
        margin = self.world.tile_narrow + self.world.tile_wide
        margin *= 2

        # position of top left visible window in "scrollrate" units
        xView, yView = self.GetViewStart()
        xViewOld, yViewOld = xView, yView

        # corresponding amount of pixel per "scroll"
        xDelta, yDelta = self.GetScrollPixelsPerUnit()

        # size of wisible window
        width, height = self.GetSizeTuple()

        #-- Determine if window needs to be scrolled so that object
        # remains visible.  Assume that the object fits entirely
        # in the visible view.
        if x0 - margin < xView*xDelta:
            xView = max(0, -1 + (x0-margin)/xDelta)
        elif x1 + margin > xView*xDelta + width:
            xView = (x1 + margin - width)/xDelta
        if y0 - margin < yView*yDelta:
            yView = max(0, -1 + (y0-margin)/yDelta)
        elif y1 + margin > yView*yDelta + height:
            yView = (y1 + margin - height)/yDelta
        # if needed, scroll window by required amount to keep image in view
        if xView != xViewOld or yView != yViewOld:
            self.Scroll(xView, yView)

    def drawImage(self):
        dc = wx.BufferedDC(None, self.buffer)
        dc.BeginDrawing()
        # Simply copy the world image onto the buffer
        dc.DrawBitmap(self.world.world_image, 0, 0, True)
        # update the editor
        if self.editor:
            self.editor.DestroyChildren() # removes the old wx.StaticText
            wx.StaticText(self.editor, -1, self.UpdateEditor(), (10, 10))
        dc.EndDrawing()


    def UpdateEditor(self):
        av_string = "avenues = " + str(self.world.num_cols//2)
        st_string = "streets = " + str(self.world.num_rows//2)
        robot_string = ''
        for name in self.world.robot_dict:
            x, y = self.world.robot_dict[name].getPos()
            beepers = self.world.robot_dict[name]._beeper_bag
            orientation = self.world.robot_dict[name]._getOrientationKey()
            robot_string += name + " = " + \
                  self.world.robot_dict[name]._getInfoString() + "\n"
        if len(self.world.walls_list) > 0:
            wall_string = "walls = [\n"
            for item in self.world.walls_list:
                wall_string = wall_string + ("    " + str(item)
                                         + ', \n')
            wall_string = wall_string[0:-3]+'\n]'
        else:
            wall_string = "walls = []"
        if len(self.world.beepers_dict) > 0:
            beeper_list = "beepers = {\n"
            for key in self.world.beepers_dict:
                beeper_list = beeper_list + ("    " + str(key) + ': '
                       + str(self.world.beepers_dict[key])+ ', \n')
            beeper_list = beeper_list[0:-3]+'\n}'
        else:
            beeper_list = "beepers = {}"

        worldmap = av_string + '\n' + st_string + '\n' + robot_string \
                  + wall_string + '\n' +  beeper_list
        return worldmap
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.