From 7e3f193d60e50d813ebf52a9709f6c0e1fc27d7d Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Fri, 2 Nov 2012 18:06:35 +0100 Subject: [PATCH] screen: add new screen module, that can be used for simulating different screen sizes/density/dpi. --- kivy/__init__.py | 4 ++ kivy/modules/__init__.py | 74 ++++++++++++++++++----------- kivy/modules/screen.py | 100 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 kivy/modules/screen.py diff --git a/kivy/__init__.py b/kivy/__init__.py index e70e3e316..14f989c39 100644 --- a/kivy/__init__.py +++ b/kivy/__init__.py @@ -369,6 +369,10 @@ if not environ.get('KIVY_DOC_INCLUDE'): Logger.info('Core: Kivy configuration saved.') sys.exit(0) + # configure all activated modules + from kivy.modules import Modules + Modules.configure() + # android hooks: force fullscreen and add android touch input provider if platform() == 'android': from kivy.config import Config diff --git a/kivy/modules/__init__.py b/kivy/modules/__init__.py index 864228dbb..1143c1f94 100644 --- a/kivy/modules/__init__.py +++ b/kivy/modules/__init__.py @@ -113,7 +113,9 @@ class ModuleBase: def import_module(self, name): try: - module = __import__(name=name, fromlist='.') + modname = 'kivy.modules.{0}'.format(name) + module = __import__(name=modname) + module = sys.modules[modname] except ImportError: Logger.exception('Modules: unable to import <%s>' % name) raise @@ -130,38 +132,17 @@ class ModuleBase: def activate_module(self, name, win): '''Activate a module on a window''' - if not name in self.mods: + if name not in self.mods: Logger.warning('Modules: Module <%s> not found' % name) return - if not 'module' in self.mods[name]: - try: - self.import_module(name) - except ImportError: - return - module = self.mods[name]['module'] if not self.mods[name]['activated']: - - # convert configuration like: - # -m mjpegserver:port=8080,fps=8 - # and pass it in context.config token - config = dict() - - args = Config.get('modules', name) - if args != '': - values = Config.get('modules', name).split(',') - for value in values: - x = value.split('=', 1) - if len(x) == 1: - config[x[0]] = True - else: - config[x[0]] = x[1] - - msg = 'Modules: Start <%s> with config %s' % (name, str(config)) + context = self.mods[name]['context'] + msg = 'Modules: Start <{0}> with config {1}'.format( + name, context) Logger.debug(msg) - self.mods[name]['context'].config = config - module.start(win, self.mods[name]['context']) + module.start(win, context) def deactivate_module(self, name, win): '''Deactivate a module from a window''' @@ -196,6 +177,45 @@ class ModuleBase: for name in modules_to_activate: self.activate_module(name, win) + def configure(self): + '''(internal) Configure all the modules before using it. + ''' + modules_to_configure = map(lambda x: x[0], Config.items('modules')) + for name in modules_to_configure: + if name not in self.mods: + Logger.warning('Modules: Module <%s> not found' % name) + continue + self._configure_module(name) + + def _configure_module(self, name): + if 'module' not in self.mods[name]: + try: + self.import_module(name) + except ImportError: + return + + # convert configuration like: + # -m mjpegserver:port=8080,fps=8 + # and pass it in context.config token + config = dict() + + args = Config.get('modules', name) + if args != '': + values = Config.get('modules', name).split(',') + for value in values: + x = value.split('=', 1) + if len(x) == 1: + config[x[0]] = True + else: + config[x[0]] = x[1] + + self.mods[name]['context'].config = config + + # call configure if module have one + if hasattr(self.mods[name]['module'], 'configure'): + self.mods[name]['module'].configure(config) + + def usage_list(self): print print 'Available modules' diff --git a/kivy/modules/screen.py b/kivy/modules/screen.py new file mode 100644 index 000000000..71ba23d48 --- /dev/null +++ b/kivy/modules/screen.py @@ -0,0 +1,100 @@ +''' +Screen +====== + +This module change some environement and configuration to match the density / +dpi / screensize of a specific devices. + +To see a list of the available screenid, just run:: + + python main.py -m screen + +Simulate a medium-density screen as Motolora Droid 2:: + + python main.py -m screen,droid2 + +Simulate a high-density screen as HTC One X, in portrait:: + + python main.py -m screen,onex,portrait + +Simulate the iPad 2 screen:: + + python main.py -m screen,ipad +''' + +import sys +from os import environ +from kivy.config import Config +from kivy.logger import Logger + +# taken from http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density +devices = { + # device: (name, width, height, dpi, density) + 'onex': ('HTC One X', 1280, 720, 312, 2), + 's3': ('Galaxy SIII', 1280, 720, 306, 2), + 'droid2': ('Motolora Droid 2', 854, 480, 240, 1.5), + 'xoom': ('Motolora Xoom', 1280, 800, 149, 1), + 'ipad': ('iPad (1 and 2)', 1024, 768, 132, 1), + 'ipad3': ('iPad 3', 2048, 1536, 264, 2), + 'iphone4': ('iPhone 4', 640, 960, 326, 2), + 'iphone5': ('iPhone 5', 640, 1136, 326, 2), +} + + +def start(win, ctx): + pass + + +def stop(win, ctx): + pass + + +def apply_device(device, scale, orientation): + name, width, height, dpi, density = devices[device] + if orientation == 'portrait': + width, height = height, width + Logger.info('Screen: Apply screen settings for {0}'.format(name)) + Logger.info('Screen: size={0}x{1} dpi={2} density={3} ' + 'orientation={4}'.format(width, height, dpi, density, orientation)) + environ['KIVY_METRICS_DENSITY'] = str(density) + environ['KIVY_DPI'] = str(dpi) + Config.set('graphics', 'width', str(width)) + Config.set('graphics', 'height', str(height)) + Config.set('graphics', 'fullscreen', '0') + Config.set('graphics', 'show_mousecursor', '1') + + +def usage(device=None): + if device: + Logger.error('Screen: The specified device ({0}) is unknow.', + device) + print '\nModule usage: python main.py -m screen,deviceid[,orientation]\n' + print 'Availables devices:\n' + print '{0:12} {1:<22} {2:<8} {3:<8} {4:<5} {5:<8}'.format( + 'Device ID', 'Name', 'Width', 'Height', 'DPI', 'Density') + for device, info in devices.iteritems(): + print '{0:12} {1:<22} {2:<8} {3:<8} {4:<5} {5:<8}'.format( + device, *info) + print '\n' + print 'Simulate a medium-density screen as Motolora Droid 2:\n' + print ' python main.py -m screen,droid2\n' + print 'Simulate a high-density screen as HTC One X, in portrait:\n' + print ' python main.py -m screen,onex,portrait\n' + print 'Simulate the iPad 2 screen\n' + print ' python main.py -m screen,ipad\n' + sys.exit(1) + + +def configure(ctx): + scale = ctx.pop('scale', None) + orientation = 'landscape' + ctx.pop('landscape', None) + if ctx.pop('portrait', None): + orientation = 'portrait' + if not ctx: + return usage(None) + device = ctx.keys()[0] + if device not in devices: + return usage('') + apply_device(device, scale, orientation) +