--- /dev/null
+from kivy.app import App
+from kivy.uix.widget import Widget
+from kivy.uix.boxlayout import BoxLayout
+from kivy.uix.slider import Slider
+from kivy.uix.textinput import TextInput
+from kivy.uix.label import Label
+from kivy.uix.listview import ListView
+from kivy.properties import NumericProperty, ReferenceListProperty,\
+ ObjectProperty, BoundedNumericProperty
+from kivy.vector import Vector
+from kivy.clock import Clock
+from kivy.adapters.simplelistadapter import SimpleListAdapter
+
+import re
+import random
+
+MAX_DICE = 30
+MAX_SKILL = 6
+
+class SlavedSlider(Slider):
+ pass
+
+class SlavedTextInput(TextInput):
+ pat = re.compile('[^0-9]')
+
+ def insert_text(self, substring, from_undo=False):
+ pat = self.pat
+ s = re.sub(pat, '', substring)
+ return super(SlavedTextInput, self).insert_text(s, from_undo=from_undo)
+
+class TenraRoller(BoxLayout):
+
+ max_dice = NumericProperty(MAX_DICE)
+ max_skill = NumericProperty(MAX_SKILL)
+
+ dice_slider = ObjectProperty(None)
+ dice_text = ObjectProperty(None)
+ dice_value = BoundedNumericProperty(int(MAX_DICE / 2), min=1, max=MAX_DICE)
+
+ skill_slider = ObjectProperty(None)
+ skill_text = ObjectProperty(None)
+ skill_value = BoundedNumericProperty(int(MAX_SKILL / 2), min=1, max=MAX_SKILL)
+
+ result_label = ObjectProperty(None)
+ previous_results = ObjectProperty(None)
+
+ last_results_texts = []
+ previous_results_la = SimpleListAdapter(data=last_results_texts,
+ cls=Label)
+
+
+ def slider_value_change(self, myid):
+ print("Slider {} changed to {}".format(myid, myid.value))
+ if myid == self.dice_slider:
+ self.dice_value = int(myid.value)
+ self.dice_text.text = str(self.dice_value)
+ if myid == self.skill_slider:
+ self.skill_value = int(myid.value)
+ self.skill_text.text = str(self.skill_value)
+
+ def text_value_change(self, myid):
+ print("Text {} changed to {}".format(myid, myid.text))
+ try:
+ if myid == self.skill_text:
+ self.skill_value = int(myid.text)
+ self.skill_slider.value = self.skill_value
+ if myid == self.dice_text:
+ self.dice_value = int(myid.text)
+ self.dice_slider.value = self.dice_value
+ except ValueError:
+ myid.background_color = [1, 0.5, 0.5, 1]
+ else:
+ myid.background_color = [1, 1, 1, 1]
+
+ # if myid == self.dice_text:
+ # self.dice_value = int(myid.text)
+ # self.dice_slider.value = self.dice_value
+ # if myid == self.skill_text:
+ # try:
+ # self.skill_value = int(myid.text)
+ # except ValueError:
+ # myid.background_color = [1, 0.5, 0.5, 1]
+ # else:
+ # myid.background_color = [1, 1, 1, 1]
+ # self.skill_slider.value = self.skill_value
+
+
+ def roll_dice(self):
+ successes = 0
+ for i in range(self.dice_value):
+ if random.randint(1, 6) <= self.skill_value:
+ successes += 1
+ self.last_results_texts = [self.result_label.text] + self.last_results_texts
+ self.result_label.text = 'Rolled {dice}({skill}) for {succ} successes'.format(dice=self.dice_value, skill=self.skill_value,
+ succ=successes)
+ self.previous_results_la.data = self.last_results_texts
+
+
+# def slider_value_change(slider, value):
+# print("Slider {} changed to {}".format(slider, value))
+
+class TenraRollerApp(App):
+ # dice_slider = ObjectProperty(None)
+ # dice_text = ObjectProperty(None)
+ # dice_value = BoundedNumericProperty(10, min=1, max=30)
+
+ def build(self):
+ roller = TenraRoller(max_dice=MAX_DICE, max_skill=MAX_SKILL)
+ return roller
+
+
+if __name__ == '__main__':
+ TenraRollerApp().run()
--- /dev/null
+from os.path import join, dirname
+import sys
+sys.path.append(join(dirname(__file__), '_applibs'))
--- /dev/null
+<SlavedSlider>:
+
+<SlavedTextInput>:
+
+<TenraRoller>:
+ dice_slider: dice_slider
+ dice_text: dice_text
+ skill_slider: skill_slider
+ skill_text: skill_text
+
+ roll_button: roll_button
+ result_label: result_label
+ previous_results: previous_results
+
+ BoxLayout:
+ orientation: 'vertical'
+ spacing: 10
+ size_hint: 1, 1
+
+ BoxLayout:
+ orientation: 'horizontal'
+ spacing: 10
+ center_x: root.center_x
+ width: root.width
+ Label:
+ text: "Dice"
+ SlavedSlider:
+ id: dice_slider
+ orientation: 'horizontal'
+ min: 1
+ max: root.max_dice
+ step: 1
+ value: int(root.max_dice / 2)
+ on_value: root.slider_value_change(dice_slider)
+ SlavedTextInput:
+ id: dice_text
+ multiline: False
+ on_text: root.text_value_change(dice_text)
+ text: str(int(root.max_dice / 2))
+
+ BoxLayout:
+ orientation: 'horizontal'
+ spacing: 10
+ width: root.width
+ Label:
+ text: "Skill"
+ SlavedSlider:
+ id: skill_slider
+ orientation: 'horizontal'
+ min: 1
+ max: root.max_skill
+ step: 1
+ value: int(root.max_skill / 2)
+ on_value: root.slider_value_change(skill_slider)
+ SlavedTextInput:
+ id: skill_text
+ multiline: False
+ on_text: root.text_value_change(skill_text)
+ text: str(int(root.max_skill / 2))
+
+ Button:
+ id: roll_button
+ text: "Roll"
+ on_press: root.roll_dice()
+
+ Label:
+ id: result_label
+ text: "No result"
+
+ ListView:
+ id: previous_results
+ adapter: root.previous_results_la
--- /dev/null
+Subproject commit 5674bced02508dcaa75c798706ea05b7b45eea34
--- /dev/null
+Subproject commit f343c147696e6093204f4d0614480636ec732d85
--- /dev/null
+{"android:latestmode": "debug", "android:sdk_installation": ["19", "9", "9c", "/home/neil/.buildozer/android/platform/android-sdk-20", "/home/neil/.buildozer/android/platform/android-ndk-r9c"], "cache.gardenlibs": "", "android:latestapk": "TBZRoller-0.1-debug.apk", "android:available_permissions": ["ACCESS_CHECKIN_PROPERTIES", "ACCESS_COARSE_LOCATION", "ACCESS_FINE_LOCATION", "ACCESS_LOCATION_EXTRA_COMMANDS", "ACCESS_MOCK_LOCATION", "ACCESS_NETWORK_STATE", "ACCESS_SURFACE_FLINGER", "ACCESS_WIFI_STATE", "ACCOUNT_MANAGER", "ADD_SYSTEM_SERVICE", "ADD_VOICEMAIL", "AUTHENTICATE_ACCOUNTS", "BATTERY_STATS", "BIND_ACCESSIBILITY_SERVICE", "BIND_APPWIDGET", "BIND_DEVICE_ADMIN", "BIND_INPUT_METHOD", "BIND_NFC_SERVICE", "BIND_NOTIFICATION_LISTENER_SERVICE", "BIND_PRINT_SERVICE", "BIND_REMOTEVIEWS", "BIND_TEXT_SERVICE", "BIND_VPN_SERVICE", "BIND_WALLPAPER", "BLUETOOTH", "BLUETOOTH_ADMIN", "BLUETOOTH_PRIVILEGED", "BRICK", "BROADCAST_PACKAGE_REMOVED", "BROADCAST_SMS", "BROADCAST_STICKY", "BROADCAST_WAP_PUSH", "CALL_PHONE", "CALL_PRIVILEGED", "CAMERA", "CAPTURE_AUDIO_OUTPUT", "CAPTURE_SECURE_VIDEO_OUTPUT", "CAPTURE_VIDEO_OUTPUT", "CHANGE_COMPONENT_ENABLED_STATE", "CHANGE_CONFIGURATION", "CHANGE_NETWORK_STATE", "CHANGE_WIFI_MULTICAST_STATE", "CHANGE_WIFI_STATE", "CLEAR_APP_CACHE", "CLEAR_APP_USER_DATA", "CONTROL_LOCATION_UPDATES", "DELETE_CACHE_FILES", "DELETE_PACKAGES", "DEVICE_POWER", "DIAGNOSTIC", "DISABLE_KEYGUARD", "DUMP", "EXPAND_STATUS_BAR", "FACTORY_TEST", "FLASHLIGHT", "FORCE_BACK", "FOTA_UPDATE", "GET_ACCOUNTS", "GET_PACKAGE_SIZE", "GET_TASKS", "GET_TOP_ACTIVITY_INFO", "GLOBAL_SEARCH", "HARDWARE_TEST", "INJECT_EVENTS", "INSTALL_LOCATION_PROVIDER", "INSTALL_PACKAGES", "INSTALL_SHORTCUT", "INTERNAL_SYSTEM_WINDOW", "INTERNET", "KILL_BACKGROUND_PROCESSES", "LOCATION_HARDWARE", "MANAGE_ACCOUNTS", "MANAGE_APP_TOKENS", "MANAGE_DOCUMENTS", "MASTER_CLEAR", "MEDIA_CONTENT_CONTROL", "MODIFY_AUDIO_SETTINGS", "MODIFY_PHONE_STATE", "MOUNT_FORMAT_FILESYSTEMS", "MOUNT_UNMOUNT_FILESYSTEMS", "NFC", "PERSISTENT_ACTIVITY", "PROCESS_OUTGOING_CALLS", "READ_CALENDAR", "READ_CALL_LOG", "READ_CONTACTS", "READ_EXTERNAL_STORAGE", "READ_FRAME_BUFFER", "READ_HISTORY_BOOKMARKS", "READ_INPUT_STATE", "READ_LOGS", "READ_OWNER_DATA", "READ_PHONE_STATE", "READ_PROFILE", "READ_SMS", "READ_SOCIAL_STREAM", "READ_SYNC_SETTINGS", "READ_SYNC_STATS", "READ_USER_DICTIONARY", "REBOOT", "RECEIVE_BOOT_COMPLETED", "RECEIVE_MMS", "RECEIVE_SMS", "RECEIVE_WAP_PUSH", "RECORD_AUDIO", "REORDER_TASKS", "RESTART_PACKAGES", "SEND_RESPOND_VIA_MESSAGE", "SEND_SMS", "SET_ACTIVITY_WATCHER", "SET_ALARM", "SET_ALWAYS_FINISH", "SET_ANIMATION_SCALE", "SET_DEBUG_APP", "SET_ORIENTATION", "SET_POINTER_SPEED", "SET_PREFERRED_APPLICATIONS", "SET_PROCESS_FOREGROUND", "SET_PROCESS_LIMIT", "SET_TIME", "SET_TIME_ZONE", "SET_WALLPAPER", "SET_WALLPAPER_HINTS", "SIGNAL_PERSISTENT_PROCESSES", "STATUS_BAR", "SUBSCRIBED_FEEDS_READ", "SUBSCRIBED_FEEDS_WRITE", "SYSTEM_ALERT_WINDOW", "TRANSMIT_IR", "UNINSTALL_SHORTCUT", "UPDATE_DEVICE_STATS", "USE_CREDENTIALS", "USE_SIP", "VIBRATE", "WAKE_LOCK", "WRITE_APN_SETTINGS", "WRITE_CALENDAR", "WRITE_CALL_LOG", "WRITE_CONTACTS", "WRITE_EXTERNAL_STORAGE", "WRITE_GSERVICES", "WRITE_HISTORY_BOOKMARKS", "WRITE_OWNER_DATA", "WRITE_PROFILE", "WRITE_SECURE_SETTINGS", "WRITE_SETTINGS", "WRITE_SMS", "WRITE_SOCIAL_STREAM", "WRITE_SYNC_SETTINGS", "WRITE_USER_DICTIONARY"], "cache.applibs": [], "android:available_permissions_sdk": "20", "android.requirements": ["kivy"], "cache.build_id": "3", "android.requirements.source": {}}
\ No newline at end of file
--- /dev/null
+*.py[cod]
+
+# C extensions
+*.so
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+lib
+lib64
+__pycache__
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+nosetests.xml
+
+# Translations
+*.mo
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+
+# IPython
+.ipynb*
+
+# Sublime text
+*.sublime-workspace
+
+# Logs
+*.log
--- /dev/null
+[app]
+
+# (str) Title of your application
+title = TBZ Roller
+
+# (str) Package name
+package.name = tbzroller
+
+# (str) Package domain (needed for android/ios packaging)
+package.domain = uk.me.njae
+
+# (str) Source code where the main.py live
+source.dir = .
+
+# (list) Source files to include (let empty to include all the files)
+source.include_exts = py,png,jpg,kv,atlas
+
+# (list) List of inclusions using pattern matching
+#source.include_patterns = assets/*,images/*.png
+
+# (list) Source files to exclude (let empty to not exclude anything)
+#source.exclude_exts = spec
+
+# (list) List of directory to exclude (let empty to not exclude anything)
+#source.exclude_dirs = tests, bin
+
+# (list) List of exclusions using pattern matching
+#source.exclude_patterns = license,images/*/*.jpg
+
+# (str) Application versioning (method 1)
+version = 0.1
+
+# (str) Application versioning (method 2)
+# version.regex = __version__ = ['"](.*)['"]
+# version.filename = %(source.dir)s/main.py
+
+# (list) Application requirements
+# comma seperated e.g. requirements = sqlite3,kivy
+requirements = kivy
+
+# (str) Custom source folders for requirements
+# Sets custom source for any requirements with recipes
+# requirements.source.kivy = ../../kivy
+
+# (list) Garden requirements
+#garden_requirements =
+
+# (str) Presplash of the application
+#presplash.filename = %(source.dir)s/data/presplash.png
+
+# (str) Icon of the application
+#icon.filename = %(source.dir)s/data/icon.png
+
+# (str) Supported orientation (one of landscape, portrait or all)
+orientation = landscape
+
+# (list) List of service to declare
+#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
+
+#
+# OSX Specific
+#
+
+#
+# author = © Copyright Info
+
+#
+# Android specific
+#
+
+# (bool) Indicate if the application should be fullscreen or not
+fullscreen = 1
+
+# (list) Permissions
+#android.permissions = INTERNET
+
+# (int) Android API to use
+#android.api = 19
+
+# (int) Minimum API required
+#android.minapi = 9
+
+# (int) Android SDK version to use
+#android.sdk = 20
+
+# (str) Android NDK version to use
+#android.ndk = 9c
+
+# (bool) Use --private data storage (True) or --dir public storage (False)
+#android.private_storage = True
+
+# (str) Android NDK directory (if empty, it will be automatically downloaded.)
+#android.ndk_path =
+
+# (str) Android SDK directory (if empty, it will be automatically downloaded.)
+#android.sdk_path =
+
+# (str) ANT directory (if empty, it will be automatically downloaded.)
+#android.ant_path =
+
+# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
+#android.p4a_dir =
+
+# (list) python-for-android whitelist
+#android.p4a_whitelist =
+
+# (bool) If True, then skip trying to update the Android sdk
+# This can be useful to avoid excess Internet downloads or save time
+# when an update is due and you just want to test/build your package
+# android.skip_update = False
+
+# (str) Android entry point, default is ok for Kivy-based app
+#android.entrypoint = org.renpy.android.PythonActivity
+
+# (list) List of Java .jar files to add to the libs so that pyjnius can access
+# their classes. Don't add jars that you do not need, since extra jars can slow
+# down the build process. Allows wildcards matching, for example:
+# OUYA-ODK/libs/*.jar
+#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
+
+# (list) List of Java files to add to the android project (can be java or a
+# directory containing the files)
+#android.add_src =
+
+# (str) python-for-android branch to use, if not master, useful to try
+# not yet merged features.
+#android.branch = master
+
+# (str) OUYA Console category. Should be one of GAME or APP
+# If you leave this blank, OUYA support will not be enabled
+#android.ouya.category = GAME
+
+# (str) Filename of OUYA Console icon. It must be a 732x412 png image.
+#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
+
+# (str) XML file to include as an intent filters in <activity> tag
+#android.manifest.intent_filters =
+
+# (list) Android additionnal libraries to copy into libs/armeabi
+#android.add_libs_armeabi = libs/android/*.so
+#android.add_libs_armeabi_v7a = libs/android-v7/*.so
+#android.add_libs_x86 = libs/android-x86/*.so
+#android.add_libs_mips = libs/android-mips/*.so
+
+# (bool) Indicate whether the screen should stay on
+# Don't forget to add the WAKE_LOCK permission if you set this to True
+#android.wakelock = False
+
+# (list) Android application meta-data to set (key=value format)
+#android.meta_data =
+
+# (list) Android library project to add (will be added in the
+# project.properties automatically.)
+#android.library_references =
+
+# (str) Android logcat filters to use
+#android.logcat_filters = *:S python:D
+
+# (bool) Copy library instead of making a libpymodules.so
+#android.copy_libs = 1
+
+#
+# iOS specific
+#
+
+# (str) Path to a custom kivy-ios folder
+#ios.kivy_ios_dir = ../kivy-ios
+
+# (str) Name of the certificate to use for signing the debug version
+# Get a list of available identities: buildozer ios list_identities
+#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"
+
+# (str) Name of the certificate to use for signing the release version
+#ios.codesign.release = %(ios.codesign.debug)s
+
+
+[buildozer]
+
+# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
+log_level = 1
+
+# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
+warn_on_root = 1
+
+# (str) Path to build artifact storage, absolute or relative to spec file
+# build_dir = ./.buildozer
+
+# (str) Path to build output (i.e. .apk, .ipa) storage
+# bin_dir = ./bin
+
+# -----------------------------------------------------------------------------
+# List as sections
+#
+# You can define all the "list" as [section:key].
+# Each line will be considered as a option to the list.
+# Let's take [app] / source.exclude_patterns.
+# Instead of doing:
+#
+#[app]
+#source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
+#
+# This can be translated into:
+#
+#[app:source.exclude_patterns]
+#license
+#data/audio/*.wav
+#data/images/original/*
+#
+
+
+# -----------------------------------------------------------------------------
+# Profiles
+#
+# You can extend section / key with a profile
+# For example, you want to deploy a demo version of your application without
+# HD content. You could first change the title to add "(demo)" in the name
+# and extend the excluded directories to remove the HD content.
+#
+#[app@demo]
+#title = My Application (demo)
+#
+#[app:source.exclude_patterns@demo]
+#images/hd/*
+#
+# Then, invoke the command line with the "demo" profile:
+#
+#buildozer --profile demo android debug
--- /dev/null
+from kivy.app import App
+from kivy.uix.widget import Widget
+from kivy.uix.boxlayout import BoxLayout
+from kivy.uix.slider import Slider
+from kivy.uix.textinput import TextInput
+from kivy.uix.label import Label
+from kivy.uix.listview import ListView
+from kivy.properties import NumericProperty, ReferenceListProperty,\
+ ObjectProperty, BoundedNumericProperty, StringProperty
+from kivy.vector import Vector
+from kivy.clock import Clock
+from kivy.adapters.simplelistadapter import SimpleListAdapter
+
+import re
+import random
+
+MAX_DICE = 40
+MAX_SKILL = 5
+INITIAL_RESULT_LABEL = "No result"
+
+class SlavedSlider(Slider):
+ pass
+
+class SlavedTextInput(TextInput):
+ pat = re.compile('[^0-9]')
+
+ def insert_text(self, substring, from_undo=False):
+ pat = self.pat
+ s = re.sub(pat, '', substring)
+ return super(SlavedTextInput, self).insert_text(s, from_undo=from_undo)
+
+class PaddedLabel(Label):
+ line_height = 2
+
+class TenraRoller(BoxLayout):
+
+ max_dice = NumericProperty(MAX_DICE)
+ max_skill = NumericProperty(MAX_SKILL)
+ initial_result_label_text = StringProperty(INITIAL_RESULT_LABEL)
+
+ dice_slider = ObjectProperty(None)
+ dice_text = ObjectProperty(None)
+ dice_value = BoundedNumericProperty(int(MAX_DICE / 2), min=1, max=MAX_DICE)
+
+ skill_slider = ObjectProperty(None)
+ skill_text = ObjectProperty(None)
+ skill_value = BoundedNumericProperty(int(MAX_SKILL / 2), min=1, max=MAX_SKILL)
+
+ result_label = ObjectProperty(None)
+ previous_results = ObjectProperty(None)
+
+ previous_results_la = SimpleListAdapter(data=[],
+ cls=PaddedLabel)
+
+
+ def slider_value_change(self, myid):
+ print("Slider {} changed to {}".format(myid, myid.value))
+ if myid == self.dice_slider:
+ self.dice_value = int(myid.value)
+ self.dice_text.text = str(self.dice_value)
+ if myid == self.skill_slider:
+ self.skill_value = int(myid.value)
+ self.skill_text.text = str(self.skill_value)
+
+ def text_value_change(self, myid):
+ print("Text {} changed to {}".format(myid, myid.text))
+ try:
+ if myid == self.skill_text:
+ self.skill_value = int(myid.text)
+ self.skill_slider.value = self.skill_value
+ if myid == self.dice_text:
+ self.dice_value = int(myid.text)
+ self.dice_slider.value = self.dice_value
+ except ValueError:
+ myid.background_color = [1, 0.5, 0.5, 1]
+ else:
+ myid.background_color = [1, 1, 1, 1]
+
+ # if myid == self.dice_text:
+ # self.dice_value = int(myid.text)
+ # self.dice_slider.value = self.dice_value
+ # if myid == self.skill_text:
+ # try:
+ # self.skill_value = int(myid.text)
+ # except ValueError:
+ # myid.background_color = [1, 0.5, 0.5, 1]
+ # else:
+ # myid.background_color = [1, 1, 1, 1]
+ # self.skill_slider.value = self.skill_value
+
+
+ def roll_dice(self):
+ successes = 0
+ for i in range(self.dice_value):
+ if random.randint(1, 6) <= self.skill_value:
+ successes += 1
+ if self.result_label.text != INITIAL_RESULT_LABEL:
+ self.previous_results_la.data = [self.result_label.text] + self.previous_results_la.data
+ self.result_label.text = 'Rolled {dice}({skill}) for {succ} successes'.format(dice=self.dice_value, skill=self.skill_value,
+ succ=successes)
+
+
+# def slider_value_change(slider, value):
+# print("Slider {} changed to {}".format(slider, value))
+
+class TenraRollerApp(App):
+ # dice_slider = ObjectProperty(None)
+ # dice_text = ObjectProperty(None)
+ # dice_value = BoundedNumericProperty(10, min=1, max=30)
+
+ def build(self):
+ roller = TenraRoller()
+ return roller
+
+
+if __name__ == '__main__':
+ TenraRollerApp().run()
--- /dev/null
+{
+ "folders":
+ [
+ {
+ "path": "."
+ }
+ ]
+}
--- /dev/null
+<SlavedSlider>:
+ orientation: 'horizontal'
+ min: 1
+ step: 1
+
+<SlavedTextInput>:
+ padding: [5, ( self.height - self.line_height ) / 2]
+ multiline: False
+
+<TenraRoller>:
+ dice_slider: dice_slider
+ dice_text: dice_text
+ skill_slider: skill_slider
+ skill_text: skill_text
+
+ roll_button: roll_button
+ result_label: result_label
+ previous_results: previous_results
+
+ BoxLayout:
+ orientation: 'vertical'
+ spacing: 10
+
+ BoxLayout:
+ orientation: 'horizontal'
+ spacing: 10
+ center_x: root.center_x
+ width: root.width
+ Label:
+ text: "Dice"
+ SlavedSlider:
+ id: dice_slider
+ max: root.max_dice
+ value: root.dice_value
+ on_value: root.slider_value_change(dice_slider)
+ SlavedTextInput:
+ id: dice_text
+ text: str(root.dice_value)
+ on_text: root.text_value_change(dice_text)
+
+
+ BoxLayout:
+ orientation: 'horizontal'
+ spacing: 10
+ width: root.width
+ Label:
+ text: "Skill"
+ SlavedSlider:
+ id: skill_slider
+ max: root.max_skill
+ value: root.skill_value
+ on_value: root.slider_value_change(skill_slider)
+ SlavedTextInput:
+ id: skill_text
+ on_text: root.text_value_change(skill_text)
+ text: str(root.skill_value)
+
+
+ Button:
+ id: roll_button
+ text: "Roll"
+ on_press: root.roll_dice()
+
+ Label:
+ id: result_label
+ bold: True
+ text: root.initial_result_label_text
+
+ ListView:
+ id: previous_results
+ adapter: root.previous_results_la