#!/data/data/com.termux/files/usr/bin/python
import tkinter as tk  # GUI toolkit
from tkinter import messagebox
import config  # config.py

class Application (tk.Frame):
	def __init__ (self, master = None):  # Constructor
		tk.Frame.__init__ (self, master)
		self.grid (sticky = tk.N + tk.S + tk.E + tk.W)
		# I'm leaving this here in case I want to draw a background image in the future.
		#self.imgBackground = tk.PhotoImage(file=config.defaultimage0)
		#self.lblBackground = tk.Label(self, image=self.imgBackground)
		#self.lblBackground.place(x=0, y=0, relwidth=1, relheight=1)
		self.createwidgets()  # Self-explanatory
		self.refreshlist (None)  # Fetch the list of games from the default group as defined in config.py

	def createwidgets (self):
		top=self.winfo_toplevel()
		top.rowconfigure (0, weight = 1)
		top.columnconfigure (0, weight = 1)
		self.rowconfigure (0, weight = 1)
		self.columnconfigure (0, weight = 1)

		self.yScroll = tk.Scrollbar (self, orient = tk.VERTICAL)  # This is the Scrollbar, which will be used for the game list.
		self.yScroll.grid (row = 0, column = 2, rowspan = 5, sticky = tk.N + tk.S)  # Setting "sticky" to two opposite directions (N and S in this case) stretches the widget across that axis.  Where not stretched, widgets conform in size to the amount of space they need.

		# First, we create variable objects.
		self.varGame = tk.StringVar()  # This is a String variable object.  Its default value is an empty string.
		self.varGroupName = tk.StringVar()  # Another String variable object, representing the name of the game group
		self.varGroupName.set (config.GroupList[config.defaultgroup])  # Which one is the default?
		self.varGroupIndex = tk.IntVar()  # This is an Integer variable object.  It will be used to represent the number of the game group throughout the application.
		# Second, we create the desired widget which is bound to a created variable object.
		self.optGroup = tk.OptionMenu (self, self.varGroupName, *config.GroupList, command = self.refreshlist)  # Here is our first widget, an OptionMenu, which will display the list of game groups when clicked.
		self.optGroup.config (font = config.font, bg = "#201114", fg = "white smoke", width = 16)  # Unlike the other widgets, the OptionMenu's style has to be set using the config method, not during instantiation.
		self.optGroup ["menu"].config (font = config.fontoptionmenu, bg = "#201114", fg = "white smoke")  # This is for the drop-down menu that appears when you click on the widget.
		self.optGroup.grid (row = 0, column = 3)  # One of three methods can be used to see the widget we just created.  I'm using the .grid method.

		self.varBasefilename = tk.StringVar()  # Used to fetch all the other relevant files with the same base filename as the ROM image of the selected game
		self.cboGame = tk.Listbox (self, font = config.font, bg = "#201114", fg = "white smoke", width = 46, yscrollcommand = self.yScroll.set, listvariable = self.varGame)  # After creating our variable object, we create the widget we want with all the parameters.
		self.cboGame.grid (row = 0, column = 1, rowspan = 5, sticky = tk.N + tk.S)
		self.yScroll ["command"] = self.cboGame.yview  # Bind the Listbox widget to the scrollbar we created.
		self.cboGame.bind ("<<ListboxSelect>>", self.getscreenshot)  # Action to take when a game is selected from the Listbox.  In this case, we call getscreenshot.

		self.imgScreenshot = tk.PhotoImage (file = config.defaultimage1)  # Next is the screenshot preview.  By default, it will display an image that contains text to select a game.
		self.lblScreenshot = tk.Label (self, image = self.imgScreenshot)  # To actually display the image, we have a Label widget set to show a picture instead of text.
		self.lblScreenshot.grid (row = 0, column = 0, rowspan = 2)

		# Notice these LabelFrame objects are widgets which can have subwidgets that conform to their own grids.
		self.frameGraphicsOptions = tk.LabelFrame (self, font = config.fontframeheader, labelanchor = "n", text = "Display Options", bg = "LightGoldenrod2")  # Setting labelanchor to N centers the label text across the top line of the frame.
		self.frameGraphicsOptions.grid (row = 2, column = 0, rowspan = 3)  # This frame will stretch across three rows so its height will be the combined height of the three frames to the right of it, once we generate them.

		self.frameCommands = tk.LabelFrame (self, font = config.fontframeheader, labelanchor = "n", text = "Commands", bg = "LightGoldenrod2")  # This frame will contain command buttons.
		self.frameCommands.grid (row = 1, column = 3)  # The height of the screenshot label will be the combined height of this frame and the OptionMenu above.

		self.framePeripheralOptions = tk.LabelFrame (self, font = config.fontframeheader, labelanchor = "n", text = "Peripheral Options", bg = "LightGoldenrod2")
		self.framePeripheralOptions.grid (row = 2, column = 3, sticky = tk.N + tk.E + tk.W)

		self.frameSoundOptions = tk.LabelFrame (self, font = config.fontframeheader, labelanchor = "n", text = "Audio Options", bg = "LightGoldenrod2")
		self.frameSoundOptions.grid (row = 3, column = 3, sticky = tk.E + tk.W)

		self.frameGeneralOptions = tk.LabelFrame (self, font = config.fontframeheader, labelanchor = "n", text = "Other Options", bg = "LightGoldenrod2")
		self.frameGeneralOptions.grid (row = 4, column = 3, sticky = tk.S + tk.E + tk.W)

		# Here are the first widgets inside one of the frames.  In this case, they're command buttons.
		self.cmdPlay = tk.Button (self.frameCommands, font = config.font, text = "Play", bg = "#201114", width = 10, disabledforeground = "black", fg = "white smoke", state = tk.DISABLED, command = self.launchjzintv)  # The Play button.  It's initialized to be disabled until the user selects a game.  Also note its parent (the first parameter) is the frameCommands widget.
		self.cmdPlay.grid (row = 0, column = 0)  # Because the Button has a different parent than "self", it has its own grid that it will snap in place to.

		self.cmdAbout = tk.Button (self.frameCommands, font = config.font, text = "About", bg = "#201114", width = 10, fg = "white smoke", command = self.about)  # The About button.
		self.cmdAbout.grid (row = 1, column = 0)

		self.cmdQuit = tk.Button (self.frameCommands, font = config.font, text = "Quit", bg = "#201114", width = 10, fg = "white smoke", command = self.cancel)  # The Quit button.
		self.cmdQuit.grid (row = 2, column = 0)

		# This block is for a pair of Checkbuttons whose parent is the framePeripheralOptions widget, so they will appear within that frame.
		self.varIntellivoice = tk.IntVar()  # Integer variables' default value is 0.
		self.chkIntellivoice = tk.Checkbutton (self.framePeripheralOptions, font = config.font, text = "IntelliVoice", bg = "LightGoldenrod2", variable = self.varIntellivoice, offvalue = 0, onvalue = 1)  # This widget has two values: one when checked (onvalue) and one when unchecked (offvalue).
		self.chkIntellivoice.grid (row = 0, sticky = tk.W)  # The "sticky" value is set to W for left-justification.  Otherwise the Checkbuttons and their associated label would all be center-justified within the frame.
		#self.chkIntellivoice.deselect()  # Deselecting the checkbutton here would immediately set the variable's value to that of the offvalue property.  Since the offvalue happens to be the default value of the bound Integer variable, I commented this line out.

		self.varECS = tk.IntVar()
		self.chkECS = tk.Checkbutton (self.framePeripheralOptions, font = config.font, text = "ECS", bg = "LightGoldenrod2", variable = self.varECS, offvalue = 0, onvalue = 1)
		self.chkECS.grid (row = 1, sticky = tk.W)
		#self.chkECS.deselect()

		# Here is our first group of Radiobuttons.  As you may know, radiobuttons are designed to appear in groups, exactly one of which within each group will be checked at all times.
		self.varDisplaySize = tk.IntVar()
		self.varDisplaySize.set (config.defaultwindowsize)  # We'll fetch the desired default value from our config file.
		# Next, we create widgets and bind them to a certain variable object as before.
		self.chkZ0 = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "320x200,8bpp", bg = "LightGoldenrod2", variable = self.varDisplaySize, value = 0)  # There is only one value this time, the value when checked, analagous to the checkbutton's onvalue.
		self.chkZ0.grid (row = 0, column = 0, columnspan = 2, sticky = tk.W)  # We have a columnspan of 2 because there will be two columns of widgets within this frame, as you will soon see.
		self.chkZ1 = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "640x480,8bpp", bg = "LightGoldenrod2", variable = self.varDisplaySize, value = 1)  # Binding the subsequent Radiobuttons to the same variable as the original one, and having a different value, is how we ensure only one will be checked at a time.
		self.chkZ1.grid (row = 1, column = 0, columnspan = 2, sticky = tk.W)
		self.chkZ2 = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "320x240,16bpp", bg = "LightGoldenrod2", variable = self.varDisplaySize, value = 2)
		self.chkZ2.grid (row = 2, column = 0, columnspan = 2, sticky = tk.W)
		self.chkZ3 = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "1024x768,8bpp", bg = "LightGoldenrod2", variable = self.varDisplaySize, value = 3)
		self.chkZ3.grid (row = 3, column = 0, columnspan = 2, sticky = tk.W)
		self.chkZ4 = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "1680x1050,8bpp", bg = "LightGoldenrod2", variable = self.varDisplaySize, value = 4)
		self.chkZ4.grid (row = 4, column = 0, columnspan = 2, sticky = tk.W)
		self.chkZ5 = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "800x400,16bpp", bg = "LightGoldenrod2", variable = self.varDisplaySize, value = 5)
		self.chkZ5.grid (row = 5, column = 0, columnspan = 2, sticky = tk.W)
		self.chkZ6 = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "1600x1200,32bpp", bg = "LightGoldenrod2", variable = self.varDisplaySize, value = 6)
		self.chkZ6.grid (row = 6, column = 0, columnspan = 2, sticky = tk.W)
		self.chkZ7 = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "3280x1200,32bpp", bg = "LightGoldenrod2", variable = self.varDisplaySize, value = 7)
		self.chkZ7.grid (row = 7, column = 0, columnspan = 2, sticky = tk.W)
		# Normally with a group of Radiobuttons all bound to a single variable, the default is the one whose value is 0 if an Integer variable, or an empty string if a String variable.
		# When the user clicks on a Radiobutton, the bound variable changes its value to that of the button clicked.
		# Then, all the Radiobuttons bound to that same variable will either become selected or unselected based on whether their value matches that of the bound variable.

		self.varBorderSize = tk.IntVar()
		self.varBorderSize.set (config.defaultbordersize)
		self.validation = self.register (self.onlydigits)  # This code fires the onlydigits function.
		self.lblBorderSize = tk.Label (self.frameGraphicsOptions, font = config.font, text = "Border Size: ", bg = "LightGoldenrod2")  # Notice the space at the end of the label text.  That will provide just the right amount of horizontal "padding" we need.
		self.lblBorderSize.grid (row = 8, column = 0, pady = 10, sticky = tk.E + tk.S)  # The label's horizontal "sticky" property is set to E, and the Entry widget's horizontal "sticky" property will be set to W, so they'll be next to each other.  The pady property provides visual distance from the Radiobuttons above.
		# Next is an Entry widget, where the user can type something into a textbox.
		# "validate='key'" means that validation happens whenever there's a keystroke while this widget has the focus.
		# After that is the validatecommand option, which binds the onlydigits function.
		# '%P' is the text being inserted to the Entry widget.  The validation needs that to see if it's numeric.
		self.txtBorderSize = tk.Entry (self.frameGraphicsOptions, font = config.font, textvariable = self.varBorderSize, validate = "key", validatecommand = (self.validation, "%P"), width = 2)
		self.txtBorderSize.grid (row = 8, column = 1, pady = 10, sticky = tk.W + tk.S)  # This is the first widget that appears in the second column within the "Graphics Options" frame.

		self.varFullscreen = tk.IntVar()
		self.varFullscreen.set (config.defaultfullscreen)
		self.chkWindowed = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "Windowed", bg = "LightGoldenrod2", variable = self.varFullscreen, value = 0)
		self.chkWindowed.grid (row = 9, column = 0, sticky = tk.W)
		self.chkFullscreen = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "Full Screen", bg = "LightGoldenrod2", variable = self.varFullscreen, value = 1)
		self.chkFullscreen.grid (row = 10, column = 0, sticky = tk.W)

		self.varMode = tk.StringVar()  # The default value of String variable objects is an empty string.
		self.varMode.set (config.defaultgraphicsmode)  # Again, we'll look to the config.py file to get the default we want.
		self.chkNTSC = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "NTSC", bg = "LightGoldenrod2", variable = self.varMode, value = " ")  # This Radiobutton's value ought to be an empty string ...
		self.chkNTSC.grid (row = 9, column = 1, sticky = tk.W)
		self.chkPAL = tk.Radiobutton (self.frameGraphicsOptions, font = config.font, text = "PAL", bg = "LightGoldenrod2", variable = self.varMode, value = "-P")  # ... but that would cause a cosmetic bug where this Radiobutton would display the wrong graphic when unchecked.
		self.chkPAL.grid (row = 10, column = 1, sticky = tk.W)

		self.varAudioRate = tk.IntVar()
		self.varAudioRate.set (config.defaultaudiorate)
		self.chkAudioNone = tk.Radiobutton (self.frameSoundOptions, font = config.font, text = "No sound", bg = "LightGoldenrod2", variable = self.varAudioRate, value = 0)  # Would be checked by default since its value is 0, but we have a "defaultaudiorate" in config.py.
		self.chkAudioNone.grid (row = 0, column = 0, sticky = tk.W)
		self.chkAudioLow = tk.Radiobutton (self.frameSoundOptions, font = config.font, text = "Better performance", bg = "LightGoldenrod2", variable = self.varAudioRate, value = 11025)
		self.chkAudioLow.grid (row = 1, column = 0, sticky = tk.W)
		self.chkAudioHigh = tk.Radiobutton (self.frameSoundOptions, font = config.font, text = "Better quality", bg = "LightGoldenrod2", variable = self.varAudioRate, value = 48000)
		self.chkAudioHigh.grid (row = 2, column = 0, sticky = tk.W)

		self.varGRAM = tk.IntVar()
		self.chkGRAM0 = tk.Radiobutton (self.frameGeneralOptions, font = config.font, text = "Normal GRAM", bg = "LightGoldenrod2", variable = self.varGRAM, value = 0)
		self.chkGRAM0.grid (row = 0, sticky = tk.W)
		self.chkGRAM1 = tk.Radiobutton (self.frameGeneralOptions, font = config.font, text = "Double GRAM", bg = "LightGoldenrod2", variable = self.varGRAM, value = 1, state = tk.DISABLED, command = lambda:self.gramwarning (None))  # The command property calls a procedure when this Radiobutton is checked.
		self.chkGRAM1.grid (row = 1, sticky = tk.W)
		self.chkGRAM2 = tk.Radiobutton (self.frameGeneralOptions, font = config.font, text = "Quadruple GRAM", bg = "LightGoldenrod2", variable = self.varGRAM, value = 2, state = tk.DISABLED, command = lambda:self.gramwarning (None))  # The procedure called will throw an exception unless a game is selected first, which is why these two radiobuttons are disabled by default, same as with the Play button.
		self.chkGRAM2.grid (row = 2, sticky = tk.W)
		#self.chkGRAM0.select()  # The first Radiobutton is the one we want selected by default.

		self.varPalette = tk.StringVar()
		self.varPalette.set (config.defaultpalette)
		self.chkPalette = tk.Checkbutton (self.frameGeneralOptions, font = config.font, text = "Custom palette", bg = "LightGoldenrod2", variable = self.varPalette, offvalue = "", onvalue = "--gfx-palette=" + config.workingpath + "intycolors.cfg")
		self.chkPalette.grid (row = 3, column = 0, pady = 10, sticky = tk.W + tk.S)

	# This code fires when the user selects a different game group from the group list.
	def refreshlist (self, event):
		self.cboGame.selection_clear (0, tk.END)  # Clear any existing game selection.
		self.cmdPlay.config (state=tk.DISABLED)  # "Grey-out" the Play button again.
		self.chkGRAM0.select()  # Set GRAM to default.
		self.chkGRAM1.config (state=tk.DISABLED)  # "Grey-out" the "extra GRAM" radiobuttons.
		self.chkGRAM2.config (state=tk.DISABLED)
		self.imgScreenshot.config (file=config.defaultimage1)  # Revert to the initial dummy screenshot image.
		for index, string in enumerate (config.GroupList):  # Find the group in the list.
			if (self.varGroupName.get() == string):  # Is this the group the user just selected?
				self.varGroupIndex.set (index)  # Capture the index since we will refer to it quite a few times.
				self.GameNames = []  # Clear the game list.
				for Game in config.GameList[index]:  # Iterate through the appropriate group in the GameList in config.py.
					self.GameNames.append(Game[0])  # Fetch the name of each game, the first element (index 0).
		self.varGame.set (self.GameNames)  # Bind the newly-built game list.

	# Validation for the Entry box.  We want only numeric characters.
	def onlydigits (self, inp):
		if inp == "":  # Check for an empty string first, which we will allow (there are no non-numeric characters).
			return True
		return inp.isdigit()  # isdigit is a Python function that checks the range of numeric characters.

	# This code fires when the user selects a game from the game list.
	def getscreenshot (self, event):
		self.cmdPlay.config (state=tk.NORMAL)  # The Play button can now be enabled since a game is selected.
		self.chkGRAM1.config (state=tk.NORMAL)  # Same goes for the "extra GRAM" radiobuttons.
		self.chkGRAM2.config (state=tk.NORMAL)
		try:
			self.varBasefilename.set (config.GameList[self.varGroupIndex.get()][self.cboGame.curselection()[0]][1])  # We're looking at the second element in the GameList ("[1]", since indexes start at 0) to get the ROM image filename.
			self.varBasefilename.set (self.varBasefilename.get()[: self.varBasefilename.get().rfind('.') - len(self.varBasefilename.get())])  # Strip the filename extension.  I'm using rfind in case there's another period within the filename.
			self.varECS.set (config.GameList[self.varGroupIndex.get()][self.cboGame.curselection()[0]][2])  # Do we want ECS, per the GameList third element?
			self.varIntellivoice.set (config.GameList[self.varGroupIndex.get()][self.cboGame.curselection()[0]][3])  # Do we want IntelliVoice, per the fourth element?
			self.varGRAM.set (config.GameList[self.varGroupIndex.get()][self.cboGame.curselection()[0]][4])  # Do we want expanded GRAM, per the fifth element?
		except:
			self.cmdPlay.config (state=tk.DISABLED)
			self.chkGRAM0.select()
			self.chkGRAM1.config (state=tk.DISABLED)
			self.chkGRAM2.config (state=tk.DISABLED)
			print ("Wake up!")  # There have been instances where the game selection gets cleared after a period of inactivity.  That's why I added an exception handler here.
			#tk.messagebox.showerror('Wake up!', 'Selection lost.')
		try:
			self.imgScreenshot.config(file=config.screenshotpath + self.varBasefilename.get() + ".gif")  # If the screenshot file exists for this game, change to that image.
		except:
			self.imgScreenshot.config(file=config.defaultimage2)  # If not, change to a default image with text that's a little friendlier than "file not found."  Yes, there has to be an exception handler wrapped around this.

	# This code fires when the user selects one of the additional GRAM Radiobuttons.
	def gramwarning (self, event):
		try:  # I created another exception handler here due to an bug I found on 2021 May 18.  There's no need to disable it though.
			if self.varGRAM.get() > config.GameList[self.varGroupIndex.get()][self.cboGame.curselection()[0]][4]:  # Does the user want more GRAM than the game supports, per the fifth element in the GameList?
				if not tk.messagebox.askyesno ("Caution about expanding GRAM", "Games that do not support additional GRAM may have graphical glitches\n\nAre you sure you want to do this?"):  # Pop up a warning message with yes/no buttons.
					self.chkGRAM0.select()  # Revert to default GRAM if the user selected No.
		except:  # The bug had to do with trying to change the GRAM settings with no game selected.  Proactively selecting the default GRAM and disabling the other radiobuttons is the ideal thing to do.
			tk.messagebox.showerror ("Error in expanding GRAM", "Select a game before tweaking the GRAM settings.")

	# This code fires when the uset clicks the Play button.
	def launchjzintv (self):
		# Write to the temporary BASH script:
		file.write("if [ -e \"" + config.boxpath + self.varBasefilename.get() + ".png\" ] ; then\n")  # Check for an existing box image.
		#file.write("\tfeh --bg-max \"" + config.boxpath + self.varBasefilename.get() + ".png\"\n")  # If found, draw it onto the root window.  That's the way it used to be before I switched to a "desktop-based" environment, which now takes control of the root window to have "wallpaper" in the background.
		file.write("\tfeh --no-fehbg --force-aliasing -x -F -Z \"" + config.boxpath + self.varBasefilename.get() + ".png\" &\n")  # The box image will appear on the right side of the screen if its dimensions are small.  There will be no window decorations above the box image.
		file.write("\tsleep 1\n")  # Need to add a one-second delay so the box image doesn't pop up on top of the overlay image.
		file.write("fi\n")  # Close the if code block.  "if" backwards is how it's done in BASH scripts.
		file.write ("if [ -e \"" + config.overlaypath + self.varBasefilename.get() + ".pdf\" ] ; then\n")  # Check for an existing instruction manual.
		file.write ("\txpdf -geometry -0+0 \"" + config.manualpath + self.varBasefilename.get() + ".pdf\" &\n")  # If found, draw it as a pop-up window on the top right corner of the screen.
		file.write ("\tsleep 1\n")  # Need to add a one-second delay here as well.
		file.write ("fi\n")
		file.write("if [ -e \"" + config.overlaypath + self.varBasefilename.get() + ".jpg\" ] ; then\n")  # Check for an existing overlay image.
		file.write("\tfeh --no-fehbg -x -g +0+0 \"" + config.overlaypath + self.varBasefilename.get() + ".jpg\" &\n")  # If found, draw it as a pop-up window on the top left corner of the screen.
		file.write("fi\n")
		# Now for the call to jzintv.
		file.writelines([config.jzintvpath + "jzintv",
			" \"" + config.rompath + config.GameList[self.varGroupIndex.get()][self.cboGame.curselection()[0]][1] + "\"",  # The ROM image file, encapsulated in quotes.
			" " + config.globaloptions,  # The global options will come first, so anything game-specific can override them.
			" " + self.varPalette.get(),  # Default or custom palette?  Note the .get method to fetch the value from the variable objects.
			" " + self.varMode.get(),  # NTSC or PAL?  It's okay if we end up with an extra space in the case of NTSC.
			" -s" + str(self.varECS.get()),  # ECS or no?  Starting here, we need to convert numeric values to strings.
			" -v" + str(self.varIntellivoice.get()),  # IntelliVoice or no?
			" -G" + str(self.varGRAM.get()),  # The usual amount of GRAM or more for future releases?
			" -f" + str(self.varFullscreen.get()),  # Fullscreen or no?
			" -b" + str(self.varBorderSize.get()),  # Border size
			" -z" + str(self.varDisplaySize.get()),  # Display size and bit depth
			" -a" + str(self.varAudioRate.get()),  # Audio sampling rate
			" " + config.GameList[self.varGroupIndex.get()][self.cboGame.curselection()[0]][5],  # Game-specific parameters, the sixth element in the GameList.
			"\n"])  # No '&' token here because we want the script to wait until jzIntv is closed.
		file.write("if [ -e \"" + config.overlaypath + self.varBasefilename.get() + ".jpg\" ] ; then\n")  # After playing, if there was an overlay image, ...
		file.write("\tpkill feh\n")  # Then get rid of the window.
		file.write("fi\n")
		file.write ("if [ -e \"" + config.manualpath + self.varBasefilename.get() + ".pdf\" ] ; then\n")  # After playing, if there was an instruction manual, ...
		file.write ("\tpkill xpdf\n")  # Then get rid of the PDF window.
		file.write ("fi\n")
		file.write("if [ -e \"" + config.boxpath + self.varBasefilename.get() + ".png\" ] ; then\n")  # If there was a box image, ...
		#file.write("\tfeh --bg-max -z *.jpg \n")  # Then replace the "wallpaper" with something we were using before.
		file.write("\tpkill feh\n")  # Then get rid of that window as well.
		file.write("fi\n")
		file.write("play &\n")  # Re-launch this application.
		file.close()
		self.quit()  # Because the last line of the temporary BASH script re-runs the original script to launch this application, we'll close this for now to start the temp script's execution.

	# This code fires when the user clicks the About button.
	def about (self):
		tk.messagebox.showinfo ("About PIDEjL", "PIDEjL - Portable Intellivision Development Environment jzIntv Launcher\n\nWritten by Michael Hayes\n\nDate Of Last Modification:\nMarch 24, 2023")

	# This code fires when the user clicks the Quit button.
	def cancel (self):
		file.close()  # When the program is first run, it opens the temporary script file and writes the "hashbang".  That is all the file contains at this point, so nothing else will be executed, ...
		self.quit()  # ... including re-launching this application, as with the Play button.

app = Application()  # Instantiate the Application.
app.master.title ("Portable Intellivision Development Environment jzintv Launcher")
app.master.geometry ("+0+0")  # Put the front-end window in the top left corner.
app.master.iconphoto (True, tk.PhotoImage (file = config.workingpath + "blueeye.png"))
app.configure (bg="LightGoldenrod2")  # Color the portions of the window not covered by widgets.
file = open (config.workingpath + "temp.sh", "w")  # Open the temporary script file we will be using, write-only, replacing existing contents.
file.write (config.hashbang + "\n")  # Write the hashbang to the temp script.  If the user clicks on the "Quit" button, nothing will happen after this program closes.
app.mainloop()  # Listen for events.  Let the fun begin!
# EOF
