changeset 538:00aa20dc8b7f

Made the Setting class much more customizable by adding the SettingEntry class. Adopted demos to the changes Note: Setting ScreenWidth and ScreenHeight are now combined into ScreenResolution of format <width>x<height> FullScreen and PlaySounds are now of type bool
author nihathrael@33b003aa-7bff-0310-803a-e67f0ece8222
date Tue, 01 Jun 2010 18:14:26 +0000
parents 764510a6d2f9
children 4c7b5eee211c
files demos/pychan_demo/settings-dist.xml demos/rio_de_hola/settings-dist.xml demos/rpg/settings-dist.xml demos/shooter/settings-dist.xml engine/python/fife/extensions/basicapplication.py engine/python/fife/extensions/fife_settings.py
diffstat 6 files changed, 208 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/demos/pychan_demo/settings-dist.xml	Mon May 31 21:37:10 2010 +0000
+++ b/demos/pychan_demo/settings-dist.xml	Tue Jun 01 18:14:26 2010 +0000
@@ -1,11 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <Settings>
 	<Module name="FIFE">
-		<Setting name="FullScreen" type="int"> 0 </Setting>
-		<Setting name="PlaySounds" type="int"> 1 </Setting>
-		<Setting name="RenderBackend" type="str"> OpenGL </Setting>
-		<Setting name="ScreenWidth" type="int"> 1024 </Setting>
-		<Setting name="ScreenHeight" type="int"> 768 </Setting>
+		<Setting name="FullScreen" type="bool"> False </Setting>
+		<Setting name="PlaySounds" type="bool"> True </Setting>
+		<Setting name="RenderBackend" type="str"> OpenGL </Setting>
+		<Setting name="ScreenResolution" type="str">1024x768</Setting>
 		<Setting name="BitsPerPixel" type="int"> 0 </Setting>
 		<Setting name="InitialVolume" type="float"> 5.0 </Setting>
 		<Setting name="SDLRemoveFakeAlpha" type="int"> 1 </Setting>
--- a/demos/rio_de_hola/settings-dist.xml	Mon May 31 21:37:10 2010 +0000
+++ b/demos/rio_de_hola/settings-dist.xml	Tue Jun 01 18:14:26 2010 +0000
@@ -1,11 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <Settings>
 	<Module name="FIFE">
-		<Setting name="FullScreen" type="int"> 0 </Setting>
-		<Setting name="PlaySounds" type="int"> 1 </Setting>
+		<Setting name="FullScreen" type="bool"> False </Setting>
+		<Setting name="PlaySounds" type="bool"> True </Setting>
 		<Setting name="RenderBackend" type="str"> OpenGL </Setting>
-		<Setting name="ScreenWidth" type="int"> 1024 </Setting>
-		<Setting name="ScreenHeight" type="int"> 768 </Setting>
+		<Setting name="ScreenResolution" type="str">1024x768</Setting>
 		<Setting name="BitsPerPixel" type="int"> 0 </Setting>
 		<Setting name="InitialVolume" type="float"> 5.0 </Setting>
 		<Setting name="SDLRemoveFakeAlpha" type="int"> 1 </Setting>
--- a/demos/rpg/settings-dist.xml	Mon May 31 21:37:10 2010 +0000
+++ b/demos/rpg/settings-dist.xml	Tue Jun 01 18:14:26 2010 +0000
@@ -1,11 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <Settings>
 	<Module name="FIFE">
-		<Setting name="FullScreen" type="int"> 0 </Setting>
-		<Setting name="PlaySounds" type="int"> 1 </Setting>
+		<Setting name="FullScreen" type="bool"> False </Setting>
+		<Setting name="PlaySounds" type="bool"> True </Setting>
 		<Setting name="RenderBackend" type="str"> OpenGL </Setting>
