rur_start.py :  » IDE » RUR » rurple1.0rc3 » 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_start.py
#!/usr/bin/env python
# -*- coding: latin-1 -*-
""" RUR-PLE: Roberge's Used Robot - a Python Learning Environment
    rur_start.py - "Main" file for RUR-PLE.
    Version 1.0
    Author: Andr Roberge    Copyright  2006
    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.

# todo: consider adding support for translation of commands e.g.
# todo: ...  francais()  initialises commands equivalent like avance(), etc.
# todo: create easy install for windows (exe file)
# todo: create easy install for linux  (setup.py...)
# todo: consider adding new page in notebook for turtle graphics.

import os
import sys
import wx
import wx.lib.buttons
import rur_py.misc as misc  # a few global variables

if __name__ == "__main__": # ensures that all wxPython stuff is loaded properly
    App = wx.PySimpleApp(0) # (1) redirects print output to window; 
                            # (0) to terminal
    cur_path = os.path.dirname(sys.argv[0])
    if cur_path != '':
        os.chdir(cur_path)
    misc.HOME = os.getcwd() # sets up path for later use
    #
    os.chdir("rur_images")
    misc.IMAGE_DIR = os.getcwd()
    os.chdir(misc.HOME)
    #
    os.chdir("lessons")
    from rur_py.translation import language_code
    os.chdir(language_code)
    misc.HTML_DIR = os.getcwd()
    os.chdir(misc.HOME)
    #
    os.chdir("rur_programs")
    misc.PRGM_DIR = os.getcwd()
    os.chdir(misc.HOME)
    #
    os.chdir("world_files")
    misc.WORLD_DIR = os.getcwd()
    os.chdir(misc.HOME)
    #
    os.chdir("python_files")
    misc.PYTHON_DIR  = os.getcwd()
    os.chdir(misc.HOME)

#--- see end of file for completion of the start of the application

import wx.py as py           # For the interpreter
import rur_py.images as images # load all images
import rur_py.dialogs as rD    # contains various dialogs and exception classes
from rur_py.translation import _

from rur_py.sash import MySashWindow
from rur_py.lightning import EditorSashWindow
import rur_py.parser as parser
from rur_py.bouton import pythonChoiceWindow
code = ""    # global variable defined for convenience; contains user program

from rur_py.cpu import rur_program
import rur_py.browser as browser
import rur_py.event_manager as event_manager
from rur_py.status_bar import rurStatusBar

class RURnotebook(wx.Notebook):
    def __init__(self, parent):
        wx.Notebook.__init__(self, parent, -1)
        self.parent = parent
        wx.EVT_NOTEBOOK_PAGE_CHANGED(self, -1, self.OnPageChanged)

    def OnPageChanged(self, event):
        arg = self.parent.status_bar.notebook_new_page, event.GetSelection()
        event_manager.SendCustomEvent(self.parent, arg)
        event.Skip()

class RURApp(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, 
                          _("RUR: a Python Learning Environment"),
                          size = (800, 660),
                          style=wx.DEFAULT_FRAME_STYLE)
        self.raw_code = ""
        self.filename = ""
        self.world_filename = ""
        self.isPaused = False
        self.isRunning = False
        self.isStepped = False
        self.status_bar = rurStatusBar(self)
        self.SetStatusBar(self.status_bar)

        # icon on top left of window
        icon = wx.EmptyIcon()
        icon.CopyFromBitmap(images.ICON)
        self.SetIcon(icon)
        #
        self.Show(True)
        self.window = RURnotebook(self)
        #
        win = browser.TestHtmlPanel(self.window, self)
        self.window.AddPage(win, _("  RUR: Read and Learn  "))
        #
        self.sash = MySashWindow(self.window, self)
        
        self.outputWindow = self.sash.output_window
        
        self.window.AddPage(self.sash, _("Robot: Code and Learn"))
        # See MySashWindow for the following 'shortcut' notation
        self.world = self.WorldDisplay.world
        # create a backup copy that will be used to "reset" the world
        self.backup_dict = {}
        self.backup_dict['avenues'] = self.world.av
        self.backup_dict['streets'] = self.world.st
        self.backup_dict['beepers'] = {}
        self.backup_dict['walls'] = []
        # add a robot to start
        self.world.addOneRobot(name='robot')
        self.backup_dict['robot'] = self.world.robot_dict[
                                                    'robot']._getInfoTuple()
        # create user_program object as a two-step process: create Singleton
        self.user_program = rur_program()
        # binds attributes explicitly
        self.user_program.myInit(self, self.world, self.WorldDisplay,
                               self.ProgramEditor, self.world.robot_dict)
        # We will then be able to "link" to the one rur_program() without
        # having to worry about changing attributes
        # recreate the image so that the robot shows up.
        self.world.DoDrawing()
        self.WorldDisplay.drawImage()
        self.WorldDisplay.Refresh()
        #
        win = py.shell.Shell(self.window, -1,
                            introText = "")
        self.window.AddPage(win, _("Python: Code and Learn"))

        self.sash2 = EditorSashWindow(self.window, grand_parent=self,
                                      controller=pythonChoiceWindow,
                 top_control=True, top_control_height=40)    
                # 40 = bouton "." btn_size[1] + 8
        self.window.AddPage(self.sash2, _("Python: simple editor"))

        self.SetSize((900, 660))
        self.window.SetFocus()
        self.SendSizeEvent()  # added to attempt to solve problem on MacOS
        wx.EVT_CLOSE(self, self.OnClose)

    def OnClose(self, event):
        if self.ProgramEditor.GetModify():
            rD.rurMessageDialog(
             _("Robot program has changed.\nYou may save it before quitting."), 
             _("Program has been changed"))
            self.SaveProgramFile(event)
            # in case the user does not save the program, make it appear
            # as though it has been saved so that the next attempt to 
            # quit will work.
            self.ProgramEditor.SetSavePoint() 
        else:
            self.Destroy()

#---- World file methods
    def OpenWorldFile(self, dummy):
        if self.isRunning:
            return
        wildcard = _("World files (*.wld)|*.wld| All files (*.*)|*.*") 
        dlg = wx.FileDialog(self, _("Choose a file"), misc.WORLD_DIR, "",
                           wildcard, wx.OPEN | wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
            self.world_filename = dlg.GetPath()
            self.ReadWorldFile()
            self.UpdateWorld()
            self.user_program.clear_trace()
            misc.WORLD_DIR = os.path.dirname(self.world_filename)
            arg = self.status_bar.world_field, \
                  os.path.basename(self.world_filename)
            event_manager.SendCustomEvent(self, arg)
        dlg.Destroy()

    def ReadWorldFile(self):
        if self.isRunning:
            return
        txt = open(self.world_filename, 'r').read()
        txt = parser.FixLineEnding(txt)
        flag = parser.ParseWorld(txt)
        if flag:
            self.backup_dict = {} # used to 'reset' the world
            exec txt in self.backup_dict # extracts avenues, streets, robot,
                                     # walls and beepers

    def ResetWorld(self, dummy):
        if self.isRunning:
            return
        self.UpdateWorld()

    def UpdateWorld(self):
        try:
            av = self.backup_dict['avenues']
        except:
            rD.rurMessageDialog(
                   _("Problem with %s\nPlease recreate world file.")%
                   _("avenues"), 
                   _("Invalid world file format"))
            return
        try:
            st = self.backup_dict['streets']
        except:
            rD.rurMessageDialog(
                   _("Problem with %s\nPlease recreate world file.")%
                   _("streets"), 
                   _("Invalid world file format"))
            return
        self.world.resetDimensions(av, st)
        try:
            if 'robot' in self.backup_dict:
                x, y, key, beep = self.backup_dict['robot']
                arg = self.status_bar.beeper_field, beep
                event_manager.SendCustomEvent(self, arg)
        except:
            rD.rurMessageDialog(
                   _("Problem with %s\nPlease recreate world file.")%
                   _("robot"), 
                   _("Invalid world file format"))
            return
        # We might be reloading the world, to which robots may have been added
        # Remove all robots that have been added, if any; 
        # recall that "named" robots are added through a user-defined program, 
        # not in a world file.
        self.world.robot_dict = {}
        # Recreate the robot that was in the original file
        if 'robot' in self.backup_dict:
            self.world.addOneRobot(x, y, key, beep, name='robot')

        # world characteristics
        # note: we make shallow copies of rurApp.backup_dict as we 
        # may need it if we call ResetWorld().
        try:
            for corner in self.world.beepers_dict:
                del self.world.beepers_dict[corner] # empty, but keep reference
            for corner in self.backup_dict['beepers']:
                self.world.beepers_dict[corner] = self.backup_dict[
                                                            'beepers'][corner]
        except:
            rD.rurMessageDialog(
                   _("Problem with %s\nPlease recreate world file.")%
                   _("beepers"), 
                   _("Invalid world file format"))
            return
        # We need to keep one reference only to walls_list
        try:
            for col, row in self.world.walls_list:
                self.world.walls_list.remove((col, row)) # empty, but keep ref.
            for col, row in self.backup_dict['walls']:
                self.world.walls_list.append((col, row))
        except:
            rD.rurMessageDialog(
                   _("Problem with %s\nPlease recreate world file.")%
                   _("walls"), 
                   _("Invalid world file format"))
            return

        # prepare to recreate the background images
        self.world.background_images_created = False
        self.world.AdjustWorldSize()
        self.world.InitTileSizes()
        self.WorldDisplay.InitialiseVariables()
        self.world.DoDrawing()
        # create a new bitmap image
        self.WorldDisplay.buffer = wx.EmptyBitmap(self.world.maxWidth,
                                               self.world.maxHeight)
        self.WorldDisplay.drawImage()

    def SaveWorldFile(self, dummy):
        if self.isRunning:
            return
        wildcard = _("World files (*.wld)|*.wld| All files (*.*)|*.*")
        fname = os.path.basename(self.filename)
        dlg = wx.FileDialog(self, _("Save new world as"), misc.WORLD_DIR,
                               fname, wildcard, wx.SAVE| wx.CHANGE_DIR )
        if dlg.ShowModal() == wx.ID_OK:
            self.world_filename = dlg.GetPath()
            f = open(self.world_filename, 'w')
            txt = self.WorldDisplay.UpdateEditor()
            f.write(txt)
            f.close()
            arg = self.status_bar.world_field, \
                  os.path.basename(self.world_filename)
            event_manager.SendCustomEvent(self, arg)
            misc.WORLD_DIR = os.path.dirname(self.world_filename)
            # save a backup copy to 'reset world'
            self.backup_dict = {} 
            exec txt in self.backup_dict
        dlg.Destroy()

#----- Program files methods

    def OpenProgramFile(self, dummy):
        if self.isRunning:
            return
        wildcard = _("Program files (*.rur)|*.rur| All files (*.*)|*.*")
        dlg = wx.FileDialog(self, _("Choose a file"), misc.PRGM_DIR, "",
                           wildcard, wx.OPEN | wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
            global code
            self.filename = dlg.GetPath()
            arg = self.status_bar.program_field, \
                  os.path.basename(self.filename)
            event_manager.SendCustomEvent(self, arg)
            code = open(self.filename, 'r').read()
            code = parser.FixLineEnding(code)
            self.ProgramEditor.SetText(code)
            no_error, mesg = parser.ParseProgram(code)
            misc.PRGM_DIR = os.path.dirname(self.filename)
            if no_error:
                self.raw_code = code
                self.ProgramEditor.SetSavePoint()
            else:
                code = ""
                rD.rurMessageDialog(mesg, ("Program will not be used."))
        dlg.Destroy()
    
    def SaveProgramFile(self, dummy):
        if self.isRunning:
            return
        global code
        code = self.ProgramEditor.GetText()
        no_error, mesg = parser.ParseProgram(code)
        if no_error:
            wildcard = _("Program files (*.rur)|*.rur| All files (*.*)|*.*")
            fname = os.path.basename(self.filename)
            dlg = wx.FileDialog(self, _("Save new program as"), misc.PRGM_DIR,
                               fname, wildcard, wx.SAVE| wx.CHANGE_DIR )
            if dlg.ShowModal() == wx.ID_OK:
                self.filename = dlg.GetPath()
                f = open(self.filename, 'w')
                f.write(code)
                f.close()
                arg = self.status_bar.program_field, \
                      os.path.basename(self.filename)
                event_manager.SendCustomEvent(self, arg)
                code = parser.FixLineEnding(code)
                misc.PRGM_DIR = os.path.dirname(self.filename)
            dlg.Destroy()
            self.ProgramEditor.SetSavePoint()
        else:
            code = ""
            rD.rurMessageDialog(mesg, _("Program will not be saved."))

#--- Program controls

    def RunProgram(self, dummy):
        if self.user_program.isRunning:
            if self.user_program.isPaused or self.user_program.isStepped:
                self.user_program.isStepped = False
                self.Pause(None)
            return
        self.user_program.isRunning = True
        self.user_program.restart(self.world.robot_dict)

    def Pause(self, dummy):
        if not (self.user_program.isRunning or self.user_program.isStepped):
            return
        if self.user_program.isPaused:
            self.user_program.isPaused = False
            arg = self.status_bar.running_field, _("Program is running")
            event_manager.SendCustomEvent(self, arg)
        else:
            self.user_program.isPaused = True
            arg = self.status_bar.running_field, _("Program paused")
            event_manager.SendCustomEvent(self, arg)

    def Step(self, dummy):
        self.user_program.isStepped = True
        if not self.user_program.isRunning:
            self.RunProgram(None)
        else:
            self.Pause(None)

    def StopProgram(self, dummy):
        self.user_program.StopProgram()
        arg = self.status_bar.running_field, _("Program not running")
        event_manager.SendCustomEvent(self, arg)
        self.user_program.stopped_by_user = True

#--- World controls

    def EditWalls(self, event):
        if self.user_program.isRunning:
            return
        self.user_program.clear_trace()
        if self.world.editWalls:
            self.world.editWalls = False
            self.world.DoDrawing()
        else:
            self.world.editWalls = True
            self.world.DoDrawing()
        self.WorldDisplay.drawImage()
        self.WorldDisplay.Refresh()

    def BeepersToRobot(self, dummy):
        if self.user_program.isRunning:
            return
        self.user_program.clear_trace()
        try:
            dummy = self.backup_dict['robot']
        except KeyError:
            msg = _("No robot in world to give beepers to.")
            rD.rurMessageDialog(msg, 'error')
            return
        rD.RobotBeeperDialog(self, -1, _("Beepers!"))

    def BeepersUpdateStatusBar(self):
        arg = self.status_bar.beeper_field, \
              self.world.robot_dict['robot']._beeper_bag
        event_manager.SendCustomEvent(self, arg)
        # update the world window text at the same time
        self.rightWindow.DestroyChildren() # removes the old wx.StaticText
        wx.StaticText(self.rightWindow, -1,
                        self.WorldDisplay.UpdateEditor(), (10, 10))
                        
    def ResizeWorld(self, dummy):
        if self.user_program.isRunning:
            return
        self.user_program.clear_trace()
        rD.ResizeWorldDialog(self, -1, _("World size!"))

    def ToggleHighlight(self, dummy):
        if self.user_program.isRunning:
            return
        global code
        if misc.line_number_flag:
            misc.line_number_flag = False
            code = self.raw_code
        else:
            misc.line_number_flag = True
            code = parser.add_line_number_info(code)

    def ToggleWorldWindow(self, dummy):
        if self.user_program.isRunning:
            return
        if self.rightWindow.isVisible:
            self.rightWindow.SetDefaultSize(wx.Size(0, 600))
            self.rightWindow.isVisible = False
        else:
            self.rightWindow.SetDefaultSize(wx.Size(200, 600))
            self.rightWindow.isVisible = True

        wx.LayoutAlgorithm().LayoutWindow(self.sash, self.WorldDisplay)
        self.rightWindow.DestroyChildren() # removes the old wx.StaticText
        wx.StaticText(self.rightWindow, -1,
                        self.WorldDisplay.UpdateEditor(), (10, 10))

    def AddRemoveRobot(self, dummy):
        if self.user_program.isRunning:
            return
        if self.world.robot_dict:
            # remove all robots from non-empty dict
            self.world.robot_dict = {}
            arg = self.status_bar.beeper_field, self.status_bar.no_robot
        else:
            self.world.robot_dict = {}
            self.world.addOneRobot(name='robot')
            self.backup_dict['robot'] = self.world.robot_dict[
                                                       'robot']._getInfoTuple()
            arg = self.status_bar.beeper_field, \
                  self.world.robot_dict['robot']._beeper_bag
        event_manager.SendCustomEvent(self, arg)
        self.world.DoDrawing()
        self.WorldDisplay.drawImage()
        self.WorldDisplay.Refresh()
        
    def load_images(self, event):
        wildcard = "All files (*.*)|*.*"
        dlg = wx.FileDialog(self, "Choose an image: robot facing South", 
                           os.getcwd(), "", wildcard, wx.OPEN | wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
            self.fileSouth = dlg.GetPath()
        dlg.Destroy()        
        dlg = wx.FileDialog(self, "Choose an image: robot facing North", 
                           os.getcwd(), "", wildcard, wx.OPEN | wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
            self.fileNorth = dlg.GetPath()
        dlg.Destroy()  
        dlg = wx.FileDialog(self, "Choose an image: robot facing East", 
                           os.getcwd(), "", wildcard, wx.OPEN | wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
            self.fileEast = dlg.GetPath()
        dlg.Destroy()  
        dlg = wx.FileDialog(self, "Choose an image: robot facing West", 
                           os.getcwd(), "", wildcard, wx.OPEN | wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
            self.fileWest = dlg.GetPath()
        dlg.Destroy()  
        image_south = images.GREY_ROBOT_S
        image_north = images.GREY_ROBOT_N
        image_east = images.GREY_ROBOT_E
        image_west = images.GREY_ROBOT_W
        try:
            image_south = wx.Image(self.fileSouth).ConvertToBitmap()
            image_north = wx.Image(self.fileNorth).ConvertToBitmap()
            image_east = wx.Image(self.fileEast).ConvertToBitmap()
            image_west = wx.Image(self.fileWest).ConvertToBitmap()
        except Exception, info:
            print "Conversion or loading problems: can not use new images."
            print "info = %", info
        images.GREY_ROBOT_S = image_south
        images.GREY_ROBOT_N = image_north
        images.GREY_ROBOT_E = image_east
        images.GREY_ROBOT_W = image_west
        self.AddRemoveRobot(event) # remove robot with old image
        self.AddRemoveRobot(event) # and add new one

class MySplashScreen(wx.SplashScreen):
    def __init__(self):
        wx.SplashScreen.__init__(self, images.SPLASH_SCREEN,
                wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT, 100, None, -1,
                style = wx.SIMPLE_BORDER|wx.FRAME_NO_TASKBAR|wx.STAY_ON_TOP)
        wx.EVT_CLOSE(self, self.OnClose)

    def OnClose(self, evt):
        dummy = RURApp()
        evt.Skip()

if __name__ == "__main__":
    Splash = MySplashScreen()
    Splash.Show()
    App.MainLoop()

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.