## BugOptionsTab
##
## Base class for all tabs in the BUG Options Screen.
##
## Copyright (c) 2007 The BUG Mod.
##
## Author: EmperorFool

import BugOptions
import BugUtil

## Constants

CHECKBOX_INDENT = 2

## Globals

g_options = BugOptions.getOptions()

## Class

class BugOptionsTab:
	"""
	Provides an API for building a single tab on the BUG Options Screen by placing UI controls.
	"""
	
	def __init__(self, name, title):
		self.name = name
		self.tab = self.name + "Tab"
		
		self.title = title
		self.translated = False
		
		# EF: Has to be this module. I tried splitting it out into a new module without success.
		self.callbackIFace = "CvOptionsScreenCallbackInterface"

	def getName (self):
		return self.name

	def getTitle (self):
		if (not self.translated):
			self.translate()
		return self.title
	
	def translate (self):
		xmlKey = "TXT_KEY_BUG_OPTTAB_" + self.name.upper()
		self.title = BugUtil.getPlainText(xmlKey, self.title)
		self.translated = True
	
	def clearTranslation(self):
		"Marks this tab so that it will be translated again the next time it is accessed"
		self.translated = False


	def setOptions (self, options):
		self.options = options

	def getOption (self, name):
		try:
			return g_options.getOption(name)
		except BugUtil.ConfigError:
			return None


	def create (self, screen):
		"Creates the full options screen"
		pass

	def createTab (self, screen):
		"Creates and returns the options tab"
		screen.attachTabItem(self.tab, self.getTitle())
		
		return self.tab

	def createMainPanel (self, screen):
		"Creates and returns the options tab panel with Exit and Help buttons"
		# VBox with two blocks: scrolling control panel and Exit button with separator
		vbox = self.name + "VBox"
		screen.attachVBox(self.tab, vbox)		
		
		# scrollpane
		scrollpane = self.name + "Scroll"
		screen.attachScrollPanel(vbox, scrollpane)
		screen.setLayoutFlag(scrollpane, "LAYOUT_SIZE_HEXPANDING")
		screen.setLayoutFlag(scrollpane, "LAYOUT_SIZE_VEXPANDING")
		
		# panel for option controls
		panel = self.name + "Panel"
		screen.attachPanel(scrollpane, panel)
		screen.setStyle(panel, "Panel_Tan15_Style")
		screen.setLayoutFlag(panel, "LAYOUT_SIZE_HPREFERREDEXPANDING")
		screen.setLayoutFlag(panel, "LAYOUT_SIZE_VPREFERREDEXPANDING")
		
		# panel for Help and Exit buttons
		screen.attachHSeparator(vbox, "RM_ExitSeparator")
		exitPanel = self.name + "ExitBox"
		screen.attachHBox(vbox, exitPanel)
		screen.setLayoutFlag(exitPanel, "LAYOUT_HCENTER")
		
		# Help button
		title = BugUtil.getPlainText("TXT_KEY_BUG_OPTBUTTON_HELP", "Help")
		hover = BugUtil.getPlainText("TXT_KEY_BUG_OPTBUTTON_HELP_HOVER", "Opens the help file. You can hit Shift-F1 from the main interface.")
		helpButton = self.name + "Help"
		self.addButton(screen, exitPanel, helpButton, "handleBugHelpButtonInput", title, hover)
		
		self.addSpacer(screen, exitPanel, exitPanel)
		
		# Exit button
		title = BugUtil.getPlainText("TXT_KEY_PEDIA_SCREEN_EXIT", "Exit")
		hover = BugUtil.getPlainText("TXT_KEY_BUG_OPTBUTTON_EXIT_HOVER", "Exits the BUG Options screen.")
		exitButton = self.name + "Exit"
		self.addButton(screen, exitPanel, exitButton, "handleBugExitButtonInput", title, hover)
		
		return panel

	def addOneColumnLayout (self, screen, parent, panel=None):
		"Creates an HBox containing a single VBox for a list of controls"
		if (panel is None):
			panel = parent
		hbox = panel + "HBox"
		screen.attachHBox(parent, hbox)
		screen.setLayoutFlag(hbox, "LAYOUT_SIZE_HPREFERREDEXPANDING")
		screen.setLayoutFlag(hbox, "LAYOUT_SIZE_VMIN")
		
		column = panel + "VBox"
		screen.attachVBox(hbox, column)
		screen.setLayoutFlag(column, "LAYOUT_SIZE_HMIN")
		screen.setLayoutFlag(column, "LAYOUT_SIZE_VMIN")
		
		return column

	def addTwoColumnLayout (self, screen, parent, panel=None, separator=False):
		"Creates an HBox containing two VBoxes for two lists of controls"
		if (panel is None):
			panel = parent
		hbox = panel + "HBox"
		screen.attachHBox(parent, hbox)
		screen.setLayoutFlag(hbox, "LAYOUT_SIZE_HPREFERREDEXPANDING")
		screen.setLayoutFlag(hbox, "LAYOUT_SIZE_VMIN")
		
		leftColumn = panel + "Left"
		screen.attachVBox(hbox, leftColumn)
		screen.setLayoutFlag(leftColumn, "LAYOUT_SIZE_HMIN")
		screen.setLayoutFlag(leftColumn, "LAYOUT_SIZE_VMIN")
		
		if (separator):
			sep = panel + "Sep"
			screen.attachVSeparator(hbox, sep)
			screen.setLayoutFlag(sep, "LAYOUT_LEFT")
		
		rightColumn = panel + "Right"
		screen.attachVBox(hbox, rightColumn)
		screen.setLayoutFlag(rightColumn, "LAYOUT_SIZE_HMIN")
		screen.setLayoutFlag(rightColumn, "LAYOUT_SIZE_VMIN")
		
		return leftColumn, rightColumn

	def addThreeColumnLayout (self, screen, parent, panel=None, separator=False):
		"Creates an HBox containing three VBoxes for lists of controls"
		return self.addMultiColumnLayout(screen, parent, 3, panel, separator)

	def addMultiColumnLayout (self, screen, parent, count=2, panel=None, separator=False):
		"Creates an HBox containing multiple VBoxes for lists of controls"
		if (count <= 2):
			return self.addTwoColumnLayout(screen, parent, panel, separator)
		
		if (panel is None):
			panel = parent
		hbox = panel + "HBox"
		screen.attachHBox(parent, hbox)
		screen.setLayoutFlag(hbox, "LAYOUT_SIZE_HPREFERREDEXPANDING")
		screen.setLayoutFlag(hbox, "LAYOUT_SIZE_VMIN")
		
		columns = []
		first = True
		for i in range(count):
			if (separator and not first):
				sep = panel + "Sep%d" % i
				screen.attachVSeparator(hbox, sep)
				#screen.setLayoutFlag(sep, "LAYOUT_LEFT")
			first = False
			
			column = panel + "Col%d" % i
			screen.attachVBox(hbox, column)
			screen.setLayoutFlag(column, "LAYOUT_SIZE_HMIN")
			screen.setLayoutFlag(column, "LAYOUT_SIZE_VMIN")
			columns.append(column)
		
		return columns


	def addLabel (self, screen, panel, name, title=None, tooltip=None, spacer=False):
		key = "TXT_KEY_BUG_OPTLABEL_" + name.upper()
		title = BugUtil.getPlainText(key, title)
		#tooltip = BugUtil.getPlainText(key + "_HOVER", tooltip)
		if spacer:
			hbox = name + "HBox"
			screen.attachHBox(panel, hbox)
			#screen.setLayoutFlag(box, "LAYOUT_SIZE_HPREFERREDEXPANDING")
			self.addSpacer(screen, hbox, hbox, CHECKBOX_INDENT)
			panel = hbox
		if (title):
			label = name + "_Label"
			screen.attachLabel(panel, label, title)
			screen.setControlFlag(label, "CF_LABEL_DEFAULTSIZE")
			#if (tooltip):
			#	screen.setToolTip(label, tooltip)
			return label
		return None

	def addSpacer (self, screen, panel, name, size=1):
		spacer = name + "_Spacer"
		screen.attachLabel(panel, spacer, " " * size)
		screen.setControlFlag(spacer, "CF_LABEL_DEFAULTSIZE")
	
	def addButton (self, screen, panel, name, callback, title=None, tooltip=None):
		key = "TXT_KEY_BUG_OPTBUTTON_" + name.upper()
		title = BugUtil.getPlainText(key, title)
		tooltip = BugUtil.getPlainText(key + "_HOVER", tooltip)
		if (title):
			button = name + "_Button"
			screen.attachButton(panel, button, title, self.callbackIFace, callback, button)
			if (tooltip):
				screen.setToolTip(button, tooltip)
			return button
		return None

	def addCheckbox (self, screen, panel, name, spacer=False):
		option = self.getOption(name)
		if (option is not None):
			control = name + "Check"
			value = option.getRealValue()
			if spacer:
				hbox = name + "HBox"
				screen.attachHBox(panel, hbox)
				#screen.setLayoutFlag(box, "LAYOUT_SIZE_HPREFERREDEXPANDING")
				self.addSpacer(screen, hbox, hbox, CHECKBOX_INDENT)
				panel = hbox
			screen.attachCheckBox(panel, control, option.getTitle(), self.callbackIFace, "handleBugCheckboxClicked", name, value)
			screen.setToolTip(control, option.getTooltip())
			if not option.isEnabled():
				screen.setEnabled(control, False)
			return control
		else:
			self.addMissingOption(screen, panel, name)

	def addTextEdit (self, screen, labelPanel, controlPanel, name):
		option = self.getOption(name)
		if (option is not None):
			# create label
			if (labelPanel == controlPanel):
				box = name + "HBox"
				screen.attachHBox(labelPanel, box)
				screen.setLayoutFlag(box, "LAYOUT_SIZE_HPREFERREDEXPANDING")
				labelPanel = box
				controlPanel = box
			if (labelPanel is not None):
				label = name + "Label"
				screen.attachLabel(labelPanel, label, option.getTitle())
				screen.setControlFlag(label, "CF_LABEL_DEFAULTSIZE")
			
			# create textedit
			control = name + "Edit"
			value = str(option.getValue())
			screen.attachEdit(controlPanel, control, value, self.callbackIFace, "handleBugTextEditChange", name)
			screen.setToolTip(control, option.getTooltip())
			screen.setLayoutFlag(control, "LAYOUT_SIZE_HPREFERREDEXPANDING")
			if not option.isEnabled():
				screen.setEnabled(control, False)
			return control
		else:
			self.addMissingOption(screen, labelPanel, name)


	def addDropdown (self, screen, labelPanel, controlPanel, name, spacer, layout, elements, index, callback):
		option = self.getOption(name)
		if (option is not None):
			# create label
			if (labelPanel is not None):
				if (labelPanel == controlPanel or spacer):
					box = name + "HBox"
					screen.attachHBox(labelPanel, box)
					#screen.setLayoutFlag(box, "LAYOUT_SIZE_HPREFERREDEXPANDING")
					if (spacer):
						screen.attachSpacer(box)
					if (labelPanel == controlPanel):
						controlPanel = box
					labelPanel = box
				label = name + "Label"
				screen.attachLabel(labelPanel, label, option.getTitle())
				screen.setControlFlag(label, "CF_LABEL_DEFAULTSIZE")
				
			# create dropdown
			control = name + "Dropdown"
			screen.attachDropDown(controlPanel, control, "", elements, self.callbackIFace, callback, name, index)
			screen.setToolTip(control, option.getTooltip())
			screen.setLayoutFlag(control, "LAYOUT_" + layout.upper())
			if not option.isEnabled():
				screen.setEnabled(control, False)
			return control
		else:
			self.addMissingOption(screen, controlPanel, name)

	def addTextDropdown (self, screen, labelPanel, controlPanel, name, spacer=False, layout="left"):
		option = self.getOption(name)
		if (option is not None):
			index = option.getIndex()
			elements = tuple(option.getDisplayValues())
			return self.addDropdown(screen, labelPanel, controlPanel, name, spacer, layout, elements, index, "handleBugDropdownChange")
		else:
			self.addMissingOption(screen, controlPanel, name)

	def addIntDropdown (self, screen, labelPanel, controlPanel, name, spacer=False, layout="right"):
		option = self.getOption(name)
		if (option is not None):
			index = option.getIndex()
			elements = tuple(option.getDisplayValues())
			return self.addDropdown(screen, labelPanel, controlPanel, name, spacer, layout, elements, index, "handleBugIntDropdownChange")
		else:
			self.addMissingOption(screen, controlPanel, name)

	def addFloatDropdown (self, screen, labelPanel, controlPanel, name, spacer=False, layout="right"):
		option = self.getOption(name)
		if (option is not None):
			index = option.getIndex()
			elements = tuple(option.getDisplayValues())
			return self.addDropdown(screen, labelPanel, controlPanel, name, spacer, layout, elements, index, "handleBugFloatDropdownChange")
		else:
			self.addMissingOption(screen, controlPanel, name)

	def addColorDropdown (self, screen, labelPanel, controlPanel, name, spacer=False, layout="left"):
		option = self.getOption(name)
		if (option is not None):
			index = option.getIndex()
			elements = tuple(option.getDisplayValues())
			return self.addDropdown(screen, labelPanel, controlPanel, name, spacer, layout, elements, index, "handleBugColorDropdownChange")
		else:
			self.addMissingOption(screen, controlPanel, name)
	

	def addCheckboxDropdown (self, screen, checkPanel, dropPanel, checkName, dropName, layout, elements, index, callback, spacer=False):
		"Adds a dropdown with a checkbox for a label."
		checkOption = self.getOption(checkName)
		dropOption = self.getOption(dropName)
		if (checkOption is not None and dropOption is not None):
			# create checkbox
			if (checkPanel == dropPanel):
				box = checkPanel + "HBox"
				screen.attachHBox(checkPanel, box)
				#screen.setLayoutFlag(box, "LAYOUT_SIZE_HPREFERREDEXPANDING")
				checkPanel = box
				dropPanel = box
			checkControl = self.addCheckbox(screen, checkPanel, checkName, spacer)
			
			# create dropdown
			dropControl = dropName + "Dropdown"
			screen.attachDropDown(dropPanel, dropControl, "", elements, self.callbackIFace, callback, dropName, index)
			screen.setToolTip(dropControl, dropOption.getTooltip())
			screen.setLayoutFlag(dropControl, "LAYOUT_" + layout.upper())
			if not dropOption.isEnabled():
				screen.setEnabled(dropControl, False)
			return checkControl, dropControl
		else:
			if (checkOption is None):
				self.addMissingOption(screen, checkPanel, checkOption)
			if (dropOption is None):
				self.addMissingOption(screen, dropPanel, dropOption)

	def addCheckboxTextDropdown (self, screen, checkPanel, dropPanel, checkName, dropName, layout="left", spacer=False):
		checkOption = self.getOption(checkName)
		dropOption = self.getOption(dropName)
		if (checkOption is not None and dropOption is not None):
			index = dropOption.getIndex()
			elements = tuple(dropOption.getDisplayValues())
			checkControl, dropControl = self.addCheckboxDropdown(screen, checkPanel, dropPanel, checkName, dropName, layout, elements, index, "handleBugDropdownChange", spacer)
			return checkControl, dropControl
		else:
			if (checkOption is None):
				self.addMissingOption(screen, checkPanel, checkOption)
			if (dropOption is None):
				self.addMissingOption(screen, dropPanel, dropOption)

	def addCheckboxIntDropdown (self, screen, checkPanel, dropPanel, checkName, dropName, layout="right", spacer=False):
		checkOption = self.getOption(checkName)
		dropOption = self.getOption(dropName)
		if (checkOption is not None and dropOption is not None):
			index = dropOption.getIndex()
			elements = tuple(dropOption.getDisplayValues())
			checkControl, dropControl = self.addCheckboxDropdown(screen, checkPanel, dropPanel, checkName, dropName, layout, elements, index, "handleBugIntDropdownChange", spacer)
			return checkControl, dropControl
		else:
			if (checkOption is None):
				self.addMissingOption(screen, checkPanel, checkOption)
			if (dropOption is None):
				self.addMissingOption(screen, dropPanel, dropOption)

	def addCheckboxFloatDropdown (self, screen, checkPanel, dropPanel, checkName, dropName, layout="right", spacer=False):
		checkOption = self.getOption(checkName)
		dropOption = self.getOption(dropName)
		if (checkOption is not None and dropOption is not None):
			index = dropOption.getIndex()
			elements = tuple(dropOption.getDisplayValues())
			checkControl, dropControl = self.addCheckboxDropdown(screen, checkPanel, dropPanel, checkName, dropName, layout, elements, index, "handleBugFloatDropdownChange", spacer)
			return checkControl, dropControl
		else:
			if (checkOption is None):
				self.addMissingOption(screen, checkPanel, checkOption)
			if (dropOption is None):
				self.addMissingOption(screen, dropPanel, dropOption)
	

	def addSlider (self, screen, labelPanel, controlPanel, name, spacer=False, vertical=False, expanding=True, fill=None, min=0, max=100):
		option = self.getOption(name)
		if (option is not None):
			# create label
			if (labelPanel is not None):
				if (labelPanel == controlPanel or spacer):
					box = name + "HBox"
					screen.attachHBox(labelPanel, box)
					#screen.setLayoutFlag(box, "LAYOUT_SIZE_HPREFERREDEXPANDING")
					if (spacer):
						screen.attachSpacer(box)
					if (labelPanel == controlPanel):
						controlPanel = box
					labelPanel = box
				label = name + "Label"
				screen.attachLabel(labelPanel, label, option.getTitle())
				screen.setControlFlag(label, "CF_LABEL_DEFAULTSIZE")
				
			# create slider
			control = name + "Slider"
			value = option.getRealValue()
			if vertical:
				screen.attachVSlider(controlPanel, control, self.callbackIFace, "handleBugSliderChanged", name, min, max, value)
				if expanding:
					screen.setLayoutFlag(control, "LAYOUT_SIZE_VEXPANDING")
			else:
				screen.attachHSlider(controlPanel, control, self.callbackIFace, "handleBugSliderChanged", name, min, max, value)
				if expanding:
					screen.setLayoutFlag(control, "LAYOUT_SIZE_HEXPANDING")
			if fill:
				screen.setControlFlag(control, "CF_SLIDER_FILL_" + fill.upper())
			screen.setToolTip(control, option.getTooltip())
			if not option.isEnabled():
				screen.setEnabled(control, False)
			return control
		else:
			self.addMissingOption(screen, controlPanel, name)


	def addMissingOption (self, screen, panel, name):
		screen.attachLabel(panel, name + "Missing", "Missing: " + name)
