From: Neil Smith Date: Tue, 10 May 2016 09:20:27 +0000 (+0100) Subject: Initial version X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=tenra-roller.git Initial version --- f1779c1f45e42b276db16cbf2cb3243f24685ebf diff --git a/.buildozer/android/app/main.py b/.buildozer/android/app/main.py new file mode 100644 index 0000000..a98e9c5 --- /dev/null +++ b/.buildozer/android/app/main.py @@ -0,0 +1,113 @@ +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() diff --git a/.buildozer/android/app/sitecustomize.py b/.buildozer/android/app/sitecustomize.py new file mode 100644 index 0000000..6650864 --- /dev/null +++ b/.buildozer/android/app/sitecustomize.py @@ -0,0 +1,3 @@ +from os.path import join, dirname +import sys +sys.path.append(join(dirname(__file__), '_applibs')) diff --git a/.buildozer/android/app/tenraroller.kv b/.buildozer/android/app/tenraroller.kv new file mode 100644 index 0000000..62f9462 --- /dev/null +++ b/.buildozer/android/app/tenraroller.kv @@ -0,0 +1,72 @@ +: + +: + +: + 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 diff --git a/.buildozer/android/platform/python-for-android b/.buildozer/android/platform/python-for-android new file mode 160000 index 0000000..5674bce --- /dev/null +++ b/.buildozer/android/platform/python-for-android @@ -0,0 +1 @@ +Subproject commit 5674bced02508dcaa75c798706ea05b7b45eea34 diff --git a/.buildozer/android/platform/python-for-android-master b/.buildozer/android/platform/python-for-android-master new file mode 160000 index 0000000..f343c14 --- /dev/null +++ b/.buildozer/android/platform/python-for-android-master @@ -0,0 +1 @@ +Subproject commit f343c147696e6093204f4d0614480636ec732d85 diff --git a/.buildozer/state.db b/.buildozer/state.db new file mode 100644 index 0000000..8e12ebf --- /dev/null +++ b/.buildozer/state.db @@ -0,0 +1 @@ +{"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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0546add --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +*.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 diff --git a/buildozer.spec b/buildozer.spec new file mode 100644 index 0000000..0b0e3c7 --- /dev/null +++ b/buildozer.spec @@ -0,0 +1,227 @@ +[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 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: ()" + +# (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 diff --git a/main.py b/main.py new file mode 100644 index 0000000..5e599e2 --- /dev/null +++ b/main.py @@ -0,0 +1,117 @@ +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() diff --git a/tenra-roller.sublime-project b/tenra-roller.sublime-project new file mode 100644 index 0000000..24db303 --- /dev/null +++ b/tenra-roller.sublime-project @@ -0,0 +1,8 @@ +{ + "folders": + [ + { + "path": "." + } + ] +} diff --git a/tenraroller.kv b/tenraroller.kv new file mode 100644 index 0000000..b2b0067 --- /dev/null +++ b/tenraroller.kv @@ -0,0 +1,71 @@ +: + orientation: 'horizontal' + min: 1 + step: 1 + +: + padding: [5, ( self.height - self.line_height ) / 2] + multiline: False + +: + 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