-		<Setting name="ScreenWidth" type="int"> 1024 </Setting>
-		<Setting name="ScreenHeight" type="int"> 768 </Setting>
+		<Setting name="ScreenResolution" type="str">1024x768</Setting>
 		<Setting name="BitsPerPixel" type="int"> 0 </Setting>
 		<Setting name="InitialVolume" type="float"> 5.0 </Setting>
 		<Setting name="SDLRemoveFakeAlpha" type="int"> 1 </Setting>
@@ -32,7 +31,7 @@
 		<Setting name="ActorLayer" type="str"> actor_layer </Setting>
 		<Setting name="ItemLayer" type="str"> item_layer </Setting>
 		<Setting name="HelpText" type="str"> misc/help.txt </Setting>
-		
+
 		<Setting name="DefaultActorWalkSpeed" type="float"> 2.5 </Setting>
 	</Module>
 </Settings>
--- a/demos/shooter/settings-dist.xml	Mon May 31 21:37:10 2010 +0000
+++ b/demos/shooter/settings-dist.xml	Tue Jun 01 18:14:26 2010 +0000
@@ -1,11 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <Settings>
 	<Module name="FIFE">
-		<Setting name="FullScreen" type="int"> 0 </Setting>
-		<Setting name="PlaySounds" type="int"> 1 </Setting>
+		<Setting name="FullScreen" type="bool"> False </Setting>
+		<Setting name="PlaySounds" type="bool"> True </Setting>
 		<Setting name="RenderBackend" type="str"> OpenGL </Setting>
-		<Setting name="ScreenWidth" type="int"> 1024 </Setting>
-		<Setting name="ScreenHeight" type="int"> 768 </Setting>
+		<Setting name="ScreenResolution" type="str">1024x768</Setting>
 		<Setting name="BitsPerPixel" type="int"> 0 </Setting>
 		<Setting name="InitialVolume" type="float"> 5.0 </Setting>
 		<Setting name="SDLRemoveFakeAlpha" type="int"> 1 </Setting>
--- a/engine/python/fife/extensions/basicapplication.py	Mon May 31 21:37:10 2010 +0000
+++ b/engine/python/fife/extensions/basicapplication.py	Tue Jun 01 18:14:26 2010 +0000
@@ -74,7 +74,7 @@
 			self._setting = setting
 		else:
 			self._setting =  Setting(app_name="", settings_file="./settings.xml", settings_gui_xml="")
-	
+
 		self.engine = fife.Engine()
 
 		self.loadSettings()
@@ -103,27 +103,28 @@
 		engineSetting.setBitsPerPixel(self._setting.get("FIFE", "BitsPerPixel", 0))
 		engineSetting.setInitialVolume(self._setting.get("FIFE", "InitialVolume", 5.0))
 		engineSetting.setSDLRemoveFakeAlpha(self._setting.get("FIFE", "SDLRemoveFakeAlpha", 1))
-		engineSetting.setScreenWidth(self._setting.get("FIFE", "ScreenWidth", 1024))
-		engineSetting.setScreenHeight(self._setting.get("FIFE", "ScreenHeight", 768))
+		(width, height) = self._setting.get("FIFE", "ScreenResolution", "1024x768").split('x')
+		engineSetting.setScreenWidth(int(width))
+		engineSetting.setScreenHeight(int(height))
 		engineSetting.setRenderBackend(self._setting.get("FIFE", "RenderBackend", "OpenGL"))
-		engineSetting.setFullScreen(self._setting.get("FIFE", "FullScreen", 0))
+		engineSetting.setFullScreen(self._setting.get("FIFE", "FullScreen", False))
 
 		try:
 			engineSetting.setColorKeyEnabled(self._setting.get("FIFE", "ColorKeyEnabled", False))
 		except:
 			pass
-			
+
 		try:
 			key = self._setting.get("FIFE", "ColorKey", "255,0,255").split(',')
 			engineSetting.setColorKey(int(key[0]), int(key[1]), int(key[2]))
 		except:
 			pass
-			
+
 		try:
 			engineSetting.setWindowTitle(self._setting.get("FIFE", "WindowTitle", "No window title set"))
 			engineSetting.setWindowIcon(self._setting.get("FIFE", "WindowIcon", ""))
 		except:
