Mercurial > fife-parpg
comparison engine/python/fife/extensions/fife_settings.py @ 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 | 082e919cc348 |
children | 4c7b5eee211c |
comparison
equal
deleted
inserted
replaced
537:764510a6d2f9 | 538:00aa20dc8b7f |
---|---|
86 </Module> | 86 </Module> |
87 | 87 |
88 </Settings> | 88 </Settings> |
89 """ | 89 """ |
90 | 90 |
91 DEFAULT_MODULE = "FIFE" | |
92 | |
91 class Setting(object): | 93 class Setting(object): |
92 """ | 94 """ |
93 This class manages loading and saving of game settings. | 95 This class manages loading and saving of game settings. |
94 | 96 |
95 Usage:: | 97 Usage:: |
145 tree = ET.parse(StringIO(EMPTY_SETTINGS)) | 147 tree = ET.parse(StringIO(EMPTY_SETTINGS)) |
146 tree.write(os.path.join(self._appdata, self._settings_file), 'UTF-8') | 148 tree.write(os.path.join(self._appdata, self._settings_file), 'UTF-8') |
147 | 149 |
148 #default settings | 150 #default settings |
149 self._resolutions = ['640x480', '800x600', '1024x768', '1280x800', '1440x900'] | 151 self._resolutions = ['640x480', '800x600', '1024x768', '1280x800', '1440x900'] |
152 self._renderbackends = ['OpenGL', 'SDL'] | |
150 | 153 |
151 #Used to stylize the options gui | 154 #Used to stylize the options gui |
152 self._gui_style = "default" | 155 self._gui_style = "default" |
153 | 156 |
154 self.loadSettings() | 157 self.loadSettings() |
158 | |
159 # Holds SettingEntries | |
160 self._entries = [] | |
161 | |
162 self._initDefaultSettingEntries() | |
163 | |
164 def _initDefaultSettingEntries(self): | |
165 """Initializes the default fife setting entries. Not to be called from | |
166 outside this class.""" | |
167 self.createAndAddEntry(DEFAULT_MODULE, "PlaySounds", "enable_sound", | |
168 requiresrestart=True) | |
169 self.createAndAddEntry(DEFAULT_MODULE, "FullScreen", "enable_fullscreen", | |
170 requiresrestart=True) | |
171 self.createAndAddEntry(DEFAULT_MODULE, "ScreenResolution", "screen_resolution", initialdata = self._resolutions, | |
172 requiresrestart=True) | |
173 self.createAndAddEntry(DEFAULT_MODULE, "RenderBackend", "render_backend", initialdata = self._renderbackends, | |
174 requiresrestart=True) | |
175 | |
176 def createAndAddEntry(self, module, name, widgetname, applyfunction=None, initialdata=None, requiresrestart=False): | |
177 """" | |
178 @param module: The Setting module this Entry belongs to | |
179 @type module: C{String} | |
180 @param name: The Setting's name | |
181 @type name: C{String} | |
182 @param widgetname: The name of the widget that is used to change this | |
183 setting | |
184 @type widgetname: C{String} | |
185 @param applyfunction: function that makes the changes when the Setting is | |
186 saved | |
187 @type applyfunction: C{function} | |
188 @param initialdata: If the widget supports the setInitialData() function | |
189 this can be used to set the initial data | |
190 @type initialdata: C{String} or C{Boolean} | |
191 @param requiresrestart: Whether or not the changing of this setting | |
192 requires a restart | |
193 @type requiresrestart: C{Boolean} | |
194 """ | |
195 entry = SettingEntry(module, name, widgetname, applyfunction, initialdata, requiresrestart) | |
196 self._entries.append(entry) | |
197 | |
198 def addEntry(self, entry): | |
199 """Adds a new C{SettingEntry} to the Settting | |
200 @param entry: A new SettingEntry that is to be added | |
201 @type entry: C{SettingEntry} | |
202 """ | |
203 self._entries.append(entry) | |
155 | 204 |
156 def loadSettings(self): | 205 def loadSettings(self): |
157 self._tree = ET.parse(os.path.join(self._appdata, self._settings_file)) | 206 self._tree = ET.parse(os.path.join(self._appdata, self._settings_file)) |
158 self._root_element = self._tree.getroot() | 207 self._root_element = self._tree.getroot() |
159 self.validateTree() | 208 self.validateTree() |
374 if os.path.isfile(self._settings_gui_xml): | 423 if os.path.isfile(self._settings_gui_xml): |
375 self.OptionsDlg = pychan.loadXML(self._settings_gui_xml) | 424 self.OptionsDlg = pychan.loadXML(self._settings_gui_xml) |
376 else: | 425 else: |
377 self.OptionsDlg = pychan.loadXML(StringIO(self._settings_gui_xml)) | 426 self.OptionsDlg = pychan.loadXML(StringIO(self._settings_gui_xml)) |
378 self.OptionsDlg.stylize(self._gui_style) | 427 self.OptionsDlg.stylize(self._gui_style) |
379 self.OptionsDlg.distributeInitialData({ | 428 self.fillWidgets() |
380 'screen_resolution' : self._resolutions, | |
381 'render_backend' : ['OpenGL', 'SDL'] | |
382 }) | |
383 self.OptionsDlg.distributeData({ | |
384 'screen_resolution' : self._resolutions.index(str(self.get("FIFE", "ScreenWidth")) + 'x' + str(self.get("FIFE", "ScreenHeight"))), | |
385 'render_backend' : 0 if self.get("FIFE", "RenderBackend") == "OpenGL" else 1, | |
386 'enable_fullscreen' : self.get("FIFE", "FullScreen"), | |
387 'enable_sound' : self.get("FIFE", "PlaySounds") | |
388 }) | |
389 self.OptionsDlg.mapEvents({ | 429 self.OptionsDlg.mapEvents({ |
390 'okButton' : self.applySettings, | 430 'okButton' : self.applySettings, |
391 'cancelButton' : self.OptionsDlg.hide, | 431 'cancelButton' : self.OptionsDlg.hide, |
392 'defaultButton' : self.setDefaults | 432 'defaultButton' : self.setDefaults |
393 }) | 433 }) |
394 self.OptionsDlg.show() | 434 self.OptionsDlg.show() |
395 | 435 |
436 def fillWidgets(self): | |
437 for entry in self._entries: | |
438 widget = self.OptionsDlg.findChildByName(entry.settingwidgetname) | |
439 value = self.get(entry.module, entry.name) | |
440 if type(entry.initialdata) is list: | |
441 try: | |
442 value = entry.initialdata.index(value) | |
443 except ValueError: | |
444 raise ValueError(value + " is not a valid value for " + entry.name) | |
445 entry.initializeWidget(widget, value) | |
446 | |
396 def applySettings(self): | 447 def applySettings(self): |
397 """ | 448 """ |
398 Writes the settings file. If a change requires a restart of the engine | 449 Writes the settings file. If a change requires a restart of the engine |
399 it notifies you with a small dialog box. | 450 it notifies you with a small dialog box. |
400 """ | 451 """ |
401 screen_resolution, render_backend, enable_fullscreen, enable_sound = self.OptionsDlg.collectData('screen_resolution', 'render_backend', 'enable_fullscreen', 'enable_sound') | 452 for entry in self._entries: |
402 render_backend = 'OpenGL' if render_backend is 0 else 'SDL' | 453 widget = self.OptionsDlg.findChildByName(entry.settingwidgetname) |
403 if render_backend != self.get("FIFE", "RenderBackend"): | 454 data = widget.getData() |
404 self.set("FIFE", 'RenderBackend', render_backend) | 455 |
405 self.changesRequireRestart = True | 456 # If the data is a list we need to get the correct selected data |
406 if int(enable_fullscreen) != int(self.get("FIFE", "FullScreen")): | 457 # from the list. This is needed for e.g. dropdowns or listboxs |
407 self.set("FIFE", 'FullScreen', int(enable_fullscreen)) | 458 if type(entry.initialdata) is list: |
408 self.changesRequireRestart = True | 459 value = entry.initialdata[data] |
409 if int(enable_sound) != int(self.get("FIFE", "PlaySounds")): | 460 self.set(entry.module, entry.name, value) |
410 self.set("FIFE", 'PlaySounds', int(enable_sound)) | 461 else: |
411 self.changesRequireRestart = True | 462 self.set(entry.module, entry.name, data) |
412 if screen_resolution != self._resolutions.index(str(self.get("FIFE", "ScreenWidth")) + 'x' + str(self.get("FIFE", "ScreenHeight"))): | 463 |
413 self.set("FIFE", 'ScreenWidth', int(self._resolutions[screen_resolution].partition('x')[0])) | 464 if entry.requiresrestart: |
414 self.set("FIFE", 'ScreenHeight', int(self._resolutions[screen_resolution].partition('x')[2])) | 465 self.changesRequireRestart = True |
415 self.changesRequireRestart = True | 466 entry.onApply(widget) |
416 | 467 |
417 self.saveSettings() | 468 self.saveSettings() |
418 | 469 |
419 self.OptionsDlg.hide() | 470 self.OptionsDlg.hide() |
420 if self.changesRequireRestart: | 471 if self.changesRequireRestart: |
421 RestartDlg = pychan.loadXML(StringIO(self._changes_gui_xml)) | 472 self._showChangeRequireRestartDialog() |
422 RestartDlg.mapEvents({ 'closeButton' : RestartDlg.hide }) | 473 |
423 RestartDlg.show() | 474 |
475 def _showChangeRequireRestartDialog(self): | |
476 """Shows a dialog that informes the user that a restart is required | |
477 to perform the changes.""" | |
478 RestartDlg = pychan.loadXML(StringIO(self._changes_gui_xml)) | |
479 RestartDlg.mapEvents({ 'closeButton' : RestartDlg.hide }) | |
480 RestartDlg.show() | |
481 | |
424 | 482 |
425 def setAvailableScreenResolutions(self, reslist): | 483 def setAvailableScreenResolutions(self, reslist): |
426 """ | 484 """ |
427 A list of valid default screen resolutions. This should be called once | 485 A list of valid default screen resolutions. This should be called once |
428 right after you instantiate Settings. | 486 right after you instantiate Settings. |
439 Overwrites the setting file with the default settings-dist.xml file. | 497 Overwrites the setting file with the default settings-dist.xml file. |
440 """ | 498 """ |
441 shutil.copyfile('settings-dist.xml', os.path.join(self._appdata, self._settings_file)) | 499 shutil.copyfile('settings-dist.xml', os.path.join(self._appdata, self._settings_file)) |
442 self.changesRequireRestart = True | 500 self.changesRequireRestart = True |
443 self.loadSettings() | 501 self.loadSettings() |
444 self.applySettings() | 502 self._showChangeRequireRestartDialog() |
445 | 503 |
446 if self.OptionsDlg: | 504 if self.OptionsDlg: |
447 self.OptionsDlg.hide() | 505 self.OptionsDlg.hide() |
506 | |
507 | |
508 | |
509 class SettingEntry(object): | |
510 | |
511 def __init__(self, module, name, widgetname, applyfunction=None, initialdata=None, requiresrestart=False): | |
512 """ | |
513 @param module: The Setting module this Entry belongs to | |
514 @type module: C{String} | |
515 @param name: The Setting's name | |
516 @type name: C{String} | |
517 @param widgetname: The name of the widget that is used to change this | |
518 setting | |
519 @type widgetname: C{String} | |
520 @param applyfunction: function that makes the changes when the Setting is | |
521 saved | |
522 @type applyfunction: C{function} | |
523 @param initialdata: If the widget supports the setInitialData() function | |
524 this can be used to set the initial data | |
525 @type initialdata: C{String} or C{Boolean} | |
526 @param requiresrestart: Whether or not the changing of this setting | |
527 requires a restart | |
528 @type requiresrestart: C{Boolean} | |
529 """ | |
530 self._module = module | |
531 self._name = name | |
532 self._settingwidgetname = widgetname | |
533 self._requiresrestart = requiresrestart | |
534 self._initialdata = initialdata | |
535 self._applyfunction = applyfunction | |
536 | |
537 def initializeWidget(self, widget, currentValue): | |
538 """Initialize the widget with needed data""" | |
539 if self._initialdata is not None: | |
540 widget.setInitialData(self._initialdata) | |
541 widget.setData(currentValue) | |
542 | |
543 def onApply(self, widget): | |
544 """Implement actions that need to be taken when the setting is changed | |
545 here. | |
546 """ | |
547 if self._applyfunction is not None: | |
548 self._applyfunction(widget.getData()) | |
549 | |
550 def _getModule(self): | |
551 return self._module | |
552 | |
553 def _setModule(self, module): | |
554 self._module = module | |
555 | |
556 def _getName(self): | |
557 return self._name | |
558 | |
559 def _setName(self, name): | |
560 self._name = name | |
561 | |
562 def _getSettingWidgetName(self): | |
563 return self._settingwidgetname | |
564 | |
565 def _setSettingWidgetName(self, settingwidgetname): | |
566 self._settingwidgetname = settingwidgetname | |
567 | |
568 def _getRequiresRestart(self): | |
569 return self._requiresrestart | |
570 | |
571 def _setRequiresRestart(self, requiresrestart): | |
572 self._requiresrestart = requiresrestart | |
573 | |
574 def _getInitialData(self): | |
575 return self._initialdata | |
576 | |
577 def _setInitialData(self, initialdata): | |
578 self._initialdata = initialdata | |
579 | |
580 def _getApplyFunction(self): | |
581 return self._applyfunction | |
582 | |
583 def _setApplyFunction(self, applyfunction): | |
584 self._applyfunction = applyfunction | |
585 | |
586 module = property(_getModule, _setModule) | |
587 name = property(_getName, _setName) | |
588 settingwidgetname = property(_getSettingWidgetName, _setSettingWidgetName) | |
589 requiresrestart = property(_getRequiresRestart, _setRequiresRestart) | |
590 initialdata = property(_getInitialData, _setInitialData) | |
591 applyfunction = property(_getApplyFunction, _setApplyFunction) | |
592 | |
593 def __str__(self): | |
594 return "SettingEntry: " + self.name + " Module: " + self.module + " Widget: " + \ | |
595 self.settingwidgetname + " requiresrestart: " + str(self.requiresrestart) + \ | |
596 " initialdata: " + str(self.initialdata) | |
597 | |
598 |