#JES- Jython Environment for Students
#Copyright (C) 2002 Jason Ergle, Claire Bailey, David Raines, Joshua Sklare
#See JESCopyright.txt for full licensing information
# 5/16/03: Added coloring to the load button to indicate concurrency with the
# editor document -AdamW
import JESHomeworkTurninThread
import JESCommandWindow
import JESConstants
import JESDebugWindow
import JESEditor
import JESProgram
import JESHomeworkSubmission
import JESDBVariableWatcher
import Html_Browser
import JESGutter
import media
import java.awt as awt
import java.util as util
import java.awt.Event as Event
import java.awt.event.KeyEvent as KeyEvent
import java.lang as lang
import httplib
import java.net as net
import os
import string
import JESAddressFinder
from java.awt.event import ActionListener
from pawt import swing
import java.awt.print as printer
import JESPrintableDocument
import java.lang.System as System
MENU_SEPARATOR = '-'
COMMAND_NEW = 'New'
COMMAND_OPEN = 'Open'
COMMAND_SAVE = 'Save'
COMMAND_SAVEAS = 'Save As...'
COMMAND_EXIT = 'Exit'
COMMAND_CUT = 'Cut'
COMMAND_COPY = 'Copy'
COMMAND_PASTE = 'Paste'
COMMAND_UNDO = 'Undo'
COMMAND_GOTO = 'Goto Line ...'
COMMAND_OPTIONS = 'Options'
COMMAND_HELP = 'Help'
COMMAND_ABOUT = 'About JES'
COMMAND_SEARCH = 'Search'
COMMAND_LOAD = 'Load'
COMMAND_EDITOR = 'Editor'
COMMAND_COMMAND= 'Command'
COMMAND_EXPLORE= 'Expain'
COMMAND_SOUND_TOOL = 'Sound Tool...'
COMMAND_PICTURE_TOOL = 'Picture Tool...'
TURNIN_OPTIONS = 'Register...'
TURNIN_HW = 'Assignment'
DEBUG_SHOW_DEBUGGER = 'Open Debugger'
DEBUG_HIDE_DEBUGGER = 'Hide Debugger'
DEBUG_WATCH_VAR = 'add Variable...'
DEBUG_UNWATCH_VAR = 'remove Variable...'
PRINT= 'Print'
FILE_TITLE = 'File'
EDIT_TITLE = 'Edit'
HELP_TITLE = 'Help'
TURNIN_TITLE = 'Turnin'
DEBUG_TITLE = 'Debug'
MEDIA_TOOLS_TITLE = 'MediaTools'
HELP_FILE_EXTENTION = '.html'
if System.getProperty('os.name').find('Mac') <> -1: # if we are on a Mac
CONTROL_KEY = Event.META_MASK
else:
CONTROL_KEY = Event.CTRL_MASK
#The following is an array that is used to build the main menu bar. The
#information stored in here is the high level menu item names, the menu bar
#option names, and the accelerator keys for those menu options.
MENU_OPTIONS = [
[FILE_TITLE,
[[COMMAND_NEW, KeyEvent.VK_N, CONTROL_KEY],
[COMMAND_OPEN, KeyEvent.VK_O, CONTROL_KEY],
[COMMAND_SAVE, KeyEvent.VK_S, CONTROL_KEY],
[COMMAND_SAVEAS, KeyEvent.VK_S, CONTROL_KEY + Event.SHIFT_MASK],
[COMMAND_LOAD, KeyEvent.VK_L, CONTROL_KEY],
[PRINT, KeyEvent.VK_P, CONTROL_KEY],
[MENU_SEPARATOR, 0, 0],
[COMMAND_EXIT, KeyEvent.VK_Q, CONTROL_KEY]]],
[EDIT_TITLE,
[[COMMAND_EDITOR, KeyEvent.VK_UP, CONTROL_KEY],
[COMMAND_COMMAND,KeyEvent.VK_DOWN,CONTROL_KEY],
[MENU_SEPARATOR, 0, 0],
[COMMAND_CUT, KeyEvent.VK_X, CONTROL_KEY],
[COMMAND_COPY, KeyEvent.VK_C, CONTROL_KEY],
[COMMAND_PASTE, KeyEvent.VK_V, CONTROL_KEY],
[COMMAND_UNDO, KeyEvent.VK_Z, CONTROL_KEY],
[COMMAND_GOTO, KeyEvent.VK_G, CONTROL_KEY],
[COMMAND_SEARCH, KeyEvent.VK_F, CONTROL_KEY],
[COMMAND_OPTIONS, 0, 0]]],
[TURNIN_TITLE,
[[TURNIN_HW,0,0],
[TURNIN_OPTIONS,0,0]]],
[DEBUG_TITLE,
[[DEBUG_SHOW_DEBUGGER,0,0,1], # this is a checkBoxMenuItem
#[DEBUG_BREAK,0,0],
[DEBUG_WATCH_VAR,0,0],
[DEBUG_UNWATCH_VAR,0,0]]],
[MEDIA_TOOLS_TITLE,
[[COMMAND_SOUND_TOOL, 0, 0],
[COMMAND_PICTURE_TOOL, 0, 0]]],
[HELP_TITLE,
[[COMMAND_ABOUT, 0, 0],
[COMMAND_EXPLORE,KeyEvent.VK_E, CONTROL_KEY]]]]
LOAD_BUTTON_CAPTION = 'Load'
STOP_BUTTON_CAPTION = 'Stop'
SHOW_DEBUGGER_CAPTION = 'Show Debugger'
HIDE_DEBUGGER_CAPTION = 'Hide Debugger'
UNTITLED_FILE_NAME = 'Untitled'
HELP_URL = ''
LOAD_STATUS_CURRENT = ''
LOAD_STATUS_DIFF = ' UNLOADED '
MIN_COMMAND_WINDOW_SIZE = 150
MAX_COMMAND_WINDOW_SIZE = 250
VISUAL_CONTROL_MARGIN_SIZE = 5
SPLITTER_SIZE = 10
SPLITTER_LOCATION = 320
BUTTON_PANE_HEIGHT = 15
STATUS_BAR_HEIGHT = 30
PROMPT_SAVE_MESSAGE = 'You should save the file that you are working\non before loading or submitting it.\n-Would you like to save now?'
PROMPT_SAVE_CAPTION = 'Save File?'
FocusOwner = None
class JESUI(swing.JFrame):
FocusOwner = None
################################################################################
# Function name: __init__
# Return:
# An instance of the JESUI class.
# Description:
# Creates a new instance of the JESUI.
################################################################################
def __init__(self, program):
try:
self.FocusOwner = None
self.swing = swing
self.program = program
self.size = JESConstants.INITIAL_WINDOW_SIZE
self.windowClosing = self.exit
self.contentPane.setLayout(swing.BoxLayout(self.contentPane,
swing.BoxLayout.Y_AXIS))
self.setIconImage(swing.ImageIcon("jesicon.gif").getImage())
#Create the visual components that will be placed in the UI
self.editor = JESEditor.JESEditor(self)
self.commandWindow = JESCommandWindow.JESCommandWindow(self)
self.loadButton = swing.JButton(LOAD_BUTTON_CAPTION,
actionPerformed=self.actionPerformed)
self.loadButton.enabled = 0
self.loadStatus = swing.JLabel()
self.stopButton = swing.JButton(STOP_BUTTON_CAPTION,
actionPerformed=self.actionPerformed)
self.debuggerButton = swing.JButton(SHOW_DEBUGGER_CAPTION,
actionPerformed=self.actionPerformed)
self.runningBar = swing.JProgressBar(0, 5, string='',
preferredSize=(50, 30))
self.cursorStatusLabel = swing.JLabel()
self.cursorStatusLabel.setBorder(swing.BorderFactory.createEmptyBorder
(0,
VISUAL_CONTROL_MARGIN_SIZE,
0,
VISUAL_CONTROL_MARGIN_SIZE))
self.nameStatusLabel = swing.JLabel()
self.nameStatusLabel.setBorder(swing.BorderFactory.createEmptyBorder
(0,
VISUAL_CONTROL_MARGIN_SIZE,
0,
VISUAL_CONTROL_MARGIN_SIZE))
self.docpane = swing.JPanel()
self.docpane.setLayout(swing.BoxLayout(self.docpane, swing.BoxLayout.X_AXIS))
self.gutter = JESGutter(self.editor, self.editor.getFont())
self.gutter.setPreferredSize(awt.Dimension(25,300))
self.gutter.setBorder(swing.BorderFactory.createEtchedBorder())
if self.program.gutterOn:
self.docpane.add(self.gutter)
self.docpane.add(self.editor)
#Create and set up the panes that all visual components reside on
splitterPane = swing.JSplitPane()
editorPane = swing.JScrollPane(self.docpane)
buttonPane = swing.JPanel()
commandPane = swing.JScrollPane(self.commandWindow)
bottomPane = swing.JPanel()
statusbar = swing.JPanel()
self.settingsWindow= None
self.errorWindow= None
self.turninWindow=None
self.namefield = None
self.mailfield=None
self.gtfield=None
self.optionsWindow=None
self.listPane=None
self.titlefield=swing.JTextField()
self.gotoFrame=None
self.linefield=swing.JTextField()
self.searchFrame=None
self.searchfield=swing.JTextField()
self.up=swing.JRadioButton("Search Up")
self.down = swing.JRadioButton("Search Down",1)
self.attachmentlist=None
self.list = None
self.notesToTA=swing.JTextArea()
self.notesScrollPane = swing.JScrollPane(self.notesToTA)
self.notesScrollPane.setVerticalScrollBarPolicy(swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS)
splitterPane.orientation = swing.JSplitPane.VERTICAL_SPLIT
splitterPane.leftComponent = editorPane
splitterPane.rightComponent = bottomPane
splitterPane.setDividerSize(SPLITTER_SIZE)
splitterPane.setDividerLocation(SPLITTER_LOCATION)
splitterPane.setResizeWeight(1.0)
editorPane.setPreferredSize(awt.Dimension(lang.Short.MAX_VALUE,
lang.Short.MAX_VALUE))
editorPane.getVerticalScrollBar().setUnitIncrement(14)
buttonPane.setLayout(awt.BorderLayout())
#buttonPane.setBorder(swing.BorderFactory.createEmptyBorder
# (VISUAL_CONTROL_MARGIN_SIZE,
# VISUAL_CONTROL_MARGIN_SIZE,
# VISUAL_CONTROL_MARGIN_SIZE,
# VISUAL_CONTROL_MARGIN_SIZE))
buttonPane.setMaximumSize(awt.Dimension(lang.Short.MAX_VALUE,
BUTTON_PANE_HEIGHT))
commandPane.setMinimumSize(awt.Dimension(0, MIN_COMMAND_WINDOW_SIZE))
bottomPane.setLayout(swing.BoxLayout(bottomPane,
swing.BoxLayout.Y_AXIS))
statusbar.setMinimumSize(awt.Dimension(0, STATUS_BAR_HEIGHT))
statusbar.setMaximumSize(awt.Dimension(lang.Short.MAX_VALUE,
STATUS_BAR_HEIGHT))
statusbar.setLayout(awt.BorderLayout())
statusbar.setBorder(swing.BorderFactory.createLoweredBevelBorder())
#Add all of the components to the main frame
self.contentPane.add(splitterPane)
self.contentPane.add(statusbar)
eastBar = swing.JPanel()
#eastBar.setMaximumSize(awt.Dimension(lang.Short.MAX_VALUE,
# BUTTON_PANE_HEIGHT))
eastBar.add(self.debuggerButton)
eastBar.add(self.stopButton)
eastBar.add(self.runningBar)
westBar = swing.JPanel()
westBar.add(self.loadButton)
westBar.add(self.loadStatus)
bottomPane.add(buttonPane)
bottomPane.add(commandPane)
buttonPane.add(westBar, awt.BorderLayout.WEST)
#buttonPane.add(self.loadStatus, awt.BorderLayout.CENTER)
buttonPane.add(eastBar, awt.BorderLayout.EAST)
statusbar.add(self.cursorStatusLabel, awt.BorderLayout.WEST)
statusbar.add(self.nameStatusLabel, awt.BorderLayout.EAST)
self.turninstatuslabel=swing.JLabel("Creating Mail...")
self.turninstatuswindow=swing.JFrame("Turnin Status")
#Create the menu bar and menu items
self.menu = swing.JMenuBar()
self.setJMenuBar(self.menu)
for eachMenu in MENU_OPTIONS:
newMenu = swing.JMenu(eachMenu[0], actionPerformed=self.actionPerformed)
self.menu.add(newMenu)
#Create each menu option under the menu
for eachMenuItem in eachMenu[1]:
if eachMenuItem[0] == MENU_SEPARATOR:
newMenu.addSeparator()
else:
if len(eachMenuItem) > 3 and eachMenuItem[3] == 1:
newMenuItem = swing.JCheckBoxMenuItem(eachMenuItem[0],
actionPerformed = self.actionPerformed)
else:
newMenuItem = swing.JMenuItem(eachMenuItem[0],
actionPerformed = self.actionPerformed)
if eachMenuItem[1] <> 0:
newMenuItem.setAccelerator(swing.KeyStroke.getKeyStroke
(eachMenuItem[1],
eachMenuItem[2],
0))
newMenu.add(newMenuItem)
#If this is the help menu, store it in the self.helpMenu variable.
if eachMenu[0] == HELP_TITLE:
self.helpMenu = newMenu
if eachMenu[0] == DEBUG_TITLE:
self.debugMenu = newMenu
#print 'length:',len(self.debugMenu.subElements)
#print self.debugMenu.subElements[0].subElements
self.debugMenu.subElements[0].subElements[1].setEnabled(0)
self.debugMenu.subElements[0].subElements[2].setEnabled(0)
#Set remaining object variables
self.heldText = ''
self.setRunning(0)
self.setFileName('')
self.UpdateRowCol(1, 1)
self.UpdateName()
self.helpFiles = {}
self.helplist = []
except:
import traceback
import sys
a,b,c = sys.exc_info()
print "JESUI: WEIRD EXCEPT:"
traceback.print_exception(a,b,c)
################################################################################
# Function name: actionPerformed
# Parameters:
# -event: event object that represents action that occured
# Description:
# This function is called when a menu option is selected or a button is
# pressed. It calls the correct function in order to perform the action
# that the user wants.
################################################################################
def actionPerformed(self, event):
actionCommand = event.getActionCommand()
if actionCommand == COMMAND_NEW:
self.program.newFile()
elif actionCommand == COMMAND_OPEN:
self.program.openFile()
elif actionCommand == COMMAND_SAVE:
self.program.saveFile()
elif actionCommand == COMMAND_SAVEAS:
self.program.saveAs()
elif actionCommand == COMMAND_EXIT:
self.program.closeProgram()
elif actionCommand == COMMAND_CUT:
self.cut()
elif actionCommand == COMMAND_COPY:
self.copy()
elif actionCommand == PRINT:
self.printCommand()
elif actionCommand == COMMAND_PASTE:
self.paste()
elif actionCommand == COMMAND_UNDO:
self.undo()
elif actionCommand == COMMAND_GOTO:
self.getGoToLineNum()
elif actionCommand == COMMAND_SEARCH:
self.search()
elif actionCommand == COMMAND_OPTIONS:
self.openOptions()
elif actionCommand == COMMAND_HELP:
self.openBrowser(self, HELP_URL)
elif actionCommand == TURNIN_OPTIONS:
self.openSettings()
elif actionCommand == TURNIN_HW:
self.openTurnin(TURNIN_HW)
elif actionCommand == DEBUG_SHOW_DEBUGGER or actionCommand == DEBUG_HIDE_DEBUGGER:
self.program.interpreter.toggle_debug_mode()
elif actionCommand == DEBUG_WATCH_VAR:
self.watchVariable()
elif actionCommand == DEBUG_UNWATCH_VAR:
self.unwatchVariable()
elif actionCommand == COMMAND_ABOUT:
self.program.openAboutWindow()
elif (actionCommand == LOAD_BUTTON_CAPTION) or (actionCommand == COMMAND_LOAD):
if self.editor.modified:
if self.promptSave():
self.editor.document.removeErrorHighlighting()
self.program.loadFile()
else:
self.program.loadFile()
elif actionCommand == STOP_BUTTON_CAPTION:
self.program.stopThread()
elif actionCommand == SHOW_DEBUGGER_CAPTION or actionCommand == HIDE_DEBUGGER_CAPTION:
self.program.interpreter.toggle_debug_mode()
elif actionCommand == COMMAND_EDITOR:
self.editor.requestFocus()
elif actionCommand == COMMAND_COMMAND:
self.commandWindow.requestFocus()
elif actionCommand == COMMAND_EXPLORE:
self.openExploreWindow()
elif actionCommand == COMMAND_SOUND_TOOL:
self.loadSoundTool()
elif actionCommand == COMMAND_PICTURE_TOOL:
self.loadPictureTool()
else:
self.CheckIfHelpTopic(actionCommand)
###############################################################################
# Function: openExploreWindow
# Description:
# Examines the highlighted text in the JTextArea, and searches for it in the
# helplist. Then it pops up a help window with an API description.
###############################################################################
def openExploreWindow(self):
#Find The word under the cursor
try:
str = string.strip(self.FocusOwner.getSelectedText())
msg = "No entry found for '" + str + "'"
#Search the API help for the word (method)
for entry in self.helplist:
if string.strip(entry[0]) == str:
msg = entry[1]
break
except:
msg = "No text selected.
To use Explore, highlight a function name or keyword you want help with."
#Pop up the help window:
frame = swing.JFrame()
text = swing.JEditorPane("text/html", msg)
scrollpane = swing.JScrollPane(text)
text.setEditable(0)
frame.setSize(450, 250)
frame.setContentPane(scrollpane)
frame.show()
###############################################################################
# Function: loadCurrent
# Description:
# Updates the UI to reflact that the current code has been loaded
###############################################################################
def loadCurrent(self):
self.loadStatus.setText(LOAD_STATUS_CURRENT)
###############################################################################
# Function: loadDifferent
# Description:
# Updates the UI to reflact that the current code has not been loaded
###############################################################################
def loadDifferent(self):
self.loadStatus.setText(LOAD_STATUS_DIFF)
###############################################################################
# Function name: exit
# Parameters:
# -event: event object that represents the event that occured
# Description:
# This function, which closes the program, is called when the user closes
# the JES program with the 'X' on the main window.
################################################################################
def exit(self, event):
self.program.closeProgram()
################################################################################
# Function name: promptSave
# Return:
# TRUE if the file was saved successfully, FALSE if the save failed or the
# user decided not to save the file.
# Description:
# Prompts the user whether they want to save the currently loaded file.
################################################################################
def promptSave(self):
promptResult = swing.JOptionPane.showConfirmDialog(
self,
PROMPT_SAVE_MESSAGE,
PROMPT_SAVE_CAPTION,
swing.JOptionPane.CANCEL_OPTION
+ swing.JOptionPane.YES_OPTION)
if promptResult == swing.JOptionPane.YES_OPTION:
return self.program.saveFile()
else:
return 0
################################################################################
# Function name: openBrowser
# Parameters:
# -url: Target URL or file name for the browser. If a file name is given,
# the entire path to that file must also be included.
# Description:
# Opens a browser window to the specified location. This is used when
# displaying the HTML help.
################################################################################
def openBrowser(self, target):
try:
j=Html_Browser.Html_Browser(target)
j.show()
except:
print "ERROR opening broswer with file:",target
################################################################################
# Function name: setRunning
# Parameters:
# -runBool: Boolean identifying whether the program is running.
# Description:
# This function is called to tell the GUI whether the Jython interpreter is
# running any code. When running, the GUI will enable the stop button,
# disable the load button, and change the cursor to an hourglass.
################################################################################
def setRunning(self, runBool):
self.running = runBool
self.loadButton.enabled = not runBool
self.stopButton.enabled = runBool
if runBool:
cursor = awt.Cursor(awt.Cursor.WAIT_CURSOR)
textCursor = cursor
else:
cursor = awt.Cursor(awt.Cursor.DEFAULT_CURSOR)
textCursor = awt.Cursor(awt.Cursor.TEXT_CURSOR)
self.setCursor(cursor)
self.editor.setCursor(textCursor)
self.commandWindow.setCursor(textCursor)
################################################################################
# Function name: setFileName
# Parameters:
# -filename: name of the currenly open file
# Description:
# Sets the file name that is displayed in the program caption. If the
# filename parameter is set to '', then the file name will be shown as
# 'Untitled'.
################################################################################
def setFileName(self, filename):
if filename == '':
filename = UNTITLED_FILE_NAME
self.title = JESConstants.APPLICATION_TITLE % filename
################################################################################
# Function name: callTextEditFunction
# Description:
# Performs the cut operation on the either the editor or command window,
# depending on which one has the focus.
################################################################################
def callTextEditFunction(self, function):
#global FocusOwner
focusedComponent = self.FocusOwner #self.getFocusOwner()
if isinstance(focusedComponent, swing.JTextPane):
focusedComponent.function()
################################################################################
# Function name: cut
# Description:
# Performs the cut operation on the either the editor or command window,
# depending on which one has the focus.
################################################################################
def cut(self):
#global FocusOwner
#focusedComponent = self.getFocusOwner()
focusedComponent = self.FocusOwner
if isinstance(focusedComponent, swing.JTextPane):
focusedComponent.cut()
################################################################################
# Function name: copy
# Description:
# Performs the copy operation on the either the editor or command window,
# depending on which one has the focus.
################################################################################
def copy(self):
#global FocusOwner
focusedComponent = self.FocusOwner #self.getFocusOwner()
if isinstance(focusedComponent, swing.JTextPane):
focusedComponent.copy()
################################################################################
# Function name: paste
# Description:
# Performs the paste operation on the either the editor or command window,
# depending on which one has the focus.
################################################################################
def paste(self):
#global FocusOwner
focusedComponent = self.FocusOwner #self.getFocusOwner()
if isinstance(focusedComponent, swing.JTextPane):
focusedComponent.paste()
################################################################################
# Function name: undo
# Description:
# Performs the undo operation on the either the editor or command window,
# depending on which one has the focus.
################################################################################
def undo(self):
#global FocusOwner
focusedComponent = self.FocusOwner #self.getFocusOwner()
if isinstance(focusedComponent, swing.JTextPane):
focusedComponent.undo()
################################################################################
# Function name: print
# Description:
# Prints the current Document contained in JES
################################################################################
def printCommand(self):
try:
#Sets up local variables according to an existing config file.
array=self.program.readFromConfigFile()
name=array[JESConstants.CONFIG_NAME]
except:
#If we have a problem, just set them all to the empty string
name='Unknown'
isSaved=1
if self.editor.modified:
isSaved=self.promptSave()
if isSaved != 0:
printerJob = printer.PrinterJob.getPrinterJob()
printerJob.setPrintable( JESPrintableDocument.JESPrintableDocument(self.program.filename,name) )
doPrint = printerJob.printDialog()
if (doPrint):
try:
printerJob.print()
except:
print "Printing error"
################################################################################
# Function name: UpdateRowCol
# Parameters:
# -row: current row that the cursor is on
# -col: current column that the cursor is on
# Description:
# Updates the status bar with the given row and column.
################################################################################
def UpdateRowCol(self, row, col):
self.cursorStatusLabel.text ='Line Number:' + str(col) + ' Position: ' + str(row)
self.cursorStatusLabel.setForeground(awt.Color.black)
def UpdateName(self):
try:
array=self.program.readFromConfigFile()
name=array[JESConstants.CONFIG_NAME]
name='Current User: '+ name + ' '
self.nameStatusLabel.text =name
self.nameStatusLabel.setForeground(awt.Color.black)
except:
self.nameStatusLabel.text ='Not Registered '
################################################################################
# Function name: SetHelpFiles
# Parameters:
# -helpFiles: array of file names (including entire path) for all help files
# that will be added to help menu.
# Description:
# Adds the help files specified in the helpFiles parameter to the help menu.
################################################################################
def SetHelpFiles(self, helpFiles):
self.helpFiles = {}
self.helpMenu.addSeparator()
for eachHelpFilePath in helpFiles:
fileName = os.path.basename(eachHelpFilePath)
fileName = fileName.replace(HELP_FILE_EXTENTION, '')
fileName = fileName.replace('_', ' ')
self.helpFiles[fileName] = eachHelpFilePath
newMenuItem = swing.JMenuItem(fileName,
actionPerformed = self.actionPerformed)
self.helpMenu.add(newMenuItem)
#Set up contextual help list
helpfile = open(JESConstants.JES_API_HELP_FILE, 'r')
helpcontents = helpfile.read()
helpl = helpcontents.split("_")
for entry in helpl:
self.helplist.append(entry.split("|"))
helpfile.close()
################################################################################
# Function name: CheckIfHelpTopic
# Parameters:
# -helpTopic: string containing the name of the menu option to be checked
# Return:
# Returns true if the helpTopic variable was the name of a help topic, or
# false if it was not.
# Description:
# Checks to see if the given string (specified in the helpTopic parameter)
# is the name of a help topic. If it is, the openBrowser function is called
# to open up that help file.
################################################################################
def CheckIfHelpTopic(self, helpTopic):
if self.helpFiles.has_key(helpTopic):
self.openBrowser(self.helpFiles[helpTopic])
return 1
else:
return 0
################################################################################
# Function name: openSettings
# Description:
# Opens up a JES settings dialog. If the window has not been created, it is
# created. If the config file does not exist, the string in it are set to
# empty strings. Once everything is created, it is made visible. If the
# window already exists, but it is hidden, it is just made visible.
################################################################################
def openSettings(self):
if self.settingsWindow== None:
try:
#Sets up local variables according to an existing config file.
array=self.program.readFromConfigFile()
name=array[JESConstants.CONFIG_NAME]
gt=array[JESConstants.CONFIG_GT]
mail=array[JESConstants.CONFIG_MAIL]
mailaddr = array[JESConstants.CONFIG_EMAIL_ADDR]
webDefs = array[JESConstants.CONFIG_WEB_TURNIN]
except:
#If we have a problem, just set them all to the empty string
name=''
gt=''
mailaddr = ''
mail = JESConstants.MAIL_SERVER
webDefs = JESConstants.WEB_DEFINITIONS
#Creating the window
self.settingsWindow=swing.JFrame("JES Settings")
self.settingsWindow.contentPane.layout = awt.GridLayout(0,2)
self.settingsWindow.size = (250,150)
savebutton = swing.JButton("Save Changes",preferredSize=(100,20),
actionPerformed=self.settingsButtonPressed)
cancelbutton= swing.JButton("Cancel",preferredSize=(100,20),
actionPerformed=self.settingsButtonPressed)
self.namefield= swing.JTextField(name,preferredSize=(200,20))
namelabel=swing.JLabel("Name:")
self.gtfield= swing.JTextField(gt,preferredSize=(200,20))
gtlabel=swing.JLabel("Student #:")
self.mailaddrfield= swing.JTextField(mailaddr,preferredSize=(200,20))
mailaddrlabel=swing.JLabel("Email Address:")
self.mailfield= swing.JTextField(mail,preferredSize=(200,20))
maillabel=swing.JLabel("Mail Server:")
self.webDefsField = swing.JTextField(webDefs, preferredSize=(200,20))
webDefslabel = swing.JLabel("Turnin Definitions:")
self.settingsWindow.contentPane.add(namelabel)
self.settingsWindow.contentPane.add(self.namefield)
self.settingsWindow.contentPane.add(gtlabel)
self.settingsWindow.contentPane.add(self.gtfield)
if JESConstants.EMAIL_TURNIN:
self.settingsWindow.contentPane.add(mailaddrlabel)
self.settingsWindow.contentPane.add(self.mailaddrfield)
self.settingsWindow.contentPane.add(maillabel)
self.settingsWindow.contentPane.add(self.mailfield)
if JESConstants.COWEB_TURNIN:
pass
#self.settingsWindow.contentPane.add(webDefslabel)
#self.settingsWindow.contentPane.add(self.webDefsField)
self.settingsWindow.contentPane.add(cancelbutton)
self.settingsWindow.contentPane.add(savebutton)
self.settingsWindow.pack()
self.settingsWindow.show()
else:
self.settingsWindow.show()
################################################################################
# Function name: settingsButtonPressed
# Parameters: event
# Description:
# Handles events thrown from the settings dialog window.
################################################################################
def settingsButtonPressed(self,event):
if event.source.text=='Cancel':
pass
self.settingsWindow.hide()
else:
list = []
if self.namefield.text != None:
list.append([JESConstants.CONFIG_NAME, self.namefield.text])
if self.gtfield.text != None:
list.append([JESConstants.CONFIG_GT, self.gtfield.text])
if self.mailfield.text != None:
list.append([JESConstants.CONFIG_MAIL, self.mailfield.text])
if self.mailaddrfield.text != None:
list.append([JESConstants.CONFIG_EMAIL_ADDR, self.mailaddrfield.text])
if self.webDefsField.text != None:
list.append([JESConstants.CONFIG_WEB_TURNIN, self.webDefsField.text])
self.program.writeConfigListToFile(list)
self.UpdateName()
self.settingsWindow.hide()
################################################################################
# Function name: openTurnin
# Description:
# Opens up a JES Turnin dialog.
################################################################################
def openTurnin(self,toTurnin):
#decides what you are turning in.
self.turninWindow=swing.JFrame('Assignment Submission')
self.turninWindow.contentPane.layout = awt.GridLayout(3,1)
self.turninWindow.size = (300,400)
self.notesToTA.setText('')
self.notesToTA.setLineWrap(1)
self.notesToTA.setWrapStyleWord(1)
notesLabel=swing.JLabel("Notes to TA:")
self.notesScrollPane.size = (240, 200)
toSubmitLabel=swing.JLabel("Submitting file:")
fileNameLabel=swing.JLabel(os.path.basename(self.program.filename))
titlelabel = swing.JLabel('Assignment to submit: ')
turninbutton = swing.JButton("Turnin",preferredSize=(100,20), actionPerformed=self.turninButtonPressed)
cancelbutton= swing.JButton("Cancel",preferredSize=(100,20), actionPerformed=self.turninButtonPressed)
addbutton = swing.JButton("Add File",preferredSize=(120,20), actionPerformed=self.turninButtonPressed)
removebutton= swing.JButton("Remove File",preferredSize=(120,20), actionPerformed=self.turninButtonPressed)
assignmentStrings=self.grabAssignmentList()
self.titlefield=swing.JComboBox(assignmentStrings)
self.attachmentlist=util.Vector()
self.list=swing.JList(self.attachmentlist)
self.listPane=swing.JScrollPane(self.list)
self.listPane.preferredSize=(100,100)
try:
array=self.program.readFromConfigFile()
name=array[JESConstants.CONFIG_NAME]
gt=array[JESConstants.CONFIG_GT]
mail=array[JESConstants.CONFIG_MAIL]
namelabel=swing.JLabel("Name: "+name)
maillabel=swing.JLabel("Media Files Attached: ")
gtlabel=swing.JLabel("Student ID#: "+gt)
blanklabel=swing.JLabel("")
#Layout the components
turninProperties = swing.JPanel()
turninProperties.size = (150,50)
turninProperties.layout = awt.GridLayout(4, 2)
turninProperties.add(namelabel)
turninProperties.add(gtlabel)
turninProperties.add(toSubmitLabel)
turninProperties.add(fileNameLabel)
turninProperties.add(titlelabel)
turninProperties.add(self.titlefield)
turninProperties.add(blanklabel)
self.turninWindow.contentPane.add(turninProperties, awt.BorderLayout.NORTH)
attachPane = swing.JPanel()
attachPane.layout = awt.BorderLayout()
attachPane.add(maillabel, awt.BorderLayout.NORTH)
attachPane.add(self.listPane, awt.BorderLayout.CENTER)
buttonPane = swing.JPanel()
buttonPane.layout = awt.GridLayout(1,2)
buttonPane.add(removebutton)
buttonPane.add(addbutton)
attachPane.add(buttonPane, awt.BorderLayout.SOUTH)
self.turninWindow.contentPane.add(attachPane, awt.BorderLayout.CENTER)
notesPane = swing.JPanel()
notesPane.layout = awt.BorderLayout()
notesPane.add(notesLabel, awt.BorderLayout.NORTH)
notesPane.add(self.notesScrollPane, awt.BorderLayout.CENTER)
sendPane = swing.JPanel()
sendPane.layout = awt.GridLayout(1,2)
sendPane.add(cancelbutton)
sendPane.add(turninbutton)
notesPane.add(sendPane, awt.BorderLayout.SOUTH)
notesPane.size = (200, 300)
self.turninWindow.contentPane.add(notesPane, awt.BorderLayout.SOUTH)
#self.turninWindow.contentPane.add(toSubmitLabel)
#self.turninWindow.contentPane.add(fileNameLabel)
#self.turninWindow.contentPane.add(titlelabel)
#self.turninWindow.contentPane.add(self.titlefield)
#self.turninWindow.contentPane.add(namelabel)
#self.turninWindow.contentPane.add(gtlabel)
#self.turninWindow.contentPane.add(maillabel)
#self.turninWindow.contentPane.add(self.listPane)
#self.turninWindow.contentPane.add(removebutton)
#self.turninWindow.contentPane.add(addbutton)
#self.turninWindow.contentPane.add(notesLabel)
#self.turninWindow.contentPane.add(self.notesScrollPane)
#self.turninWindow.contentPane.add(cancelbutton)
#self.turninWindow.contentPane.add(turninbutton)
self.turninWindow.pack()
self.turninWindow.show()
except:
a="JES needs to know who you are to turn in something. \n"
b="Please choose Register from the Turnin menu to set JES's\n preferences. "
c="When you are done you can try to turn this \nassignment in again."
self.errorWindow=swing.JFrame()
swing.JOptionPane.showMessageDialog(self.errorWindow,
a+b+c,
"Error - JES properties have not been set",
swing.JOptionPane.WARNING_MESSAGE)
################################################################################
# Function name: turninButtonPressed
# Description:
# Handles events from turnin dialog
################################################################################
def turninButtonPressed(self,event):
if event.source.text=='Turnin':
try:
isSaved=1
title= self.titlefield.getSelectedItem()
if self.editor.modified:
isSaved=self.promptSave()
if self.program.filename == '':
isSaved=0
if isSaved != 0:
if title !='Assignments':
filename=self.program.filename
array=self.program.readFromConfigFile()
gt=array[JESConstants.CONFIG_GT]
zip=self.buildFileArchive(gt,title,filename)
j = JESHomeworkSubmission.JESHomeworkSubmission(title,filename,zip)
thread = JESHomeworkTurninThread.JESHomeworkTurninThread(j,self,zip)
self.turninstatuswindow=swing.JFrame("Turnin Status")
self.turninstatuswindow.contentPane.layout=awt.GridLayout(1,2)
self.turninstatuswindow.contentPane.add(swing.JLabel(swing.ImageIcon("Thinking.gif")))
self.turninstatuswindow.contentPane.add(self.turninstatuslabel)
self.turninstatuswindow.setSize(400,150)
self.turninstatuswindow.show()
thread.start()
self.turninWindow.dispose()
else:
self.turninWindow.dispose()
self.errorWindow=swing.JFrame()
swing.JOptionPane.showMessageDialog(self,
'You must select an assignment from the list to submit.',
'Turnin cannot complete.',
swing.JOptionPane.WARNING_MESSAGE)
else:
self.turninWindow.dispose()
self.errorWindow=swing.JFrame()
swing.JOptionPane.showMessageDialog(self,
'There is no file open to submit, or the current file has not been saved.',
'Turnin cannot complete.',
swing.JOptionPane.WARNING_MESSAGE)
except Exception, string:
self.turninWindow.dispose()
a="An error has occurred in the turnin process. "
b="It is likely\n that the program turnin has failed. Please "
c="check JES's settings and\n resubmit the assignment."
d=" Error:" + string
self.errorWindow=swing.JFrame()
swing.JOptionPane.showMessageDialog(self,
a+b+c+d,
"Error - Turnin has failed",
swing.JOptionPane.WARNING_MESSAGE)
elif event.source.text == "Add File":
chooser = swing.JFileChooser()
chooser.setApproveButtonText("Attach File")
returnVal = chooser.showOpenDialog(self.turninWindow)
if returnVal == 0: #User has chosen a file, so now it can be opened
self.attachmentlist.add(chooser.getSelectedFile().getPath())
self.list.setListData(self.attachmentlist)
elif event.source.text == "Remove File":
self.attachmentlist.remove(self.list.getSelectedValue())
self.list.setListData(self.attachmentlist)
else:
self.turninWindow.dispose()
########################################################################
# Method: buildFileArchive
# Parameters:
# -gt: The GT number of the student
# -title: The title of the homework
# -The working file to zip up. Is actually the contents of the Editor
# Description:
# Constructs a zip file of all the submission materials for a CS1315
# assigment. The file title will be of the form: gtXXXX-.zip. Will also include any added files and notes from the
# turnin dialog.
########################################################################
def buildFileArchive(self,gt,title,fileToSend):
import zipfile
filenames=self.attachmentlist
writename = gt+'-'+title+'.zip'
writename=writename.strip()
writename=string.replace(writename," ","_")
#open the zipfile for writing
file = zipfile.ZipFile(writename, "w")
file.write(fileToSend,os.path.basename(fileToSend),zipfile.ZIP_DEFLATED)
for name in filenames:
file.write(name,os.path.basename(name),zipfile.ZIP_DEFLATED)
#Create and add a text file with the notes to the TA:
notesTA = open(".notesTA.txt", "w")
notesTA.write(self.notesToTA.getText())
notesTA.close()
file.write(".notesTA.txt", "notesTA.txt", zipfile.ZIP_DEFLATED)
file.close()
return writename
########################################################################
def grabAssignmentList(self):
try:
ret=['Assignments']
url = net.URL(JESConstants.ASSIGNMENT_URL)
h = httplib.HTTP(url.getHost())
h.putrequest('GET', url.getFile())
h.putheader('Accept', 'text/html')
h.putheader('Accept', 'text/plain')
h.endheaders()
errcode, errmsg, headers = h.getreply()
f = h.getfile()
data = f.read() # Get the raw HTML
f.close()
#Remove #BEGIN and #END from file
tempArr=string.split(data,'#BEGIN')
data=tempArr[1]
tempArr=string.split(data,'#END')
data=tempArr[0]
data=data.split("|")
for x in data:
arr=x.strip()
ret.append(arr)
return ret
except:
print "Error reading assignment list from network"
return ['Assignments']
################################################################################
# Function name: openTurnin
# Description:
# Opens up a JES Turnin dialog.
################################################################################
def openOptions(self):
self.optionsWindow=swing.JFrame('JES Options')
self.optionsWindow.contentPane.layout = awt.GridLayout(5,2)
self.optionsWindow.size = (250,450)
donebutton = swing.JButton("Done",preferredSize=(100,20),
actionPerformed=self.optionsButtonPressed)
cancelbutton= swing.JButton("Cancel",preferredSize=(100,20),
actionPerformed=self.optionsButtonPressed)
modelabel=swing.JLabel("Mode:")
fontlabel=swing.JLabel("Font:")
gutterlabel=swing.JLabel("Line Numbers:")
blocklabel=swing.JLabel("Block Boxes:")
if self.program.gutterOn:
self.gutterBox = swing.JCheckBox("", 1)
else:
self.gutterBox = swing.JCheckBox("", 0)
if self.program.blockBoxOn:
self.blockBox = swing.JCheckBox("", 1)
else:
self.blockBox = swing.JCheckBox("", 0)
if self.program.userExperience == JESConstants.BEGINNER_MODE:
self.userExperienceField = swing.JComboBox( JESConstants.USER_MODES)
else:
self.userExperienceField = swing.JComboBox( JESConstants.USER_MODES_2)
if int(self.program.userFont) == int(JESConstants.LOW_FONT):
self.userFontField = swing.JComboBox( JESConstants.FONT_MODE_LOW)
elif int(self.program.userFont) == int(JESConstants.MID_FONT):
self.userFontField = swing.JComboBox( JESConstants.FONT_MODE_MID)
else:
self.userFontField = swing.JComboBox( JESConstants.FONT_MODE_HIGH)
self.optionsWindow.contentPane.add(modelabel)
self.optionsWindow.contentPane.add(self.userExperienceField)
self.optionsWindow.contentPane.add(fontlabel)
self.optionsWindow.contentPane.add(self.userFontField)
self.optionsWindow.contentPane.add(gutterlabel)
self.optionsWindow.contentPane.add(self.gutterBox)
self.optionsWindow.contentPane.add(blocklabel)
self.optionsWindow.contentPane.add(self.blockBox)
self.optionsWindow.contentPane.add(cancelbutton)
self.optionsWindow.contentPane.add(donebutton)
self.optionsWindow.pack()
self.optionsWindow.show()
def optionsButtonPressed(self,event):
if event.source.text=='Done':
self.program.userExperience = self.userExperienceField.getSelectedItem()
self.program.userFont = self.userFontField.getSelectedItem()
self.program.blockBoxOn = self.blockBox.isSelected()
self.program.gutterOn = self.gutterBox.isSelected()
self.program.writeConfigListToFile([[JESConstants.CONFIG_MODE, self.program.userExperience],
[JESConstants.CONFIG_FONT, self.program.userFont],
[JESConstants.CONFIG_GUTTER, self.program.gutterOn],
[JESConstants.CONFIG_BLOCK, self.program.blockBoxOn]])
self.optionsWindow.dispose()
# change fonts on the fly.
editorDocument = self.editor.getDocument()
editorDocument.changeFontSize(self.program.userFont)
commandDocument = self.commandWindow.getDocument()
commandDocument.changeFontSize(self.program.userFont)
if self.program.blockBoxOn == 0:
self.editor.removeBox()
else:
self.editor.addBox()
if self.program.gutterOn == 0:
self.turnOffGutter()
else:
self.turnOnGutter()
else:
self.optionsWindow.dispose()
######################################################################
# Function name: turnOffGutter
# Description:
# Turns the gutter off, removes it from the scrollpane
######################################################################
def turnOffGutter(self):
self.docpane.remove(self.gutter)
self.docpane.repaint()
######################################################################
# Function name: turnOnGutter
# Description:
# Turns the gutter on, adds it to the scrollpane
######################################################################
def turnOnGutter(self):
self.docpane.remove(self.gutter)
self.docpane.remove(self.editor)
self.docpane.add(self.gutter)
self.docpane.add(self.editor)
self.docpane.repaint()
def getGoToLineNum(self):
self.gotoFrame=swing.JFrame("Goto Line Number")
self.gotoFrame.contentPane.layout = awt.GridLayout(2,2)
self.gotoFrame.size=(200,75)
gotobutton = swing.JButton("Goto",preferredSize=(100,20),
actionPerformed=self.gotoButtonPressed)
cancelbutton= swing.JButton("Cancel",preferredSize=(100,20),
actionPerformed=self.gotoButtonPressed)
linelabel=swing.JLabel("Line #:")
self.gotoFrame.contentPane.add(linelabel)
self.gotoFrame.contentPane.add(self.linefield)
self.gotoFrame.contentPane.add(cancelbutton)
self.gotoFrame.contentPane.add(gotobutton)
self.gotoFrame.show()
def gotoButtonPressed(self,event):
if event.source.text=='Goto':
try:
a=int(self.linefield.text)
self.editor.document.gotoLine(a)
self.linefield.text=''
self.gotoFrame.dispose()
except:
self.linefield.text=''
self.gotoFrame.dispose()
else:
self.linefield.text=''
self.gotoFrame.dispose()
def search(self):
if self.searchFrame == None:
self.searchFrame=swing.JFrame("Search for Text")
self.searchFrame.contentPane.layout = awt.GridLayout(3,2)
self.searchFrame.size=(200,100)
findbutton = swing.JButton("Find",preferredSize=(100,20),
actionPerformed=self.searchButtonPressed)
donebutton= swing.JButton("Cancel",preferredSize=(100,20),
actionPerformed=self.searchButtonPressed)
group = swing.ButtonGroup()
group.add(self.up)
group.add(self.down)
buttonpanel = swing.JPanel()
buttonpanel.layout = awt.GridLayout(0,1)
buttonpanel.add(self.up)
buttonpanel.add(self.down)
searchlabel=swing.JLabel("Text to Find:")
self.searchFrame.contentPane.add(searchlabel)
self.searchFrame.contentPane.add(self.searchfield)
self.searchFrame.contentPane.add(buttonpanel)
self.searchFrame.contentPane.add(swing.JLabel())
self.searchFrame.contentPane.add(donebutton)
self.searchFrame.contentPane.add(findbutton)
self.searchFrame.show()
else:
self.searchFrame.show()
def searchButtonPressed(self,event):
if event.source.text=='Find':
try:
toFind=self.searchfield.text
if self.up.isSelected():
self.editor.document.searchBackward(toFind)
else:
self.editor.document.searchForward(toFind)
except:
self.searchfield.text=''
self.searchFrame.hide()
else:
self.searchfield.text=''
self.searchFrame.hide()
def errorWindowClose(self,event):
self.errorWindow.dispose()
def startWork(self):
self.runningBar.indeterminate = 1
def stopWork(self):
self.runningBar.indeterminate = 0
def addBreakPoint(self):
lineno = self.editor.getLineNo()
self.program.interpreter.debugger.set_break(self.program.filename, lineno)
# should contact the gutter here
def watchVariable(self):
var = JESDBVariableWatcher.variableDialog(self)
if var:
self.program.interpreter.debugger.addVariable(var)
def unwatchVariable(self):
var = JESDBVariableWatcher.pickVariable(self,
self.program.interpreter.debugger.watcher.getVariables())
if var:
self.program.interpreter.debugger.removeVariable(var)
######################################################################
# Function name: editorChanged()
# Description:
# Called whenever the editor document is changed, so the UI can
# update accordingly. Right now, only used for coloring the
# LOAD button
######################################################################
def editorChanged(self):
self.loadDifferent()
def refreshDebugState(self):
enabled = self.program.interpreter.debug_mode# and self.program.editorLoaded()
#print self.program.interpreter.debug_mode , self.program.editorLoaded()
self.debugMenu.subElements[0].subElements[0].setSelected(enabled)
self.debugMenu.subElements[0].subElements[1].setEnabled(enabled)
self.debugMenu.subElements[0].subElements[2].setEnabled(enabled)
self.program.interpreter.debugger.watcher.setVisible(enabled)
if not enabled:
self.debuggerButton.text = SHOW_DEBUGGER_CAPTION
self.debugMenu.subElements[0].subElements[0].text = DEBUG_SHOW_DEBUGGER
else:
self.debuggerButton.text = HIDE_DEBUGGER_CAPTION
self.debugMenu.subElements[0].subElements[0].text = DEBUG_HIDE_DEBUGGER
######################################################################
# Function name: loadSoundTool()
# Description:
# Examines the namespace for all instances of sound, and presents
# a list for the user to pick from. The chosen sound is then opened
# in the sound tool.
######################################################################
def loadSoundTool(self):
#l = globals()
l = self.program.interpreter.contextForExecution
sounds = []
soundsdict = {}
for i in l.items():
try:
if i[1].__class__.__name__ == 'Sound':
sounds.append(i[0])
soundsdict.setdefault(i[0], i[1])
except Exception, e:
pass
if len(sounds) > 0:
sound = swing.JOptionPane.showInputDialog(self, "Choose a sound to examine:",
"Open Sound Tool",
swing.JOptionPane.INFORMATION_MESSAGE,
None,
sounds,
sounds[0])
if sound != None:
media.openSoundTool(soundsdict[sound])
else:
swing.JOptionPane.showMessageDialog(self, "There are no sounds to examine.",
"No sounds",
swing.JOptionPane.ERROR_MESSAGE)
######################################################################
# Function name: loadPictureTool()
# Description:
# Examines the namespace for all instances of picture, and presents
# a list for the user to pick from. The chosen picture is then opened
# in the picture tool.
######################################################################
def loadPictureTool(self):
#l = globals()
l = self.program.interpreter.contextForExecution
pictures = []
picturesdict = {}
for i in l.items():
try:
if i[1].__class__.__name__ == 'Picture':
pictures.append(i[0])
picturesdict.setdefault(i[0], i[1])
except Exception, e:
pass
if len(pictures) > 0:
picture = swing.JOptionPane.showInputDialog(self, "Choose a picture to examine:",
"Open Picture Tool",
swing.JOptionPane.INFORMATION_MESSAGE,
None,
pictures,
pictures[0])
if picture != None:
media.openPictureTool(picturesdict[picture])
else:
swing.JOptionPane.showMessageDialog(self, "There are no pictures to examine.",
"No pictures",
swing.JOptionPane.ERROR_MESSAGE)