diff --git a/doc/autobuild.py b/doc/autobuild.py index 3f1851211..5db980515 100644 --- a/doc/autobuild.py +++ b/doc/autobuild.py @@ -23,6 +23,7 @@ import kivy # force loading of kivy modules import kivy.app +import kivy.metrics import kivy.atlas import kivy.core.audio import kivy.core.camera diff --git a/doc/sources/guide/environment.rst b/doc/sources/guide/environment.rst index b98f4bb2b..db7fe7ec3 100644 --- a/doc/sources/guide/environment.rst +++ b/doc/sources/guide/environment.rst @@ -32,11 +32,6 @@ KIVY_NO_FILELOG KIVY_NO_CONSOLELOG If set, logs will be not print on the console -KIVY_DPI - If set, the value will be used instead of the value returned by the window. - - .. versionadded:: 1.4.0 - Path control ------------ @@ -101,3 +96,22 @@ KIVY_CLIPBOARD Values: pygame, dummy +Metrics +------- + +KIVY_DPI + If set, the value will be used for :data:`Metrics.dpi`. + + .. versionadded:: 1.4.0 + +KIVY_METRICS_DENSITY + If set, the value will be used for :data:`Metrics.density`. + + .. versionadded:: 1.5.0 + +KIVY_METRICS_FONTSCALE + + If set, the value will be used for :data:`Metrics.fontscale`. + + .. versionadded:: 1.5.0 + diff --git a/examples/demo/kivycatalog/kivycatalog.kv b/examples/demo/kivycatalog/kivycatalog.kv index 7b292bd11..c2784fdc5 100644 --- a/examples/demo/kivycatalog/kivycatalog.kv +++ b/examples/demo/kivycatalog/kivycatalog.kv @@ -137,11 +137,11 @@ TextInput: id:info_lbl readonly: True - font_size: 11 + font_size: '11sp' background_color: (0, 0, 0, 1) foreground_color: (1, 1, 1, 1) opacity:0 size_hint: 1, None text_size: self.size height: '150pt' - top: 0 \ No newline at end of file + top: 0 diff --git a/examples/demo/showcase/main.py b/examples/demo/showcase/main.py index 0b50230dc..db966fcc4 100644 --- a/examples/demo/showcase/main.py +++ b/examples/demo/showcase/main.py @@ -250,16 +250,16 @@ class ShowcaseApp(App): return col def show_popup(self): - btnclose = Button(text='Close this popup', size_hint_y=None, height=50) + btnclose = Button(text='Close this popup', size_hint_y=None, height='50sp') content = BoxLayout(orientation='vertical') content.add_widget(Label(text='Hello world')) content.add_widget(btnclose) popup = Popup(content=content, title='Modal popup example', - size_hint=(None, None), size=(300, 300), + size_hint=(None, None), size=('300dp', '300dp'), auto_dismiss=False) btnclose.bind(on_release=popup.dismiss) button = Button(text='Open popup', size_hint=(None, None), - size=(150, 70)) + size=('150sp', '70dp')) button.bind(on_release=popup.open) popup.open() col = AnchorLayout() diff --git a/examples/demo/showcase/showcase.kv b/examples/demo/showcase/showcase.kv index 28837ce5c..9b6cbb7fd 100644 --- a/examples/demo/showcase/showcase.kv +++ b/examples/demo/showcase/showcase.kv @@ -14,17 +14,18 @@ orientation: 'vertical' BoxLayout: - padding: 10 - spacing: 10 + padding: '10dp' + spacing: '10dp' size_hint: 1, None pos_hint: {'top': 1} - height: 44 + height: '44dp' Image: size_hint: None, None - size: 24, 24 - source: 'data/logo/kivy-icon-24.png' + size: '24dp', '24dp' + source: 'data/logo/kivy-icon-64.png' + mipmap: True Label: - height: 24 + height: '24dp' text_size: self.width, None color: (1, 1, 1, .8) text: 'Kivy %s - Showcase' % kivy.__version__ @@ -55,7 +56,7 @@ [Title@Label] pos_hint: {'center_x': .5, 'y': .3} text: ctx.text - font_size: 22 + font_size: '29dp' Title: @@ -153,9 +154,9 @@ [HSeparator@Label]: size_hint_y: None - height: 45 + height: max(dp(45), self.texture_size[1] + dp(10)) text: ctx.text if 'text' in ctx else '' - text_size: self.size + text_size: self.width, None valign: 'middle' halign: 'center' canvas.before: @@ -257,18 +258,18 @@ TextInput: text: 'Monoline textinput' size_hint_y: None - height: 30 + height: sp(30) TextInput: text: 'This is a password' size_hint_y: None - height: 30 + height: sp(30) password: True TextInput: text: 'Readonly textinput' size_hint_y: None - height: 30 + height: sp(30) readonly: True TextInput: diff --git a/examples/demo/touchtracer/touchtracer.kv b/examples/demo/touchtracer/touchtracer.kv index b6326865b..259bb5329 100644 --- a/examples/demo/touchtracer/touchtracer.kv +++ b/examples/demo/touchtracer/touchtracer.kv @@ -10,17 +10,18 @@ size: self.size BoxLayout: - padding: 10 - spacing: 10 + padding: '10dp' + spacing: '10dp' size_hint: 1, None pos_hint: {'top': 1} - height: 44 + height: '44dp' Image: size_hint: None, None - size: 24, 24 - source: 'data/logo/kivy-icon-24.png' + size: '24dp', '24dp' + source: 'data/logo/kivy-icon-64.png' + mipmap: True Label: - height: 24 + height: '24dp' text_size: self.width, None color: (1, 1, 1, .8) text: 'Kivy %s - Touchtracer' % kivy.__version__ diff --git a/kivy/base.py b/kivy/base.py index d6a25620c..7e618b157 100644 --- a/kivy/base.py +++ b/kivy/base.py @@ -15,12 +15,10 @@ __all__ = ( 'stopTouchApp', ) -from os import environ from kivy.config import Config from kivy.logger import Logger from kivy.clock import Clock from kivy.event import EventDispatcher -from kivy.utils import platform, reify # private vars EventLoop = None @@ -106,32 +104,6 @@ class EventLoopBase(EventDispatcher): ''' return self.me_list - @reify - def dpi(self): - '''Return the DPI of the screen. Depending of the platform, the DPI can - be taken from the Window provider (Desktop mainly), or from - platform-specific module (like android/ios). - - On desktop, you can overload the value returned by the Window object - (96 by default), by setting the environ KIVY_DPI:: - - KIVY_DPI=200 python main.py - - .. versionadded:: 1.4.0 - ''' - custom_dpi = environ.get('KIVY_DPI') - if custom_dpi: - return float(custom_dpi) - - plat = platform() - if plat == 'android': - import android - return android.get_dpi() - - # for all other platforms.. - self.ensure_window() - return self.window.dpi - def ensure_window(self): '''Ensure that we have an window ''' diff --git a/kivy/core/text/markup.py b/kivy/core/text/markup.py index 3e9cc2199..abd41384f 100644 --- a/kivy/core/text/markup.py +++ b/kivy/core/text/markup.py @@ -140,7 +140,7 @@ class MarkupLabel(MarkupLabelBase): elif item[:6] == '[size=': item = item[6:-1] try: - if item[-2:] in ('px', 'pt', 'in', 'cm', 'mm'): + if item[-2:] in ('px', 'pt', 'in', 'cm', 'mm', 'dp', 'sp'): size = dpi2px(item[:-2], item[-2:]) else: size = int(item) diff --git a/kivy/data/style.kv b/kivy/data/style.kv index b705bc70a..1fe843cb9 100644 --- a/kivy/data/style.kv +++ b/kivy/data/style.kv @@ -109,7 +109,7 @@ background_normal: 'atlas://data/images/defaulttheme/tab_btn' background_down: 'atlas://data/images/defaulttheme/tab_btn_pressed' border: (8, 8, 8, 8) - font_size: 11 + font_size: '15sp' : @@ -167,7 +167,7 @@ : width: self.texture_size[0] - height: max(self.texture_size[1], 24) + height: max(self.texture_size[1] + dp(10), dp(24)) text_size: self.width, None @@ -252,7 +252,7 @@ orientation: 'horizontal' size_hint_y: None - height: 24 + height: '24sp' # Don't allow expansion of the ../ node is_leaf: not ctx.isdir or ctx.name.endswith('..' + ctx.sep) or self.locked on_touch_down: self.collide_point(*args[1].pos) and ctx.controller().entry_touched(self, args[1]) @@ -260,12 +260,13 @@ BoxLayout: pos: root.pos Label: - text_size: self.size + id: filename + text_size: self.width, None halign: 'left' shorten: True text: unicode(ctx.name) Label: - text_size: self.size + text_size: self.width, None size_hint_x: None halign: 'right' text: unicode(ctx.get_nice_size()) @@ -291,8 +292,8 @@ width: scrollview.width size_hint_y: None height: self.minimum_height - spacing: 10 - padding: 10 + spacing: '10dp' + padding: '10dp' [FileIconEntry@Widget]: locked: False @@ -302,6 +303,7 @@ on_touch_down: self.collide_point(*args[1].pos) and ctx.controller().entry_touched(self, args[1]) on_touch_up: self.collide_point(*args[1].pos) and ctx.controller().entry_released(self, args[1]) + size: '100dp', '100dp' canvas: Color: @@ -313,22 +315,22 @@ source: 'atlas://data/images/defaulttheme/filechooser_selected' Image: - size: 48, 48 + size: '48dp', '48dp' source: 'atlas://data/images/defaulttheme/filechooser_%s' % ('folder' if ctx.isdir else 'file') - pos: root.x + 24, root.y + 40 + pos: root.x + dp(24), root.y + dp(40) Label: text: unicode(ctx.name) text_size: (root.width, self.height) halign: 'center' shorten: True - size: 100, 16 - pos: root.x, root.y + 16 + size: '100dp', '16dp' + pos: root.x, root.y + dp(16) Label: text: unicode(ctx.get_nice_size()) - font_size: 8 + font_size: '11sp' color: .8, .8, .8, 1 - size: 100, 16 + size: '100dp', '16sp' pos: root.pos halign: 'center' @@ -358,7 +360,7 @@ size_hint_y: None height: self.texture_size[1] y: pb.center_y - self.height - 8 - font_size: 10 + font_size: '13sp' color: (.8, .8, .8, .8) AnchorLayout: @@ -500,7 +502,7 @@ : size_hint: .25, None - height: max(50, labellayout.height) + height: labellayout.texture_size[1] + dp(10) content: content canvas: Color: @@ -518,13 +520,12 @@ pos: root.pos Label: - size_hint: .66, None + size_hint_x: .66 id: labellayout markup: True - text: '{0}\n[size=10pt][color=999999]{1}[/color][/size]'.format(root.title or '', root.desc or '') - font_size: '11.5pt' + text: '{0}\n[size=13sp][color=999999]{1}[/color][/size]{2}'.format(root.title or '', root.desc or '', self.font_size) + font_size: '15sp' text_size: self.width - 32, None - height: self.texture_size[1] + 10 BoxLayout: id: content @@ -542,26 +543,26 @@ Label: text: str(root.value) pos: root.pos - font_size: '11.5pt' + font_size: '15sp' : Label: text: str(root.value) pos: root.pos - font_size: '11.5pt' + font_size: '15sp' : Label: text: str(root.value) pos: root.pos - font_size: '11.5pt' + font_size: '15sp' : text_size: self.width - 32, None size_hint_y: None - height: max(50, self.texture_size[1] + 20) + height: max(dp(20), self.texture_size[1] + dp(20)) color: (.9, .9, .9, 1) - font_size: '11.5pt' + font_size: '15sp' canvas: Color: rgba: .15, .15, .15, .5 @@ -577,8 +578,8 @@ : size_hint: 1, None text_size: self.width - 32, None - height: max(50, self.texture_size[1] + 10) - font_size: '11.5pt' + height: self.texture_size[1] + dp(20) + font_size: '15sp' canvas.before: Color: rgba: 47 / 255., 167 / 255., 212 / 255., int(self.selected) @@ -598,7 +599,7 @@ text_size: self.width - 32, None height: max(50, self.texture_size[1] + 20) color: (.5, .5, .5, 1) - font_size: '11.5pt' + font_size: '15sp' canvas.after: Color: @@ -620,7 +621,7 @@ FloatLayout: size_hint_x: None - width: 200 + width: '200dp' GridLayout: pos: root.pos cols: 1 @@ -638,11 +639,11 @@ Button: text: 'Close' size_hint: None, None - width: 180 - height: max(50, self.texture_size[1] + 10) - pos: root.x + 10, root.y + 10 + width: '180dp' + height: max(50, self.texture_size[1] + dp(20)) + pos: root.x + dp(10), root.y + dp(10) on_release: root.dispatch('on_close') - font_size: '11.5pt' + font_size: '15sp' ScrollView: do_scroll_x: False diff --git a/kivy/lang.py b/kivy/lang.py index 60765f672..44fd488f5 100644 --- a/kivy/lang.py +++ b/kivy/lang.py @@ -458,6 +458,7 @@ from kivy.utils import OrderedDict, QueryDict from kivy.cache import Cache from kivy import kivy_data_dir, require from kivy.lib.debug import make_traceback +import kivy.metrics as metrics trace = Logger.trace @@ -517,7 +518,14 @@ class ProxyApp(object): object.__getattribute__(self, '_ensure_app')() return repr(object.__getattribute__(self, '_obj')) + global_idmap['app'] = ProxyApp() +global_idmap['pt'] = metrics.pt +global_idmap['inch'] = metrics.inch +global_idmap['cm'] = metrics.cm +global_idmap['mm'] = metrics.mm +global_idmap['dp'] = metrics.dp +global_idmap['sp'] = metrics.sp class ParserException(Exception): diff --git a/kivy/metrics.py b/kivy/metrics.py new file mode 100644 index 000000000..2b2aff71c --- /dev/null +++ b/kivy/metrics.py @@ -0,0 +1,214 @@ +''' +Metrics +======= + +.. versionadded:: 1.5.0 + +A screen is defined by its actual physical size, density, resolution. These +factors are essential for creating UI with correct size everywhere. + +In Kivy, all our graphics pipeline is working with pixels. But using pixels as a +measurement unit is wrong, because the size will changes according to the +screen. + +Dimensions +---------- + +As you design your UI for different screen sizes, you'll need new measurement +unit to work with. + +:Units: + `pt` + Points - 1/72 of an inch based on the physical size of the screen. + Prefer to use sp instead of pt. + `mm` + Millimeters - Based on the physical size of the screen + `cm` + Centimeters - Based on the physical size of the screen + `in` + Inches - Based on the physical size of the screen + `dp` + Density-independent Pixels - An abstract unit that is based on the + physical density of the screen. With a :data:`Metrics.density` of 1, 1dp + is equal to 1px. When running on a higher density screen, the number of + pixels used to draw 1dp is scaled up by the factor of appropriate + screen's dpi, and the inverse for lower dpi. + The ratio dp-to-pixes will change with the screen density, but not + necessarily in direct proportions. Using dp unit is a simple solution to + making the view dimensions in your layout resize properly for different + screen densities. In others words, it provides consistency for the + real-world size of your UI across different devices. + `sp` + Scale-independent Pixels - This is like the dp unit, but it is also + scaled by the user's font size preference. It is recommended to use this + unit when specifying font sizes, so they will be adjusted for both the + screen density and the user's preference. + +Examples +-------- + +An example of creating a label with a sp font_size, and set a manual height with +a 10dp margin:: + + #:kivy 1.5.0 + : + Label: + text: 'Hello world' + font_size: '15sp' + size_hint_y: None + height: self.texture_size[1] + dp(10) + +Manual control of metrics +------------------------- + +The metrics cannot be changed in runtime. Once a value has been converted to +pixels, you don't have the original value anymore. It's not like you'll change +the DPI or density in runtime. + +We provide new environment variables to control the metrics: + +- `KIVY_METRICS_DENSITY`: if set, this value will be used for + :data:`Metrics.density` instead of the system one. On android, the value + varies between 0.75, 1, 1.5. 2. + +- `KIVY_METRICS_FONTSCALE`: if set, this value will be used for + :data:`Metrics.fontscale` instead of the system one. On android, the value + varies between 0.8-1.2. + +- `KIVY_DPI`: if set, this value will be used for :data:`Metrics.dpi`. Please + note that settings the DPI will not impact dp/sp notation, because thoses are + based on the density. + +For example, if you want to simulate an high-density screen (like HTC One X):: + + KIVY_DPI=320 KIVY_METRICS_DENSITY=2 python main.py --size 1280x720 + +Or a medium-density (like Motorola Droid 2):: + + KIVY_DPI=240 KIVY_METRICS_DENSITY=1.5 python main.py --size 854x480 + +You can also simulate an alternative user preference for fontscale, like:: + + KIVY_METRICS_FONTSCALE=1.2 python main.py + +''' + + +__all__ = ('metrics', 'Metrics', 'pt', 'inch', 'cm', 'mm', 'dp', 'sp') + + +from os import environ +from kivy.utils import reify, platform +from kivy.properties import dpi2px + + +def pt(value): + '''Convert from points to pixels + ''' + return dpi2px(value, 'pt') + + +def inch(value): + '''Convert from inches to pixels + ''' + return dpi2px(value, 'in') + + +def cm(value): + '''Convert from centimeters to pixels + ''' + return dpi2px(value, 'cm') + + +def mm(value): + '''Convert from millimeters to pixels + ''' + return dpi2px(value, 'mm') + + +def dp(value): + '''Convert from density-independent pixels to pixels + ''' + return dpi2px(value, 'dp') + + +def sp(value): + '''Convert from scale-independent pixels to pixels + ''' + return dpi2px(value, 'sp') + + +class Metrics(object): + '''Class that contain the default attribute for metrics. Don't use the class + directly, but use the `metrics` instance. + ''' + + @reify + def dpi(self): + '''Return the DPI of the screen. Depending of the platform, the DPI can + be taken from the Window provider (Desktop mainly), or from + platform-specific module (like android/ios). + ''' + custom_dpi = environ.get('KIVY_DPI') + if custom_dpi: + return float(custom_dpi) + + if platform() == 'android': + import android + return android.get_dpi() + + # for all other platforms.. + from kivy.base import EventLoop + EventLoop.ensure_window() + return EventLoop.window.dpi + + @reify + def dpi_rounded(self): + '''Return the dpi of the screen, rounded to the nearest of 120, 160, + 240, 320. + ''' + dpi = self.dpi + if dpi < 140: + return 120 + elif dpi < 200: + return 160 + elif dpi < 280: + return 240 + return 320 + + @reify + def density(self): + '''Return the density of the screen. This value is 1 by default + on desktop, and varies on android depending the screen. + ''' + custom_density = environ.get('KIVY_METRICS_DENSITY') + if custom_density: + return float(custom_density) + + if platform() == 'android': + import jnius + Hardware = jnius.autoclass('org.renpy.android.Hardware') + return Hardware.metrics.scaledDensity + + return 1.0 + + @reify + def fontscale(self): + '''Return the fontscale user preference. This value is 1 by default, and + can varies between 0.8-1.2. + ''' + custom_fontscale = environ.get('KIVY_METRICS_FONTSCALE') + if custom_fontscale: + return float(custom_fontscale) + + if platform() == 'android': + import jnius + PythonActivity = jnius.autoclass('org.renpy.android.PythonActivity') + config = PythonActivity.mActivity.getResources().getConfiguration() + return config.fontScale + + return 1.0 + + +#: default instance of :class:`Metrics`, used everywhere in the code +metrics = Metrics() diff --git a/kivy/properties.pyx b/kivy/properties.pyx index bc36916b8..35196d4c9 100644 --- a/kivy/properties.pyx +++ b/kivy/properties.pyx @@ -173,25 +173,33 @@ __all__ = ('Property', from weakref import ref -EventLoop = None +cdef float g_dpi = -1 +cdef float g_density = -1 +cdef float g_fontscale = -1 cpdef float dpi2px(value, ext): # 1in = 2.54cm = 25.4mm = 72pt = 12pc - global EventLoop - if EventLoop is None: - from kivy.base import EventLoop + global g_dpi, g_density, g_fontscale + if g_dpi == -1: + from kivy.metrics import metrics + g_dpi = metrics.dpi + g_density = metrics.density + g_fontscale = metrics.fontscale cdef float rv = float(value) - cdef float dpi = EventLoop.dpi if ext == 'in': - return rv * dpi + return rv * g_dpi elif ext == 'px': return rv + elif ext == 'dp': + return rv * g_density + elif ext == 'sp': + return rv * g_density * g_fontscale elif ext == 'pt': - return rv * dpi / 72. + return rv * g_dpi / 72. elif ext == 'cm': - return rv * dpi / 2.54 + return rv * g_dpi / 2.54 elif ext == 'mm': - return rv * dpi / 25.4 + return rv * g_dpi / 25.4 cdef class Property: diff --git a/kivy/uix/accordion.py b/kivy/uix/accordion.py index d2a003f4d..6f2c7f875 100644 --- a/kivy/uix/accordion.py +++ b/kivy/uix/accordion.py @@ -212,7 +212,7 @@ class AccordionItem(FloatLayout): '''Link to the :attr:`Accordion.orientation` property. ''' - min_space = NumericProperty(44) + min_space = NumericProperty('44dp') '''Link to the :attr:`Accordion.min_space` property. ''' @@ -321,7 +321,7 @@ class Accordion(Widget): easing function. ''' - min_space = NumericProperty(44) + min_space = NumericProperty('44dp') '''Minimum space to use for title of each item. This value is automatically set on each children, each time the layout happens. diff --git a/kivy/uix/label.py b/kivy/uix/label.py index 64c2aac52..100e5ef0f 100644 --- a/kivy/uix/label.py +++ b/kivy/uix/label.py @@ -15,7 +15,7 @@ strings:: l = Label(text='Multi\\nLine') # size - l = Label(text='Hello world', font_size=20) + l = Label(text='Hello world', font_size='20sp') Markup text ----------- @@ -148,9 +148,6 @@ class Label(Widget): # markup have change, we need to change our rendering method. d = Label._font_properties dkw = dict(zip(d, [getattr(self, x) for x in d])) - # XXX font_size core provider compatibility - if Label.font_size.get_format(self) == 'px': - dkw['font_size'] *= 1.333 if markup: self._label = CoreMarkupLabel(**dkw) else: @@ -166,9 +163,6 @@ class Label(Widget): elif name == 'text_size': self._label.usersize = value elif name == 'font_size': - # XXX font_size core provider compatibility - if Label.font_size.get_format(self) == 'px': - value *= 1.333 self._label.options[name] = value else: self._label.options[name] = value @@ -274,11 +268,11 @@ class Label(Widget): 'DroidSans'. ''' - font_size = NumericProperty('12px') + font_size = NumericProperty('15sp') '''Font size of the text, in pixels. :data:`font_size` is a :class:`~kivy.properties.NumericProperty`, default to - 12. + 12dp. ''' bold = BooleanProperty(False) @@ -379,7 +373,7 @@ class Label(Widget): l = Label(text='Hello world') # l.texture is good - l.font_size = 50 + l.font_size = '50sp' # l.texture is not updated yet l.update_texture() # l.texture is good now. diff --git a/kivy/uix/popup.py b/kivy/uix/popup.py index 9fcd5dd59..61fbca346 100644 --- a/kivy/uix/popup.py +++ b/kivy/uix/popup.py @@ -119,13 +119,13 @@ class Popup(ModalView): default to [47 / 255., 167 / 255., 212 / 255., 1.] ''' - separator_height = NumericProperty(2) + separator_height = NumericProperty('2dp') '''Height of the separator. .. versionadded:: 1.1.0 :data:`separator_height` is a :class:`~kivy.properties.NumericProperty`, - default to 2. + default to 2dp. ''' # Internals properties used for graphical representation. diff --git a/kivy/uix/rst.py b/kivy/uix/rst.py index 1d8937cd9..a3df4c80b 100644 --- a/kivy/uix/rst.py +++ b/kivy/uix/rst.py @@ -147,9 +147,9 @@ Builder.load_string(''' : markup: True valign: 'top' - font_size: 24 - self.section * 2 + font_size: sp(31 - self.section * 2) size_hint_y: None - height: self.texture_size[1] + 20 + height: self.texture_size[1] + dp(20) text_size: self.width, None bold: True @@ -178,7 +178,7 @@ Builder.load_string(''' markup: True valign: 'top' size_hint: None, None - size: self.texture_size[0] + 10, self.texture_size[1] + 10 + size: self.texture_size[0] + dp(10), self.texture_size[1] + dp(10) : cols: 2 @@ -198,7 +198,7 @@ Builder.load_string(''' cols: 1 content: content size_hint_y: None - height: content.texture_size[1] + 20 + height: content.texture_size[1] + dp(20) canvas: Color: rgb: parse_color('#cccccc') @@ -277,11 +277,11 @@ Builder.load_string(''' : size_hint: None, None - size: self.texture_size[0], self.texture_size[1] + 10 + size: self.texture_size[0], self.texture_size[1] + dp(10) : size_hint: None, None - size: self.texture_size[0], self.texture_size[1] + 10 + size: self.texture_size[0], self.texture_size[1] + dp(10) : cols: 1 @@ -350,8 +350,8 @@ Builder.load_string(''' markup: True valign: 'top' size_hint_x: None - width: self.texture_size[0] + 10 - text_size: None, self.height - 10 + width: self.texture_size[0] + dp(10) + text_size: None, self.height - dp(10) : size_hint: 0.01, 0.01 diff --git a/kivy/uix/scrollview.py b/kivy/uix/scrollview.py index 1df5a4c4d..30da4d5c7 100644 --- a/kivy/uix/scrollview.py +++ b/kivy/uix/scrollview.py @@ -651,7 +651,7 @@ class ScrollView(StencilView): [.7, .7, .7, .9]. ''' - bar_width = NumericProperty(2) + bar_width = NumericProperty('2dp') '''Width of the horizontal / vertical scroll bar. The width is interpreted as a height for the horizontal bar. diff --git a/kivy/uix/settings.py b/kivy/uix/settings.py index c342f837d..389c08519 100644 --- a/kivy/uix/settings.py +++ b/kivy/uix/settings.py @@ -108,6 +108,7 @@ __all__ = ('Settings', 'SettingsPanel', 'SettingItem', 'SettingString', import json import os +from kivy.metrics import dp from kivy.config import ConfigParser from kivy.animation import Animation from kivy.uix.boxlayout import BoxLayout @@ -339,13 +340,13 @@ class SettingString(SettingItem): def _create_popup(self, instance): # create popup layout - content = BoxLayout(orientation='vertical', spacing=5) + content = BoxLayout(orientation='vertical', spacing='5dp') self.popup = popup = Popup(title=self.title, - content=content, size_hint=(None, None), size=(400, 250)) + content=content, size_hint=(None, None), size=('400dp', '250dp')) # create the textinput used for numeric input self.textinput = textinput = TextInput(text=str(self.value), - font_size=24, multiline=False, size_hint_y=None, height=50) + font_size=24, multiline=False, size_hint_y=None, height='50dp') textinput.bind(on_text_validate=self._validate) self.textinput = textinput @@ -356,7 +357,7 @@ class SettingString(SettingItem): content.add_widget(SettingSpacer()) # 2 buttons are created for accept or cancel the current value - btnlayout = BoxLayout(size_hint_y=None, height=50, spacing=5) + btnlayout = BoxLayout(size_hint_y=None, height='50dp', spacing='5dp') btn = Button(text='Ok') btn.bind(on_release=self._validate) btnlayout.add_widget(btn) @@ -433,7 +434,7 @@ class SettingPath(SettingItem): content.add_widget(SettingSpacer()) # 2 buttons are created for accept or cancel the current value - btnlayout = BoxLayout(size_hint_y=None, height=50, spacing=5) + btnlayout = BoxLayout(size_hint_y=None, height='50dp', spacing='5dp') btn = Button(text='Ok') btn.bind(on_release=self._validate) btnlayout.add_widget(btn) @@ -500,10 +501,10 @@ class SettingOptions(SettingItem): def _create_popup(self, instance): # create the popup - content = BoxLayout(orientation='vertical', spacing=5) + content = BoxLayout(orientation='vertical', spacing='5dp') self.popup = popup = Popup(content=content, - title=self.title, size_hint=(None, None), size=(400, 400)) - popup.height = len(self.options) * 55 + 150 + title=self.title, size_hint=(None, None), size=('400dp', '400dp')) + popup.height = len(self.options) * dp(55) + dp(150) # add all the options content.add_widget(Widget(size_hint_y=None, height=1)) @@ -516,7 +517,7 @@ class SettingOptions(SettingItem): # finally, add a cancel button to return on the previous panel content.add_widget(SettingSpacer()) - btn = Button(text='Cancel', size_hint_y=None, height=50) + btn = Button(text='Cancel', size_hint_y=None, height=dp(50)) btn.bind(on_release=popup.dismiss) content.add_widget(btn) diff --git a/kivy/uix/tabbedpanel.py b/kivy/uix/tabbedpanel.py index c45b7aadf..d46a44c6d 100644 --- a/kivy/uix/tabbedpanel.py +++ b/kivy/uix/tabbedpanel.py @@ -234,14 +234,14 @@ class TabbedPanel(GridLayout): default to 'bottom_mid'. ''' - tab_height = NumericProperty(40) + tab_height = NumericProperty('40dp') '''Specifies the height of the tab header. :data:`tab_height` is a :class:`~kivy.properties.NumericProperty`, default to 40. ''' - tab_width = NumericProperty(100, allownone=True) + tab_width = NumericProperty('100dp', allownone=True) '''Specifies the width of the tab header. :data:`tab_width` is a :class:`~kivy.properties.NumericProperty`, diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index ce1c8b7be..c9f31f43d 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -1171,15 +1171,9 @@ class TextInput(Widget): def _get_line_options(self): # Get or create line options, to be used for Label creation - - # XXX font_size core label compatibility - factor = 1. - if TextInput.font_size.get_format(self) == 'px': - factor = 1.333 - if self._line_options is None: self._line_options = kw = { - 'font_size': self.font_size * factor, + 'font_size': self.font_size, 'font_name': self.font_name, 'anchor_x': 'left', 'anchor_y': 'top', @@ -1714,7 +1708,7 @@ class TextInput(Widget): 'DroidSans'. ''' - font_size = NumericProperty(10) + font_size = NumericProperty('15sp') '''Font size of the text, in pixels. :data:`font_size` is a :class:`~kivy.properties.NumericProperty`, default to diff --git a/kivy/uix/treeview.py b/kivy/uix/treeview.py index 2c57f8bfb..1319b6eb1 100644 --- a/kivy/uix/treeview.py +++ b/kivy/uix/treeview.py @@ -509,7 +509,7 @@ class TreeView(Widget): of (:data:`minimum_width`, :data:`minimum_height`) properties. ''' - indent_level = NumericProperty(16) + indent_level = NumericProperty('16dp') '''Width used for identation of each level, except the first level. Computation of spacing for eaching level of tree is:: @@ -520,7 +520,7 @@ class TreeView(Widget): defaults to 16. ''' - indent_start = NumericProperty(24) + indent_start = NumericProperty('24dp') '''Indentation width of the level 0 / root node. This is mostly the initial size to accommodate a tree icon (collapsed / expanded). See :data:`indent_level` for more information about the computation of level diff --git a/kivy/uix/vkeyboard.py b/kivy/uix/vkeyboard.py index ef55e22d1..fea7d861b 100644 --- a/kivy/uix/vkeyboard.py +++ b/kivy/uix/vkeyboard.py @@ -276,7 +276,7 @@ class VKeyboard(Scatter): have_capslock = BooleanProperty(False) have_shift = BooleanProperty(False) active_keys = DictProperty({}) - font_size = NumericProperty(15) + font_size = NumericProperty('20dp') font_name = StringProperty('data/fonts/DejaVuSans.ttf') def __init__(self, **kwargs):