# HG changeset patch
# User mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
# Date 1218124006 0
# Node ID 9a1529f9625ea3615e43ced8c7fd165e1022345d
# Parent 6e1fd35714409c3c947aa7936a1a2625e4fa1d9a
* Indentation patch by GreyGhost
diff -r 6e1fd3571440 -r 9a1529f9625e clients/rio_de_hola/scripts/agents/agent.py
--- a/clients/rio_de_hola/scripts/agents/agent.py Wed Aug 06 22:35:27 2008 +0000
+++ b/clients/rio_de_hola/scripts/agents/agent.py Thu Aug 07 15:46:46 2008 +0000
@@ -16,7 +16,7 @@
def start(self):
raise ProgrammingError('No start defined for Agent')
-
+
def create_anonymous_agents(model, objectName, layer, agentClass):
agents = []
diff -r 6e1fd3571440 -r 9a1529f9625e clients/rio_de_hola/scripts/agents/beekeeper.py
--- a/clients/rio_de_hola/scripts/agents/beekeeper.py Wed Aug 06 22:35:27 2008 +0000
+++ b/clients/rio_de_hola/scripts/agents/beekeeper.py Thu Aug 07 15:46:46 2008 +0000
@@ -17,7 +17,7 @@
c.x += random.randint(-1, 1)
c.y += random.randint(-1, 1)
self.talk()
-
+
def talk(self):
self.state = _STATE_TALK
self.agent.act('talk', self.facingLoc, True) # never calls back
diff -r 6e1fd3571440 -r 9a1529f9625e clients/rio_de_hola/scripts/agents/cloud.py
--- a/clients/rio_de_hola/scripts/agents/cloud.py Wed Aug 06 22:35:27 2008 +0000
+++ b/clients/rio_de_hola/scripts/agents/cloud.py Thu Aug 07 15:46:46 2008 +0000
@@ -8,7 +8,7 @@
def __init__(self, model, agentName, layer, uniqInMap=False):
super(Cloud, self).__init__(model, agentName, layer, uniqInMap)
self.state = _STATE_NONE
-
+
def isOutOfBounds(self, c):
return (c.x < 0) or (c.x > 100) or (c.y < 0) or (c.y > 100)
@@ -33,16 +33,15 @@
self.loc = self.agent.getLocation()
self.initialCoords = self.agent.getLocation().getExactLayerCoordinates()
self.appear()
-
+
def appear(self):
self.state = _STATE_APPEAR
self.agent.act('appear', self.loc, False)
-
+
def disappear(self):
self.state = _STATE_DISAPPEAR
self.agent.act('disappear', self.loc, False)
-
+
def move(self):
self.state = _STATE_FLOATING
self.agent.act('default', self.loc, False)
-
diff -r 6e1fd3571440 -r 9a1529f9625e clients/rio_de_hola/scripts/agents/girl.py
--- a/clients/rio_de_hola/scripts/agents/girl.py Wed Aug 06 22:35:27 2008 +0000
+++ b/clients/rio_de_hola/scripts/agents/girl.py Thu Aug 07 15:46:46 2008 +0000
@@ -30,19 +30,18 @@
l = fife.Location(self.layer)
l.setLayerCoordinates(fife.ModelCoordinate(*self.waypoints[self.waypoint_counter % len(self.waypoints)]))
return l
-
+
def start(self):
self.follow_hero()
-
+
def idle(self):
self.state = _STATE_IDLE
self.agent.act('stand', self.agent.getFacingLocation(), False)
-
+
def follow_hero(self):
self.state = _STATE_FOLLOW
self.agent.follow('run', self.hero, GIRL_SPEED)
-
+
def run(self, location):
self.state = _STATE_RUN
self.agent.move('run', location, GIRL_SPEED)
-
diff -r 6e1fd3571440 -r 9a1529f9625e clients/rio_de_hola/scripts/agents/hero.py
--- a/clients/rio_de_hola/scripts/agents/hero.py Wed Aug 06 22:35:27 2008 +0000
+++ b/clients/rio_de_hola/scripts/agents/hero.py Thu Aug 07 15:46:46 2008 +0000
@@ -22,22 +22,22 @@
heroTexts = TDS.readSetting("heroTexts", type='list', text=True)
txtindex = random.randint(0, len(heroTexts) - 1)
instance.say(heroTexts[txtindex], 2500)
-
+
def start(self):
self.idle()
-
+
def idle(self):
self.state = _STATE_IDLE
self.agent.act('stand', self.agent.getFacingLocation())
-
+
def run(self, location):
self.state = _STATE_RUN
self.agent.move('run', location, 4 * float(TDS.readSetting("TestAgentSpeed")))
-
+
def kick(self, target):
self.state = _STATE_KICK
self.agent.act('kick', target)
-
+
def talk(self, target):
self.state = _STATE_TALK
self.agent.act('talk', target)
diff -r 6e1fd3571440 -r 9a1529f9625e clients/rio_de_hola/scripts/common/eventlistenerbase.py
--- a/clients/rio_de_hola/scripts/common/eventlistenerbase.py Wed Aug 06 22:35:27 2008 +0000
+++ b/clients/rio_de_hola/scripts/common/eventlistenerbase.py Thu Aug 07 15:46:46 2008 +0000
@@ -1,10 +1,9 @@
import fife
-class EventListenerBase(fife.IKeyListener, fife.ICommandListener, fife.IMouseListener,
- fife.ConsoleExecuter, fife.IWidgetListener):
+class EventListenerBase(fife.IKeyListener, fife.ICommandListener, fife.IMouseListener, fife.ConsoleExecuter, fife.IWidgetListener):
def __init__(self, engine, regKeys=False, regCmd=False, regMouse=False, regConsole=False, regWidget=False):
self.eventmanager = engine.getEventManager()
-
+
fife.IKeyListener.__init__(self)
if regKeys:
self.eventmanager.addKeyListener(self)
@@ -20,8 +19,8 @@
fife.IWidgetListener.__init__(self)
if regWidget:
self.eventmanager.addWidgetListener(self)
-
-
+
+
def mousePressed(self, evt):
pass
def mouseReleased(self, evt):
diff -r 6e1fd3571440 -r 9a1529f9625e clients/rio_de_hola/scripts/world.py
--- a/clients/rio_de_hola/scripts/world.py Wed Aug 06 22:35:27 2008 +0000
+++ b/clients/rio_de_hola/scripts/world.py Thu Aug 07 15:46:46 2008 +0000
@@ -18,17 +18,17 @@
def __init__(self, map):
fife.MapChangeListener.__init__(self)
map.addChangeListener(self)
-
+
def onMapChanged(self, map, changedLayers):
return
print "Changes on map ", map.getId()
for layer in map.getLayers():
print layer.getId()
print " ", ["%s, %x" % (i.getObject().getId(), i.getChangeInfo()) for i in layer.getChangedInstances()]
-
+
def onLayerCreate(self, map, layer):
pass
-
+
def onLayerDelete(self, map, layer):
pass
@@ -46,11 +46,11 @@
self.instancemenu = None
self.instance_to_agent = {}
self.dynamic_widgets = {}
-
+
def show_instancemenu(self, clickpoint, instance):
if instance.getFifeId() == self.hero.agent.getFifeId():
return
-
+
dynamicbuttons = ('moveButton', 'talkButton', 'kickButton', 'inspectButton')
if not self.instancemenu:
self.instancemenu = pychan.loadXML('gui/instancemenu.xml')
@@ -67,10 +67,10 @@
self.instancemenu.removeChild(self.dynamic_widgets[btn])
except pychan.exceptions.RuntimeError:
pass
-
+
self.instancemenu.clickpoint = clickpoint
self.instancemenu.instance = instance
-
+
self.instancemenu.addChild(self.dynamic_widgets['inspectButton'])
target_distance = self.hero.agent.getLocationRef().getLayerDistanceTo(instance.getLocationRef())
if target_distance > 3.0:
@@ -81,11 +81,11 @@
self.instancemenu.addChild(self.dynamic_widgets['kickButton'])
self.instancemenu.position = (clickpoint.x, clickpoint.y)
self.instancemenu.show()
-
+
def hide_instancemenu(self):
if self.instancemenu:
self.instancemenu.hide()
-
+
def reset(self):
self.map, self.agentlayer = None, None
self.cameras = {}
@@ -99,16 +99,16 @@
self.reset()
self.map = loadMapFile(filename, self.engine)
self.maplistener = MapListener(self.map)
-
+
self.agentlayer = self.map.getLayer('TechdemoMapGroundObjectLayer')
self.hero = Hero(self.model, 'PC', self.agentlayer)
self.instance_to_agent[self.hero.agent.getFifeId()] = self.hero
self.hero.start()
-
+
self.girl = Girl(self.model, 'NPC:girl', self.agentlayer)
self.instance_to_agent[self.girl.agent.getFifeId()] = self.girl
self.girl.start()
-
+
self.beekeepers = create_anonymous_agents(self.model, 'beekeeper', self.agentlayer, Beekeeper)
for beekeeper in self.beekeepers:
self.instance_to_agent[beekeeper.agent.getFifeId()] = beekeeper
@@ -118,37 +118,37 @@
self.clouds = create_anonymous_agents(self.model, 'Cloud', cloudlayer, Cloud)
for cloud in self.clouds:
cloud.start(0.1, 0.05)
-
+
for cam in self.view.getCameras():
self.cameras[cam.getId()] = cam
self.cameras['main'].attach(self.hero.agent)
-
+
self.view.resetRenderers()
renderer = fife.FloatingTextRenderer.getInstance(self.cameras['main'])
textfont = self.engine.getGuiManager().createFont('fonts/rpgfont.png', 0, str(TDS.readSetting("FontGlyphs", strip=False)));
renderer.changeDefaultFont(textfont)
-
+
renderer = fife.FloatingTextRenderer.getInstance(self.cameras['small'])
renderer.changeDefaultFont(None)
-
+
renderer = self.cameras['main'].getRenderer('CoordinateRenderer')
renderer.clearActiveLayers()
renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("CoordinateLayerName"))))
-
+
renderer = self.cameras['main'].getRenderer('QuadTreeRenderer')
renderer.setEnabled(True)
renderer.clearActiveLayers()
if str(TDS.readSetting("QuadTreeLayerName")):
renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("QuadTreeLayerName"))))
-
+
self.cameras['small'].getLocationRef().setExactLayerCoordinates( fife.ExactModelCoordinate( 40.0, 40.0, 0.0 ))
self.initial_cam2_x = self.cameras['small'].getLocation().getExactLayerCoordinates().x
self.cur_cam2_x = self.initial_cam2_x
self.cam2_scrolling_right = True
self.cameras['small'].setEnabled(False)
-
+
self.target_rotation = self.cameras['main'].getRotation()
-
+
def save(self, filename):
saveMapFile(filename, self.engine, self.map)
@@ -174,29 +174,29 @@
self.target_rotation = (self.target_rotation + 90) % 360
elif keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL):
self.ctrldown = True
-
+
def keyReleased(self, evt):
keyval = evt.getKey().getValue()
if keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL):
self.ctrldown = False
-
+
def mouseWheelMovedUp(self, evt):
if self.ctrldown:
self.cameras['main'].setZoom(self.cameras['main'].getZoom() * 1.05)
-
+
def mouseWheelMovedDown(self, evt):
if self.ctrldown:
self.cameras['main'].setZoom(self.cameras['main'].getZoom() / 1.05)
-
+
def changeRotation(self):
currot = self.cameras['main'].getRotation()
if self.target_rotation != currot:
self.cameras['main'].setRotation((currot + 5) % 360)
-
+
def mousePressed(self, evt):
if evt.isConsumedByWidgets():
return
-
+
clickpoint = fife.ScreenPoint(evt.getX(), evt.getY())
if (evt.getButton() == fife.MouseEvent.LEFT):
self.hide_instancemenu()
@@ -205,13 +205,13 @@
l = fife.Location(self.agentlayer)
l.setMapCoordinates(target_mapcoord)
self.hero.run(l)
-
+
if (evt.getButton() == fife.MouseEvent.RIGHT):
instances = self.cameras['main'].getMatchingInstances(clickpoint, self.agentlayer)
print "selected instances on agent layer: ", [i.getObject().getId() for i in instances]
if instances:
self.show_instancemenu(clickpoint, instances[0])
-
+
def mouseMoved(self, evt):
renderer = fife.InstanceRenderer.getInstance(self.cameras['main'])
renderer.removeAllOutlines()
@@ -221,7 +221,7 @@
for i in instances:
if i.getObject().getId() in ('girl', 'beekeeper'):
renderer.addOutlined(i, 173, 255, 47, 2)
-
+
def onConsoleCommand(self, command):
result = ''
try:
@@ -233,7 +233,7 @@
def onMoveButtonPress(self):
self.hide_instancemenu()
self.hero.run(self.instancemenu.instance.getLocationRef())
-
+
def onTalkButtonPress(self):
self.hide_instancemenu()
instance = self.instancemenu.instance
@@ -246,12 +246,12 @@
girlTexts = TDS.readSetting("girlTexts", type='list', text=True)
txtindex = random.randint(0, len(girlTexts) - 1)
instance.say(girlTexts[txtindex], 5000)
-
+
def onKickButtonPress(self):
self.hide_instancemenu()
self.hero.kick(self.instancemenu.instance.getLocationRef())
self.instancemenu.instance.say('Hey!', 1000)
-
+
def onInspectButtonPress(self):
self.hide_instancemenu()
inst = self.instancemenu.instance
@@ -261,7 +261,7 @@
saytext.append(' ID %s and' % inst.getFifeId())
saytext.append(' object name %s' % inst.getObject().getId())
self.hero.agent.say('\n'.join(saytext), 3500)
-
+
def pump(self):
if self.cameras['small'].isEnabled():
loc = self.cameras['small'].getLocation()
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/basicapplication.py
--- a/engine/extensions/basicapplication.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/basicapplication.py Thu Aug 07 15:46:46 2008 +0000
@@ -13,7 +13,7 @@
class ExitEventListener(fife.IKeyListener):
"""
Default, rudimentary event listener.
-
+
Will cause the application to quit on pressing ESC.
"""
def __init__(self, app):
@@ -29,32 +29,32 @@
keyval = evt.getKey().getValue()
if keyval == fife.Key.ESCAPE:
self.app.quit()
-
+
def keyReleased(self, evt):
pass
class ApplicationBase(object):
"""
ApplicationBase is an extendable class that provides a basic environment for a FIFE-based client.
-
+
The unextended application reads in and initializes engine settings, sets up a simple event
listener, and pumps the engine while listening for a quit message. Specialized applications can
modify settings.py to change initial engine settings. They can provide their own event listener
by overriding L{createListener}. And they can override the L{_pump} method
to define runtime behavior of the application.
-
+
"""
def __init__(self):
self.engine = fife.Engine()
self.loadSettings()
self.initLogging()
-
+
self.engine.init()
-
+
self._animationloader = XMLAnimationLoader(self.engine.getImagePool(), self.engine.getVFS())
self.engine.getAnimationPool().addResourceLoader(self._animationloader)
-
+
self.quitRequested = False
self.breakRequested = False
self.returnValues = []
@@ -66,7 +66,7 @@
"""
import settings
self.settings = settings
-
+
engineSetting = self.engine.getSettings()
engineSetting.setDefaultFontGlyphs(settings.FontGlyphs)
engineSetting.setDefaultFontPath(settings.Font)
@@ -89,7 +89,7 @@
engineSetting.setImageChunkingSize(settings.ImageChunkSize)
except:
pass
-
+
def initLogging(self):
"""
Initialize the LogManager.
@@ -102,7 +102,7 @@
"""
This creates a default event listener, which will just close the program
after pressing ESC.
-
+
You should override this method to provide your own event handling.
"""
return ExitEventListener(self)
@@ -116,11 +116,11 @@
retval = self.mainLoop()
self.engine.finalizePumping()
return retval
-
+
def mainLoop(self):
"""
The programs main loop.
-
+
Do not override this, instead provide your own L{_pump} method.
You can call this recursively, e.g. to provide synchronous
Dialogs :-) and break out of the current mainLoop by calling
@@ -139,23 +139,23 @@
if self.breakRequested:
self.breakRequested = False
break
-
+
return self.returnValues.pop()
def breakFromMainLoop(self,returnValue):
"""
Break from the currently running L{mainLoop}.
-
+
The passed argument will be returned by the mainLoop.
"""
self.returnValues[-1] = returnValue
self.breakRequested = True
-
+
def _pump(self):
"""
Application pump.
-
+
Derived classes can specialize this for unique behavior.
This is called every frame.
"""
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/fife_utils.py
--- a/engine/extensions/fife_utils.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/fife_utils.py Thu Aug 07 15:46:46 2008 +0000
@@ -11,5 +11,3 @@
if m.group(1) == type('').getTypeStr():
ret = True
return ret
-
-
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/fifelog.py
--- a/engine/extensions/fifelog.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/fifelog.py Thu Aug 07 15:46:46 2008 +0000
@@ -6,7 +6,7 @@
You can set log targets individually (prompt, file). You can also adjust
things like visible modules through log manager.
'''
-
+
def __init__(self, engine, promptlog=True, filelog=False):
'''
Constructs new log manager
@@ -23,7 +23,7 @@
if k.startswith('LM_') and k not in ('LM_CORE', 'LM_MODULE_MAX'):
self.mod2name[v] = self.lm.getModuleName(v)
self.name2mod = dict([(v.lower(), k) for k, v in self.mod2name.items()])
-
+
def addVisibleModules(self, *names):
'''
Adds modules that are visible in logs. By default, all modules
@@ -41,7 +41,7 @@
self.lm.addVisibleModule(self.name2mod[m])
except KeyError:
print 'Tried to enable non-existing log module "%s"' % m
-
+
def removeVisibleModules(self, *names):
'''
Removes modules that are visible in logs. By default, all modules
@@ -56,7 +56,7 @@
else:
for m in names:
self.lm.removeVisibleModule(self.name2mod[m])
-
+
def getVisibleModules(self):
'''
Gets currently visible modules
@@ -75,4 +75,3 @@
'''
self.lm.clearVisibleModules()
self.addVisibleModules(*names)
-
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/pychan/__init__.py
--- a/engine/extensions/pychan/__init__.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/pychan/__init__.py Thu Aug 07 15:46:46 2008 +0000
@@ -247,11 +247,10 @@
@param engine: The FIFE engine object.
"""
- from manager import Manager
+ from manager import Manager
global manager
manager = Manager(engine,debug)
-
# XML Loader
from xml.sax import saxutils, handler
@@ -327,7 +326,7 @@
if self.root:
self.root.addChild( obj )
self.root = obj
-
+
def _createSpacer(self,cls,name,attrs):
obj = cls(parent=self.root)
if hasattr(self.root,'add'):
@@ -345,33 +344,33 @@
def loadXML(filename_or_stream):
"""
Loads a PyChan XML file and generates a widget from it.
-
+
@param filename_or_stream: A filename or a file-like object (for example using StringIO).
-
+
The XML format is very dynamic, in the sense, that the actual allowed tags and attributes
depend on the PyChan code.
-
+
So when a tag C{Button} is encountered, an instance of class Button will be generated,
and added to the parent object.
All attributes will then be parsed and then set in the following way:
-
+
- position,size,min_size,max_size,margins - These are assumed to be comma separated tuples
of integers.
- foreground_color,base_color,background_color - These are assumed to be triples of comma
separated integers.
- opaque,border_size,padding - These are assumed to be simple integers.
-
+
All other attributes are set verbatim as strings on the generated instance.
In case a Widget does not accept an attribute to be set or the attribute can not be parsed
correctly, the function will raise a GuiXMLError.
-
+
In short::
-
+
This result in the following code executed::
-
+
vbox = VBox(parent=None)
button = Button(parent=vbox)
button.text = "X"
@@ -388,18 +387,18 @@
def setupModalExecution(mainLoop,breakFromMainLoop):
"""
Setup the synchronous dialog execution feature.
-
+
You can enable synchronous dialog execution by
passing to functions to this function.
-
+
@param mainLoop: Function - This is regarded as the applications
main loop, which should be able to be called recursively.
It should not take no arguments and return the argument
passed to the second function (breakFromMainLoop).
-
+
@param breakFromMainLoop: Function -This function should cause the
first function to finish and return the passed argument.
-
+
With these to functions dialogs can be executed synchronously.
See L{widgets.Widget.execute}.
"""
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/pychan/attrs.py
--- a/engine/extensions/pychan/attrs.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/pychan/attrs.py Thu Aug 07 15:46:46 2008 +0000
@@ -28,7 +28,7 @@
"""
def __init__(self,name):
self.name = name
-
+
def set(self,obj,value):
"""
Parses the given value with the L{parse} method
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/pychan/fonts.py
--- a/engine/extensions/pychan/fonts.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/pychan/fonts.py Thu Aug 07 15:46:46 2008 +0000
@@ -18,7 +18,7 @@
self.antialias = int(get("antialias",1))
self.color = map(int,get("color","255,255,255").split(','))
self.font = Manager.manager.guimanager.createFont(self.source,self.size,"")
-
+
if self.font is None:
raise InitializationError("Could not load font %s" % name)
@@ -26,7 +26,7 @@
self.font.setColor(*self.color)
else:
raise InitializationError("Unsupported font type %s" % self.typename)
-
+
self.font.setRowSpacing( self.row_spacing )
self.font.setGlyphSpacing( self.glyph_spacing )
@@ -36,12 +36,12 @@
Static method to load font definitions out of a PyChan config file.
"""
import ConfigParser
-
+
fontdef = ConfigParser.ConfigParser()
fontdef.read(filename)
-
+
sections = [section for section in fontdef.sections() if section.startswith("Font/")]
-
+
fonts = []
for section in sections:
name = section[5:]
@@ -54,7 +54,7 @@
def __str__(self):
return "Font(source='%s')" % self.source
-
+
def __repr__(self):
return "" % (self.source,id(self))
@@ -63,7 +63,6 @@
Load fonts from a config file. These are then available via their name.
"""
from manager import Manager
-
+
for font in Font.loadFromFile(filename):
Manager.manager.addFont(font)
-
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/pychan/manager.py
--- a/engine/extensions/pychan/manager.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/pychan/manager.py Thu Aug 07 15:46:46 2008 +0000
@@ -17,15 +17,15 @@
raise InitializationError("No event manager installed.")
if not self.engine.getGuiManager():
raise InitializationError("No GUI manager installed.")
-
+
self.guimanager = engine.getGuiManager()
self.fonts = {}
#glyphs = ' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/:();%`\'*#=[]"'
self.fonts['default'] = self.engine.getDefaultFont()
-
+
self.styles = {}
self.addStyle('default',DEFAULT_STYLE)
-
+
self.widgetEvents = {}
self.engine.getEventManager().addWidgetListener(self)
Manager.manager = self
@@ -60,11 +60,11 @@
def getFont(self,name):
"""
Returns a GuiFont identified by its name.
-
+
@param name: A string identifier from the font definitions in pychans config files.
"""
font = self.fonts.get(name)
-
+
# For the default font directly return it,
# otherwise the GuiFont is in the font attribute.
return getattr(font,"font",font)
@@ -74,7 +74,7 @@
Add a font to the font registry. It's not necessary to call this directly.
But it expects a L{Font} instance and throws an L{InitializationError}
otherwise.
-
+
@param font: A L{Font} instance.
"""
if not isinstance(font,fonts.Font):
@@ -83,7 +83,7 @@
def addStyle(self,name,style):
style = self._remapStyleKeys(style)
-
+
for k,v in self.styles.get('default',{}).items():
style[k] = style.get(k,v)
self.styles[name] = style
@@ -93,7 +93,7 @@
for k,v in style.get('default',{}).items():
v = kwargs.get(k,v)
setattr(widget,k,v)
-
+
cls = widget.__class__
for applicable,specstyle in style.items():
if not isinstance(applicable,tuple):
@@ -108,13 +108,13 @@
def _toClass(class_):
if class_ == "default":
return class_
-
+
if type(class_) == type(widgets.Widget) and issubclass(class_,widgets.Widget):
return class_
if not widgets.WIDGETS.has_key(str(class_)):
raise InitializationError("Can't resolve %s to a widget class." % repr(class_))
return widgets.WIDGETS[str(class_)]
-
+
style_copy = {}
for k,v in style.items():
if isinstance(k,tuple):
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/pychan/tools.py
--- a/engine/extensions/pychan/tools.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/pychan/tools.py Thu Aug 07 15:46:46 2008 +0000
@@ -28,12 +28,12 @@
"""
Curries a function with extra arguments to
create a suitable callback.
-
+
If you don't know what this means, don't worry.
It is designed for the case where you need
different buttons to execute basically the same code
with different argumnets.
-
+
Usage::
# The target callback
def printStuff(text):
@@ -48,7 +48,6 @@
callback(*args,**kwargs)
return real_callback
-
def this_is_deprecated(func,message=None):
if message is None:
message = repr(func)
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/pychan/widgets.py
--- a/engine/extensions/pychan/widgets.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/pychan/widgets.py Thu Aug 07 15:46:46 2008 +0000
@@ -30,15 +30,15 @@
"""
This is the common widget base class, which provides most of the wrapping
functionality.
-
+
Attributes
==========
-
+
Widgets are manipulated (mostly) through attributes - and these can all be set by XML attributes.
Derived widgets will have other attributes. Please see their B{New Attributes} sections. The types of the
attributes are pretty straightforward, but note that Position and Color attribute types will also accept
C{fife.Point} and C{fife.Color} values.
-
+
- name: String: The identification of the widget, most useful if it is unique within a given widget hiarachy.
This is used to find widgets by L{mapEvents},L{distributeInitialData},L{distributeData} and L{collectData}.
- position: Position: The position relative to the parent widget - or on screen, if this is the root widget.
@@ -59,7 +59,7 @@
Convenience Attributes
======================
-
+
These attributes are convenience/shorthand versions of above mentioned attributes and assignment will reflect
the associated attributes values. E.g. the following is equivalent::
# Set X position, leave Y alone
@@ -76,20 +76,20 @@
- height: Integer: The vertical part of the size attribute.
"""
-
+
ATTRIBUTES = [ Attr('name'), PointAttr('position'),
PointAttr('min_size'), PointAttr('size'), PointAttr('max_size'),
ColorAttr('base_color'),ColorAttr('background_color'),ColorAttr('foreground_color'),
Attr('style'), Attr('font'),IntAttr('border_size')
]
-
+
DEFAULT_NAME = '__unnamed__'
-
+
HIDE_SHOW_ERROR = """\
You can only show/hide the top widget of a hierachy.
Use 'addChild' or 'removeChild' to add/remove labels for example.
"""
-
+
def __init__(self,parent = None, name = DEFAULT_NAME,
size = (-1,-1), min_size=(0,0), max_size=(5000,5000),
style = None, **kwargs):
@@ -97,53 +97,53 @@
assert( hasattr(self,'real_widget') )
self._has_listener = False
self._visible = False
-
+
# Data distribution & retrieval settings
self.accepts_data = False
self.accepts_initial_data = False
self._parent = parent
-
+
# This will also set the _event_id and call real_widget.setActionEventId
self.name = name
-
+
self.min_size = min_size
self.max_size = max_size
self.size = size
self.position_technique = "explicit"
self.font = 'default'
-
+
# Inherit style
if style is None and parent:
style = parent.style
self.style = style or "default"
-
+
# Not needed as attrib assignment will trigger manager.stylize call
#manager.stylize(self,self.style)
def execute(self,bind):
"""
Execute a dialog synchronously.
-
+
As argument a dictionary mapping widget names to return values
is expected. Events from these widgets will cause this function
to return with the associated return value.
-
+
This function will not return until such an event occurs.
The widget will be shown before execution and hidden afterwards.
You can only execute root widgets.
-
+
Note: This feature is not tested well, and the API will probably
change. Otherwise have fun::
# Okay this a very condensed example :-)
return pychan.loadXML("contents/gui/dialog.xml").execute({ 'okButton' : True, 'closeButton' : False })
-
+
"""
if not get_manager().can_execute:
raise RuntimeError("Synchronous execution is not set up!")
if self._parent:
raise RuntimeError("You can only 'execute' root widgets, not %s!" % str(self))
-
+
for name,returnValue in bind.items():
def _quitThisDialog(returnValue = returnValue ):
get_manager().breakFromMainLoop( returnValue )
@@ -170,7 +170,7 @@
The old event handler (if any) will be overridden by the callback.
If None is given, the event will be disabled. You can query L{isCaptured}
wether this widgets events are currently captured.
-
+
It might be useful to check out L{tools.callbackWithArguments}.
"""
@@ -226,7 +226,7 @@
get_manager().hide(self)
self.afterHide()
self._visible = False
-
+
def isVisible(self):
"""
Check whether the widget is currently shown,
@@ -236,7 +236,7 @@
while widget._parent:
widget = widget._parent
return widget._visible
-
+
def adaptLayout(self):
"""
Execute the Layout engine. Automatically called by L{show}.
@@ -245,7 +245,7 @@
"""
self._recursiveResizeToContent()
self._recursiveExpandContent()
-
+
def beforeShow(self):
"""
This method is called just before the widget is shown.
@@ -263,7 +263,7 @@
def findChildren(self,**kwargs):
"""
Find all contained child widgets by attribute values.
-
+
Usage::
closeButtons = root_widget.findChildren(name='close')
"""
@@ -277,7 +277,7 @@
def findChild(self,**kwargs):
""" Find the first contained child widgets by attribute values.
-
+
Usage::
closeButton = root_widget.findChild(name='close')
"""
@@ -312,7 +312,7 @@
"""
Convenience function to map widget events to functions
in a batch.
-
+
Subsequent calls of mapEvents will merge events with different
widget names and override the previously set callback.
You can also pass C{None} instead of a callback, which will
@@ -337,7 +337,7 @@
if not self.accepts_initial_data:
raise RuntimeError("Trying to set data on a widget that does not accept initial data. Widget: %s Data: %s " % (repr(self),repr(data)))
self._realSetInitialData(data)
-
+
def setData(self,data):
"""
Set the user-mutable data on a widget, what this means depends on the Widget.
@@ -364,19 +364,19 @@
using the keys as names and the values as the data (which is set via L{setInitialData}).
If more than one widget matches - the data is set on ALL matching widgets.
By default a missing widget is just ignored.
-
+
Use it like this::
guiElement.distributeInitialData({
'myTextField' : 'Hello World!',
'myListBox' : ["1","2","3"]
})
-
+
"""
for name,data in initialDataMap.items():
widgetList = self.findChildren(name = name)
for widget in widgetList:
widget.setInitialData(data)
-
+
def distributeData(self,dataMap):
"""
Distribute data from a dictionary over the widgets in the hierachy
@@ -402,18 +402,18 @@
This can only handle UNIQUE widget names (in the hierachy)
and will raise a RuntimeError if the number of matching widgets
is not equal to one.
-
+
Usage::
data = guiElement.collectDataAsDict(['myTextField','myListBox'])
print "You entered:",data['myTextField']," and selected ",data['myListBox']
-
+
"""
dataMap = {}
for name in widgetNames:
widgetList = self.findChildren(name = name)
if len(widgetList) != 1:
raise RuntimeError("CollectData can only handle widgets with unique names.")
-
+
dataMap[name] = widgetList[0].getData()
return dataMap
@@ -423,20 +423,20 @@
This can only handle UNIQUE widget names (in the hierachy)
and will raise a RuntimeError if the number of matching widgets
is not equal to one.
-
+
This function takes an arbitrary number of widget names and
returns a list of the collected data in the same order.
-
+
In case only one argument is given, it will return just the
data, with out putting it into a list.
-
+
Usage::
# Multiple element extraction:
text, selected = guiElement.collectData('myTextField','myListBox')
print "You entered:",text," and selected item nr",selected
# Single elements are handled gracefully, too:
test = guiElement.collectData('testElement')
-
+
"""
dataList = []
for name in widgetNames:
@@ -460,7 +460,6 @@
print "name".ljust(20),"widget".ljust(50),"parent"
self.deepApply(_printNamedWidget)
-
def stylize(self,style,**kwargs):
"""
Recursively apply a style to all widgets.
@@ -480,7 +479,7 @@
Try to expand any spacer in the widget within the current size.
Do not call directly.
"""
-
+
def _recursiveResizeToContent(self):
"""
@@ -516,7 +515,7 @@
def __str__(self):
return "%s(name='%s')" % (self.__class__.__name__,self.name)
-
+
def __repr__(self):
return "<%s(name='%s') at %x>" % (self.__class__.__name__,self.name,id(self))
@@ -573,7 +572,7 @@
color = fife.Color(*color)
self.real_widget.setBaseColor(color)
base_color = property(_getBaseColor,_setBaseColor)
-
+
def _getBackgroundColor(self): return self.real_widget.getBackgroundColor()
def _setBackgroundColor(self,color):
if isinstance(color,type(())):
@@ -587,14 +586,14 @@
color = fife.Color(*color)
self.real_widget.setForegroundColor(color)
foreground_color = property(_getForegroundColor,_setForegroundColor)
-
+
def _getSelectionColor(self): return self.real_widget.getSelectionColor()
def _setSelectionColor(self,color):
if isinstance(color,type(())):
color = fife.Color(*color)
self.real_widget.setSelectionColor(color)
selection_color = property(_getSelectionColor,_setSelectionColor)
-
+
def _getName(self): return self._name
def _setName(self,name):
from pychan import manager
@@ -631,10 +630,10 @@
be position via the position attribute. If you want to use the layout engine,
you have to use derived containers with vertical or horizontal orientation
(L{VBox} or L{HBox})
-
+
New Attributes
==============
-
+
- padding - Integer: Not used in the Container class istelf, distance between child widgets.
- background_image - Set this to a GuiImage or a resource location (simply a filename).
The image will be tiled over the background area.
@@ -642,9 +641,9 @@
to make the widget transparent.
- children - Just contains the list of contained child widgets. Do NOT modify.
"""
-
+
ATTRIBUTES = Widget.ATTRIBUTES + [ IntAttr('padding'), Attr('background_image'), BoolAttr('opaque'),PointAttr('margins') ]
-
+
def __init__(self,padding=5,margins=(5,5),_real_widget=None, **kwargs):
self.real_widget = _real_widget or fife.Container()
self.children = []
@@ -690,12 +689,12 @@
image = self._background_image
if image is None:
return
-
+
back_w,back_h = self.width, self.height
image_w, image_h = image.getWidth(), image.getHeight()
map(self.real_widget.remove,self._background)
-
+
# Now tile the background over the widget
self._background = []
icon = fife.Icon(image)
@@ -724,7 +723,7 @@
if not isinstance(image, fife.GuiImage):
image = get_manager().loadImage(image)
self._background_image = image
-
+
def getBackgroundImage(self): return self._background_image
background_image = property(getBackgroundImage,setBackgroundImage)
@@ -739,15 +738,15 @@
This class is at the core of the layout engine. The two MixIn classes L{VBoxLayoutMixin}
and L{HBoxLayoutMixin} specialise on this by reimplementing the C{resizeToContent} and
the C{expandContent} methods.
-
+
At the core the layout engine works in two passes:
-
+
Before a root widget loaded by the XML code is shown, its resizeToContent method
is called recursively (walking the widget containment relation in post order).
This shrinks all HBoxes and VBoxes to their minimum heigt and width.
After that the expandContent method is called recursively in the same order,
which will re-align the widgets if there is space left AND if a Spacer is contained.
-
+
Inside bare Container instances (without a Layout MixIn) absolute positioning
can be used.
"""
@@ -766,7 +765,6 @@
def ydelta(self,widget):return 0
def _adjustHeight(self):
-
if self.align[1] == AlignTop:return #dy = 0
if self.align[1] == AlignBottom:
y = self.height - self.childarea[1] - self.border_size - self.margins[1]
@@ -780,7 +778,6 @@
pass
def _adjustWidth(self):
-
if self.align[0] == AlignLeft:return #dx = 0
if self.align[0] == AlignRight:
x = self.width - self.childarea[0] - self.border_size - self.margins[0]
@@ -793,11 +790,11 @@
def _expandWidthSpacer(self):
x = self.border_size + self.margins[0]
xdelta = map(self.xdelta,self.children)
-
+
for widget in self.children[:self.spacer.index]:
widget.x = x
x += xdelta.pop(0)
-
+
x = self.width - sum(xdelta) - self.border_size - self.margins[0]
for widget in self.children[self.spacer.index:]:
widget.x = x
@@ -806,11 +803,11 @@
def _expandHeightSpacer(self):
y = self.border_size + self.margins[1]
ydelta = map(self.ydelta,self.children)
-
+
for widget in self.children[:self.spacer.index]:
widget.y = y
y += ydelta.pop(0)
-
+
y = self.height - sum(ydelta) - self.border_size - self.margins[1]
for widget in self.children[self.spacer.index:]:
widget.y = y
@@ -833,7 +830,7 @@
widget.y = y
widget.width = max_w
y += widget.height + self.padding
-
+
#Add the padding for the spacer.
if self.spacer:
y += self.padding
@@ -867,7 +864,7 @@
widget.y = y
widget.height = max_h
x += widget.width + self.padding
-
+
#Add the padding for the spacer.
if self.spacer:
x += self.padding
@@ -875,7 +872,7 @@
self.width = x + self.margins[0] - self.padding
self.height = max_h + 2*y
self.childarea = x - self.margins[0] - self.padding, max_h
-
+
self._adjustHeight()
self._adjustWidth()
@@ -889,11 +886,11 @@
class VBox(VBoxLayoutMixin,Container):
"""
A vertically aligned box - for containement of child widgets.
-
+
Widgets added to this container widget, will layout on top of each other.
Also the minimal width of the container will be the maximum of the minimal
widths of the contained widgets.
-
+
The default alignment is to the top. This can be changed by adding a Spacer
to the widget at any point (but only one!). The spacer will expand, so that
widgets above the spacer are aligned to the top, while widgets below the spacer
@@ -907,7 +904,7 @@
class HBox(HBoxLayoutMixin,Container):
"""
A horizontally aligned box - for containement of child widgets.
-
+
Please see L{VBox} for details - just change the directions :-).
"""
def __init__(self,padding=5,**kwargs):
@@ -917,16 +914,16 @@
class Window(VBoxLayoutMixin,Container):
"""
A L{VBox} with a draggable title bar aka a window
-
+
New Attributes
==============
-
+
- title: The Caption of the window
- titlebar_height: The height of the window title bar
"""
-
+
ATTRIBUTES = Container.ATTRIBUTES + [ Attr('title'), IntAttr('titlebar_height') ]
-
+
def __init__(self,title="title",titlebar_height=0,**kwargs):
super(Window,self).__init__(_real_widget = fife.Window(), **kwargs)
if titlebar_height == 0:
@@ -941,7 +938,7 @@
def _getTitle(self): return self.real_widget.getCaption()
def _setTitle(self,text): self.real_widget.setCaption(text)
title = property(_getTitle,_setTitle)
-
+
def _getTitleBarHeight(self): return self.real_widget.getTitleBarHeight()
def _setTitleBarHeight(self,h): self.real_widget.setTitleBarHeight(h)
titlebar_height = property(_getTitleBarHeight,_setTitleBarHeight)
@@ -961,25 +958,25 @@
"""
The base class for widgets which display a string - L{Label},L{ClickLabel},L{Button}, etc.
Do not use directly.
-
+
New Attributes
==============
-
+
- text: The text (depends on actual widget)
-
+
Data
====
-
+
The text can be set via the L{distributeInitialData} method.
"""
-
+
ATTRIBUTES = Widget.ATTRIBUTES + [Attr('text')]
-
+
def __init__(self, text = "",**kwargs):
self.margins = (5,5)
self.text = text
super(BasicTextWidget,self).__init__(**kwargs)
-
+
# Prepare Data collection framework
self.accepts_initial_data = True
self._realSetInitialData = self._setText
@@ -995,10 +992,10 @@
class Icon(Widget):
"""
An image icon.
-
+
New Attributes
==============
-
+
- image: String or GuiImage: The source location of the Image or a direct GuiImage
"""
ATTRIBUTES = Widget.ATTRIBUTES + [Attr('image')]
@@ -1034,20 +1031,20 @@
class Label(BasicTextWidget):
"""
A basic label - displaying a string.
-
+
Also allows text wrapping.
-
+
New Attributes
==============
-
+
- wrap_text: Boolean: Enable/Disable automatic text wrapping. Disabled by default.
Currently to actually see text wrapping you have to explicitly set a max_size with
the desired width of the text, as the layout engine is not capable of deriving
the maximum width from a parent container.
"""
-
+
ATTRIBUTES = BasicTextWidget.ATTRIBUTES + [BoolAttr('wrap_text')]
-
+
def __init__(self,wrap_text=False,**kwargs):
self.real_widget = fife.Label("")
self.wrap_text = wrap_text
@@ -1085,37 +1082,37 @@
self.btn = btn
self.entercb = None
self.exitcb = None
-
+
def mouseEntered(self, btn):
if self.entercb:
self.entercb(self.btn)
-
+
def mouseExited(self, btn):
if self.exitcb:
self.exitcb(self.btn)
-
+
class ImageButton(BasicTextWidget):
"""
A basic push button with three different images for the up, down and hover state.
-
+
B{Work in progress.}
-
+
New Attributes
==============
-
+
- up_image: String: The source location of the Image for the B{unpressed} state.
- down_image: String: The source location of the Image for the B{pressed} state.
- hover_image: String: The source location of the Image for the B{unpressed hovered} state.
"""
-
+
ATTRIBUTES = BasicTextWidget.ATTRIBUTES + [Attr('up_image'),Attr('down_image'),PointAttr('offset'),Attr('helptext'),Attr('hover_image')]
-
+
def __init__(self,up_image="",down_image="",hover_image="",offset=(0,0),**kwargs):
self.real_widget = fife.TwoButton()
super(ImageButton,self).__init__(**kwargs)
self.listener = ImageButtonListener(self)
self.real_widget.setListener(self.listener)
-
+
self.up_image = up_image
self.down_image = down_image
self.hover_image = hover_image
@@ -1150,7 +1147,7 @@
self._hoverimage = _DummyImage()
def _getHoverImage(self): return self._hoverimage_source
hover_image = property(_getHoverImage,_setHoverImage)
-
+
def _setOffset(self, offset):
self.real_widget.setDownOffset(offset[0], offset[1])
def _getOffset(self):
@@ -1162,7 +1159,7 @@
def _getHelpText(self):
return self.real_widget.getHelpText()
helptext = property(_getHelpText,_setHelpText)
-
+
def resizeToContent(self):
self.height = max(self._upimage.getHeight(),self._downimage.getHeight(),self._hoverimage.getHeight()) + self.margins[1]*2
self.width = max(self._upimage.getWidth(),self._downimage.getWidth(),self._hoverimage.getWidth()) + self.margins[1]*2
@@ -1173,32 +1170,32 @@
callback should have form of function(button)
'''
self.listener.entercb = cb
-
+
def setExitCallback(self, cb):
'''
Callback is called when mouse enters the area of ImageButton
callback should have form of function(button)
'''
self.listener.exitcb = cb
-
+
class CheckBox(BasicTextWidget):
"""
A basic checkbox.
-
+
New Attributes
==============
-
+
- marked: Boolean value, whether the checkbox is checked or not.
-
+
Data
====
The marked status can be read and set via L{distributeData} and L{collectData}
"""
-
+
ATTRIBUTES = BasicTextWidget.ATTRIBUTES + [BoolAttr('marked')]
-
+
def __init__(self,**kwargs):
self.real_widget = fife.CheckBox()
super(CheckBox,self).__init__(**kwargs)
@@ -1207,9 +1204,9 @@
self.accepts_data = True
self._realGetData = self._isMarked
self._realSetData = self._setMarked
-
+
# Initial data stuff inherited.
-
+
def _isMarked(self): return self.real_widget.isSelected()
def _setMarked(self,mark): self.real_widget.setSelected(mark)
marked = property(_isMarked,_setMarked)
@@ -1217,21 +1214,21 @@
class RadioButton(BasicTextWidget):
"""
A basic radiobutton (an exclusive checkbox).
-
+
New Attributes
==============
-
+
- marked: Boolean: Whether the checkbox is checked or not.
- group: String: All RadioButtons with the same group name
can only be checked exclusively.
-
+
Data
====
The marked status can be read and set via L{distributeData} and L{collectData}
"""
-
+
ATTRIBUTES = BasicTextWidget.ATTRIBUTES + [BoolAttr('marked'),Attr('group')]
-
+
def __init__(self,group="_no_group_",**kwargs):
self.real_widget = fife.RadioButton()
super(RadioButton,self).__init__(**kwargs)
@@ -1242,9 +1239,9 @@
self.accepts_data = True
self._realGetData = self._isMarked
self._realSetData = self._setMarked
-
+
# Initial data stuff inherited.
-
+
def _isMarked(self): return self.real_widget.isSelected()
def _setMarked(self,mark): self.real_widget.setSelected(mark)
marked = property(_isMarked,_setMarked)
@@ -1270,7 +1267,7 @@
self.pop()
def getNumberOfElements(self):
return len(self)
-
+
def getElementAt(self, i):
i = max(0,min(i,len(self) - 1))
return str(self[i])
@@ -1279,16 +1276,16 @@
"""
A basic list box widget for displaying lists of strings. It makes most sense to wrap
this into a L{ScrollArea}.
-
+
New Attributes
==============
-
+
- items: A List of strings. This can be treated like an ordinary python list.
but only strings are allowed.
- selected: The index of the selected item in the list. Starting from C{0} to C{len(items)-1}.
A negative value indicates, that no item is selected.
- selected_item: The selected string itself, or C{None} - if no string is selected.
-
+
Data
====
The selected attribute can be read and set via L{distributeData} and L{collectData}.
@@ -1302,7 +1299,7 @@
# Prepare Data collection framework
self.accepts_initial_data = True
self._realSetInitialData = self._setItems
-
+
self.accepts_data = True
self._realSetData = self._setSelected
self._realGetData = self._getSelected
@@ -1319,7 +1316,7 @@
def _setItems(self,items):
# Note we cannot use real_widget.setListModel
# for some reason ???
-
+
# Also self assignment can kill you
if id(items) != id(self._items):
self._items.clear()
@@ -1339,16 +1336,16 @@
class DropDown(Widget):
"""
A dropdown or combo box widget for selecting lists of strings.
-
+
New Attributes
==============
-
+
- items: A List of strings. This can be treated like an ordinary python list.
but only strings are allowed.
- selected: The index of the selected item in the list. Starting from C{0} to C{len(items)-1}.
A negative value indicates, that no item is selected.
- selected_item: The selected string itself, or C{None} - if no string is selected.
-
+
Data
====
The selected attribute can be read and set via L{distributeData} and L{collectData}.
@@ -1362,7 +1359,7 @@
# Prepare Data collection framework
self.accepts_initial_data = True
self._realSetInitialData = self._setItems
-
+
self.accepts_data = True
self._realSetData = self._setSelected
self._realGetData = self._getSelected
@@ -1379,13 +1376,13 @@
def _setItems(self,items):
# Note we cannot use real_widget.setListModel
# for some reason ???
-
+
# Also self assignment can kill you
if id(items) != id(self._items):
self._items.clear()
self._items.extend(items)
items = property(_getItems,_setItems)
-
+
def _getSelected(self): return self.real_widget.getSelected()
def _setSelected(self,index): self.real_widget.setSelected(index)
selected = property(_getSelected,_setSelected)
@@ -1398,13 +1395,13 @@
class TextBox(Widget):
"""
An editable B{multiline} text edit widget.
-
+
New Attributes
==============
-
+
- text: The text in the TextBox.
- filename: A write-only attribute - assigning a filename will cause the widget to load it's text from it.
-
+
Data
====
The text can be read and set via L{distributeData} and L{collectData}.
@@ -1452,12 +1449,12 @@
class TextField(Widget):
"""
An editable B{single line} text edit widget.
-
+
New Attributes
==============
-
+
- text: The text in the TextBox.
-
+
Data
====
The text can be read and set via L{distributeData} and L{collectData}.
@@ -1495,18 +1492,18 @@
class ScrollArea(Widget):
"""
A wrapper around another (content) widget.
-
+
New Attributes
==============
-
+
- content: The wrapped widget.
- vertical_scrollbar: Boolean: Set this to False to hide the Vertcial scrollbar
- horizontal_scrollbar: Boolean: Set this to False to hide the Horizontal scrollbar
-
+
"""
-
+
ATTRIBUTES = Widget.ATTRIBUTES + [ BoolAttr("vertical_scrollbar"),BoolAttr("horizontal_scrollbar") ]
-
+
def __init__(self,**kwargs):
self.real_widget = fife.ScrollArea()
self._content = None
@@ -1541,7 +1538,7 @@
if visibility:
return fife.ScrollArea.SHOW_AUTO
return fife.ScrollArea.SHOW_NEVER
-
+
def _scrollPolicyToVisibility(self,policy):
if policy == fife.ScrollArea.SHOW_NEVER:
return False
@@ -1549,13 +1546,13 @@
def _setHorizontalScrollbar(self,visibility):
self.real_widget.setHorizontalScrollPolicy( self._visibilityToScrollPolicy(visibility) )
-
+
def _setVerticalScrollbar(self,visibility):
self.real_widget.setVerticalScrollPolicy( self._visibilityToScrollPolicy(visibility) )
def _getHorizontalScrollbar(self):
return self._scrollPolicyToVisibility( self.real_widget.getHorizontalScrollPolicy() )
-
+
def _getVerticalScrollbar(self):
return self._scrollPolicyToVisibility( self.real_widget.getVerticalScrollPolicy() )
@@ -1566,13 +1563,13 @@
class Spacer(object):
""" A spacer represents expandable 'whitespace' in the GUI.
-
+
In a XML file you can get this by adding a inside a VBox or
HBox element (Windows implicitly are VBox elements).
-
+
The effect is, that elements before the spacer will be left (top)
and elements after the spacer will be right (bottom) aligned.
-
+
There can only be one spacer in VBox (HBox).
"""
def __init__(self,parent=None,**kwargs):
@@ -1580,7 +1577,7 @@
def __str__(self):
return "Spacer(parent.name='%s')" % getattr(self._parent,'name','None')
-
+
def __repr__(self):
return "" % (getattr(self._parent,'name','None'),id(self))
@@ -1594,18 +1591,18 @@
"VBox" : VBox,
"HBox" : HBox,
"ScrollArea" :ScrollArea,
-
+
# Simple Widgets
"Icon" : Icon,
"Label" : Label,
"ClickLabel" : ClickLabel,
-
+
# Button Widgets
"Button" : Button,
"CheckBox" : CheckBox,
"RadioButton" : RadioButton,
"ImageButton" : ImageButton,
-
+
#Complexer Widgets / Text io
"TextField" : TextField,
"TextBox" : TextBox,
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/pythonize.py
--- a/engine/extensions/pythonize.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/pythonize.py Thu Aug 07 15:46:46 2008 +0000
@@ -51,7 +51,7 @@
except TypeError, e:
#print func, e
return False
-
+
def createNames(name):
for prefix in ('get', 'is', 'are'):
if name.startswith(prefix):
@@ -60,7 +60,7 @@
settername = 'set' + new_name
propertyname = new_name[0].lower() + new_name[1:]
return settername, propertyname
-
+
getter = re.compile(r"^(get|are|is)[A-Z]")
for class_ in classes:
methods = [(name,attr) for name,attr in class_.__dict__.items()
@@ -75,7 +75,7 @@
#print name, settername, "--->",propertyname,'(',method,',',setter,')'
setattr(class_,propertyname,property(method,setter))
if not getters: continue
-
+
# We need to override the swig setattr function
# to get properties to work.
class_._property_names = set([name for name,method in getters])
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/savers.py
--- a/engine/extensions/savers.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/savers.py Thu Aug 07 15:46:46 2008 +0000
@@ -72,7 +72,7 @@
def write_imports(self, map, importList):
for importdir in importList:
self.write_importdir(root_subfile(map.getResourceFile(), importdir))
-
+
imports = []
for layer in map.getLayers():
for instance in layer.getInstances():
@@ -117,14 +117,14 @@
self.xmlout.startElementNS((None, 'import'), 'import', attrs)
self.xmlout.endElementNS((None, 'import'), 'import')
self.file.write('\n')
-
+
def pathing_val_to_str(self, val):
if val == fife.CELL_EDGES_AND_DIAGONALS:
return "cell_edges_and_diagonals"
if val == fife.FREEFORM:
return "freeform"
return "cell_edges_only"
-
+
def write_layers(self, map):
for layer in map.getLayers():
cellgrid = layer.getCellGrid()
@@ -189,7 +189,7 @@
self.xmlout.startElementNS((None, 'i'), 'i', attrs)
self.xmlout.endElementNS((None, 'i'), 'i')
self.file.write('\n')
-
+
self.endElement('instances')
# Save the linked camera of a map.
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/serializers/__init__.py
--- a/engine/extensions/serializers/__init__.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/serializers/__init__.py Thu Aug 07 15:46:46 2008 +0000
@@ -34,16 +34,16 @@
NOTE: masterfile is expected to be *file*, not directory. subfile can be either
'''
s = '/'
-
+
masterfile = norm_path(os.path.abspath(masterfile))
subfile = norm_path(os.path.abspath(subfile))
-
+
master_fragments = masterfile.split(s)
sub_fragments = subfile.split(s)
-
+
master_leftovers = []
sub_leftovers = []
-
+
for i in xrange(len(master_fragments)):
try:
if master_fragments[i] == sub_fragments[i]:
@@ -51,7 +51,7 @@
sub_leftovers = sub_fragments[i+1:]
except IndexError:
break
-
+
pathstr = ''
for f in master_leftovers[:-1]:
pathstr += '..' + s
@@ -67,12 +67,12 @@
NOTE: masterfile is expected to be *file*, not directory. subfile can be either
'''
s = '/'
-
+
masterfile = norm_path(os.path.abspath(masterfile)).split(s)[:-1]
subfile = norm_path(os.path.abspath( s.join(masterfile) + s + subfile ))
masterfile = norm_path(os.getcwd()) + s + 'foo.bar' # cheat a little to satisfy root_subfile
return root_subfile(masterfile, subfile)
-
+
def norm_path(path):
'''
Makes the path use '/' delimited separators. FIFE always uses these delimiters, but some os-related
@@ -80,5 +80,5 @@
'''
if os.path.sep == '/':
return path
-
+
return '/'.join(path.split(os.path.sep))
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/serializers/xmlanimation.py
--- a/engine/extensions/serializers/xmlanimation.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/serializers/xmlanimation.py Thu Aug 07 15:46:46 2008 +0000
@@ -9,7 +9,7 @@
self.thisown = 0
self.filename = ''
self.node = None
-
+
def loadResource(self, location):
self.filename = location.getFilename()
return self.do_load_resource()
@@ -19,17 +19,17 @@
f.thisown = 1
tree = ET.parse(f)
self.node = tree.getroot()
-
+
animation = fife.Animation()
common_frame_delay = int(self.node.get('delay', 0))
x_offset = int(self.node.get('x_offset', 0))
y_offset = int(self.node.get('y_offset', 0))
animation.setActionFrame(int(self.node.get('action', 0)))
-
+
frames = self.node.findall('frame')
if not frames:
raise InvalidFormat('animation without s')
-
+
for frame in frames:
source = frame.get('source')
if not source:
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/serializers/xmlmap.py
--- a/engine/extensions/serializers/xmlmap.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/serializers/xmlmap.py Thu Aug 07 15:46:46 2008 +0000
@@ -44,7 +44,7 @@
if not format == FORMAT: self._err(''.join(['This file has format ', format, ' but this loader has format ', FORMAT]))
if not id: self._err('Map declared without an identifier.')
-
+
map = None
try:
self.map = self.model.createMap(str(id))
@@ -120,7 +120,7 @@
print e.getMessage()
print 'The layer ' + str(id) + ' already exists! Ignoring this layer.'
continue
-
+
strgy = fife.CELL_EDGES_ONLY
if pathing == "cell_edges_and_diagonals":
strgy = fife.CELL_EDGES_AND_DIAGONALS
@@ -129,7 +129,7 @@
layer_obj.setPathingStrategy(strgy)
self.parse_instances(layer, layer_obj)
-
+
def parse_instances(self, layerelt, layer):
instelt = layerelt.find('instances')
@@ -179,19 +179,19 @@
self.y = y
else:
y = self.y
-
+
if z:
z = float(z)
else:
z = 0.0
-
+
if not id:
id = ''
else:
id = str(id)
inst = layer.createInstance(object, fife.ExactModelCoordinate(x,y,z), str(id))
-
+
rotation = instance.get('r')
if not rotation:
rotation = instance.get('rotation')
@@ -204,7 +204,7 @@
else:
rotation = int(rotation)
inst.setRotation(rotation)
-
+
fife.InstanceVisual.create(inst)
if (stackpos):
inst.get2dGfxVisual().setStackPosition(int(stackpos))
diff -r 6e1fd3571440 -r 9a1529f9625e engine/extensions/serializers/xmlobject.py
--- a/engine/extensions/serializers/xmlobject.py Wed Aug 06 22:35:27 2008 +0000
+++ b/engine/extensions/serializers/xmlobject.py Thu Aug 07 15:46:46 2008 +0000
@@ -28,16 +28,16 @@
isobjectfile = True
f = self.vfs.open(self.filename)
f.thisown = 1
-
+
obj_identifier = ''
try:
s = f.readString(len(obj_identifier))
except fife.IndexOverflow:
isobjectfile = False
-
+
if isobjectfile and s != obj_identifier:
isobjectfile = False
-
+
if not isobjectfile:
raise WrongFileType('Tried to open non-object file %s with XMLObjectLoader.' % self.filename)
self.do_load_resource(f)
@@ -51,7 +51,7 @@
def parse_object(self, object):
if self.node.tag != 'object':
raise InvalidFormat('Expected