-			pass			
+			pass
 
 		try:
 			engineSetting.setImageChunkingSize(self._setting.get("FIFE", "ImageChunkSize", 256))
@@ -134,20 +135,20 @@
 		"""
 		Initialize the LogManager.
 		"""
-		
+
 		engineSetting = self.engine.getSettings()
 		logmodules = self._setting.get("FIFE", "LogModules", ["controller"])
 
 		#log to both the console and log file
-		self._log = fifelog.LogManager(self.engine, 
-									   self._setting.get("FIFE", "LogToPrompt", "0"), 
+		self._log = fifelog.LogManager(self.engine,
+									   self._setting.get("FIFE", "LogToPrompt", "0"),
 									   self._setting.get("FIFE", "LogToFile", "0"))
 
 		self._log.setLevelFilter(self._setting.get("FIFE", "LogLevelFilter", fife.LogManager.LEVEL_DEBUG))
-		
+
 		if logmodules:
-			self._log.setVisibleModules(*logmodules)		
-		
+			self._log.setVisibleModules(*logmodules)
+
 	def createListener(self):
 		"""
 		This creates a default event listener, which will just close the program
--- a/engine/python/fife/extensions/fife_settings.py	Mon May 31 21:37:10 2010 +0000
+++ b/engine/python/fife/extensions/fife_settings.py	Tue Jun 01 18:14:26 2010 +0000
@@ -88,6 +88,8 @@
 </Settings>
 """
 
+DEFAULT_MODULE = "FIFE"
+
 class Setting(object):
 	"""
 	This class manages loading and saving of game settings.
@@ -147,12 +149,59 @@
 
 		#default settings
 		self._resolutions = ['640x480', '800x600', '1024x768', '1280x800', '1440x900']
+		self._renderbackends = ['OpenGL', 'SDL']
 
 		#Used to stylize the options gui
 		self._gui_style = "default"
 
 		self.loadSettings()
 
+		# Holds SettingEntries
+		self._entries = []
+
+		self._initDefaultSettingEntries()
+
+	def _initDefaultSettingEntries(self):
+		"""Initializes the default fife setting entries. Not to be called from
+		outside this class."""
+		self.createAndAddEntry(DEFAULT_MODULE, "PlaySounds", "enable_sound",
+		              requiresrestart=True)
+		self.createAndAddEntry(DEFAULT_MODULE, "FullScreen", "enable_fullscreen",
+		              requiresrestart=True)
+		self.createAndAddEntry(DEFAULT_MODULE, "ScreenResolution", "screen_resolution", initialdata = self._resolutions,
+		              requiresrestart=True)
+		self.createAndAddEntry(DEFAULT_MODULE, "RenderBackend", "render_backend", initialdata = self._renderbackends,
+		              requiresrestart=True)
+
+	def createAndAddEntry(self, module, name, widgetname, applyfunction=None, initialdata=None, requiresrestart=False):
+		""""
+		@param module: The Setting module this Entry belongs to
+		@type module: C{String}
+		@param name: The Setting's name
+		@type name: C{String}
+		@param widgetname: The name of the widget that is used to change this
+		setting
+		@type widgetname: C{String}
+		@param applyfunction: function that makes the changes when the Setting is
+		saved
+		@type applyfunction: C{function}
+		@param initialdata: If the widget supports the setInitialData() function
+		this can be used to set the initial data
+		@type initialdata: C{String} or C{Boolean}
+		@param requiresrestart: Whether or not the changing of this setting
+		requires a restart
+		@type requiresrestart: C{Boolean}
+		"""
+		entry = SettingEntry(module, name, widgetname, applyfunction, initialdata, requiresrestart)
+		self._entries.append(entry)
+
+	def addEntry(self, entry):
+		"""Adds a new C{SettingEntry} to the Settting
+		@param entry: A new SettingEntry that is to be added
+		@type entry: C{SettingEntry}
+		"""
+		self._entries.append(entry)
+
 	def loadSettings(self):
 		self._tree = ET.parse(os.path.join(self._appdata, self._settings_file))
 		self._root_element = self._tree.getroot()
@@ -376,16 +425,7 @@
 		else:
 			self.OptionsDlg = pychan.loadXML(StringIO(self._settings_gui_xml))
 		self.OptionsDlg.stylize(self._gui_style)
-		self.OptionsDlg.distributeInitialData({
-			'screen_resolution' : self._resolutions,
-			'render_backend' : ['OpenGL', 'SDL']
-		})
-		self.OptionsDlg.distributeData({
-			'screen_resolution' : self._resolutions.index(str(self.get("FIFE", "ScreenWidth")) + 'x' + str(self.get("FIFE", "ScreenHeight"))),
-			'render_backend' : 0 if self.get("FIFE", "RenderBackend") == "OpenGL" else 1,
-			'enable_fullscreen' : self.get("FIFE", "FullScreen"),
-			'enable_sound' : self.get("FIFE", "PlaySounds")
-		})
+		self.fillWidgets()
 		self.OptionsDlg.mapEvents({
 			'okButton' : self.applySettings,
 			'cancelButton' : self.OptionsDlg.hide,
@@ -393,34 +433,52 @@
 		})
 		self.OptionsDlg.show()
 
+	def fillWidgets(self):
+		for entry in self._entries:
+			widget = self.OptionsDlg.findChildByName(entry.settingwidgetname)
+			value = self.get(entry.module, entry.name)
+			if type(entry.initialdata) is list:
+				try:
+					value = entry.initialdata.index(value)
+				except ValueError:
+					raise ValueError(value + " is not a valid value for " + entry.name)
+			entry.initializeWidget(widget, value)
+
 	def applySettings(self):
 		"""
 		Writes the settings file.  If a change requires a restart of the engine
 		it notifies you with a small dialog box.
 		"""
-		screen_resolution, render_backend, enable_fullscreen, enable_sound = self.OptionsDlg.collectData('screen_resolution', 'render_backend', 'enable_fullscreen', 'enable_sound')
-		render_backend = 'OpenGL' if render_backend is 0 else 'SDL'
-		if render_backend != self.get("FIFE", "RenderBackend"):
-			self.set("FIFE", 'RenderBackend', render_backend)
-			self.changesRequireRestart = True
-		if int(enable_fullscreen) != int(self.get("FIFE", "FullScreen")):
-			self.set("FIFE", 'FullScreen', int(enable_fullscreen))
-			self.changesRequireRestart = True
-		if int(enable_sound) != int(self.get("FIFE", "PlaySounds")):
-			self.set("FIFE", 'PlaySounds', int(enable_sound))
-			self.changesRequireRestart = True
-		if screen_resolution != self._resolutions.index(str(self.get("FIFE", "ScreenWidth")) + 'x' + str(self.get("FIFE", "ScreenHeight"))):
-			self.set("FIFE", 'ScreenWidth', int(self._resolutions[screen_resolution].partition('x')[0]))
-			self.set("FIFE", 'ScreenHeight', int(self._resolutions[screen_resolution].partition('x')[2]))
-			self.changesRequireRestart = True
+		for entry in self._entries:
+			widget = self.OptionsDlg.findChildByName(entry.settingwidgetname)
+			data = widget.getData()
+
+			# If the data is a list we need to get the correct selected data
+			# from the list. This is needed for e.g. dropdowns or listboxs
+			if type(entry.initialdata) is list:
+				value = entry.initialdata[data]
+				self.set(entry.module, entry.name, value)
+			else:
+				self.set(entry.module, entry.name, data)
+
+			if entry.requiresrestart:
+				self.changesRequireRestart = True
+			entry.onApply(widget)
 
 		self.saveSettings()
 
 		self.OptionsDlg.hide()
 		if self.changesRequireRestart:
-			RestartDlg = pychan.loadXML(StringIO(self._changes_gui_xml))
-			RestartDlg.mapEvents({ 'closeButton' : RestartDlg.hide })
-			RestartDlg.show()
+			self._showChangeRequireRestartDialog()
+
+
+	def _showChangeRequireRestartDialog(self):
+		"""Shows a dialog that informes the user that a restart is required
+		to perform the changes."""
+		RestartDlg = pychan.loadXML(StringIO(self._changes_gui_xml))
+		RestartDlg.mapEvents({ 'closeButton' : RestartDlg.hide })
+		RestartDlg.show()
+
 
 	def setAvailableScreenResolutions(self, reslist):
 		"""
@@ -441,7 +499,100 @@
 		shutil.copyfile('settings-dist.xml', os.path.join(self._appdata, self._settings_file))
 		self.changesRequireRestart = True
 		self.loadSettings()
-		self.applySettings()
+		self._showChangeRequireRestartDialog()
 
 		if self.OptionsDlg:
 			self.OptionsDlg.hide()
+
+
+
+class SettingEntry(object):
+
+	def __init__(self, module, name, widgetname, applyfunction=None, initialdata=None, requiresrestart=False):
+		"""
+		@param module: The Setting module this Entry belongs to
+		@type module: C{String}
+		@param name: The Setting's name
+		@type name: C{String}
+		@param widgetname: The name of the widget that is used to change this
+		setting
+		@type widgetname: C{String}
+		@param applyfunction: function that makes the changes when the Setting is
+		saved
+		@type applyfunction: C{function}
+		@param initialdata: If the widget supports the setInitialData() function
+		this can be used to set the initial data
+		@type initialdata: C{String} or C{Boolean}
+		@param requiresrestart: Whether or not the changing of this setting
+		requires a restart
+		@type requiresrestart: C{Boolean}
+		"""
+		self._module = module
+		self._name = name
+		self._settingwidgetname = widgetname
+		self._requiresrestart = requiresrestart
+		self._initialdata = initialdata
+		self._applyfunction = applyfunction
+
+	def initializeWidget(self, widget, currentValue):
+		"""Initialize the widget with needed data"""
+		if self._initialdata is not None:
+			widget.setInitialData(self._initialdata)
+		widget.setData(currentValue)
+
+	def onApply(self, widget):
+		"""Implement actions that need to be taken when the setting is changed
+		here.
+		"""
+		if self._applyfunction is not None:
+			self._applyfunction(widget.getData())
+
+	def _getModule(self):
+		return self._module
+
+	def _setModule(self, module):
+		self._module = module
+
+	def _getName(self):
+		return self._name
+
+	def _setName(self, name):
+		self._name = name
+
+	def _getSettingWidgetName(self):
+		return self._settingwidgetname
+
+	def _setSettingWidgetName(self, settingwidgetname):
+		self._settingwidgetname = settingwidgetname
+
+	def _getRequiresRestart(self):
+		return self._requiresrestart
+
+	def _setRequiresRestart(self, requiresrestart):
+		self._requiresrestart = requiresrestart
+
+	def _getInitialData(self):
+		return self._initialdata
+
+	def _setInitialData(self, initialdata):
+		self._initialdata = initialdata
+
+	def _getApplyFunction(self):
+		return self._applyfunction
+
+	def _setApplyFunction(self, applyfunction):
+		self._applyfunction = applyfunction
+
+	module = property(_getModule, _setModule)
+	name = property(_getName, _setName)
+	settingwidgetname = property(_getSettingWidgetName, _setSettingWidgetName)
+	requiresrestart = property(_getRequiresRestart, _setRequiresRestart)
+	initialdata = property(_getInitialData, _setInitialData)
+	applyfunction = property(_getApplyFunction, _setApplyFunction)
+
+	def __str__(self):
+		return "SettingEntry: " +  self.name + " Module: " + self.module + " Widget: " + \
+		       self.settingwidgetname + " requiresrestart: " + str(self.requiresrestart) + \
+		       " initialdata: " + str(self.initialdata)
+
+