icons, timers, menus, player setup

This commit is contained in:
Sander Land committed 2020-05-27 23:08:12 +02:00
1 parent c92d144519
commit e0bfa3c416
26 files changed
+411 -148

No files matched your search

+2 -4
View File
@@ -4,10 +4,8 @@ This repository includes:
For on related licenses for these binaries and libraries see https://github.com/lightvector/KataGo
2. Icons from www.flaticon.com, used with permission with the following attributions:
- New game/Load game/Config/Config clock icons: made by Freepik from www.flaticon.com
- Flag icons: made by Freepik from www.flaticon.com
- Save icon, Pause Icon: made by Pixel perfect from www.flaticon.com
- Next/Previous icons: made by/derived from ones made by RoundIcons from www.flaticon.com
- New game/Save game/Load game/Configure icons/Flag icons: made by or derived from work by Freepik from www.flaticon.com
- Next/Previous icons: derived from work by RoundIcons from www.flaticon.com
3. The True Type Font DIGITAL-7 version 1.02 by Sizenko Alexander, which is free for non-commercial use.
+40 -1
View File
@@ -22,7 +22,7 @@ from kivy.storage.jsonstore import JsonStore
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import Screen
from kivymd.app import MDApp
from katrain.core.constants import *
from katrain.core.ai import ai_move
from katrain.core.utils import (
DEFAULT_LANGUAGE,
@@ -36,6 +36,8 @@ from katrain.core.utils import (
MODE_PLAY,
switch_lang,
)
from katrain.gui.popups import ConfigTeacherPopup, ConfigTimerPopup
from katrain.gui.ai_settings import ConfigAIPopupContents
from katrain.core.engine import KataGoEngine
from katrain.core.game import Game, IllegalMoveException, KaTrainSGF
from katrain.core.sgf_parser import Move, ParseError
@@ -60,9 +62,14 @@ class KaTrainGui(Screen):
self.debug_level = 0
self.engine = None
self.game = None
self.new_game_popup = None
self.fileselect_popup = None
self.config_popup = None
self.ai_settings_popup = None
self.teacher_settings_popup = None
self.timer_settings_popup = None
self.logger = lambda message, level=OUTPUT_INFO: self.log(message, level)
self.config_file = self._load_config()
@@ -114,9 +121,14 @@ class KaTrainGui(Screen):
except KeyError:
self.log(f"Missing configuration option {setting}", OUTPUT_ERROR)
@property
def play_analyze_mode(self):
return self.play_mode.play_analyze_mode
@property
def ai_strategies(self):
return list(self.config("ai").keys())
def start(self):
if self.engine:
return
@@ -262,6 +274,7 @@ class KaTrainGui(Screen):
self.fileselect_popup.open()
def _do_new_game_popup(self):
self.controls.timer.paused = True
if not self.new_game_popup:
self.new_game_popup = Popup(title="New Game", size_hint=(0.5, 0.6)).__self__
popup_contents = NewGamePopup(self, self.new_game_popup, {k: v[0] for k, v in self.game.root.properties.items() if len(v) == 1})
@@ -269,12 +282,34 @@ class KaTrainGui(Screen):
self.new_game_popup.open()
def _do_config_popup(self):
self.controls.timer.paused = True
if not self.config_popup:
self.config_popup = Popup(title=f"Edit Settings - {self.config_file}", size_hint=(0.9, 0.9)).__self__
popup_contents = ConfigPopup(self, self.config_popup, dict(self._config), ignore_cats=("trainer", "ai"))
self.config_popup.add_widget(popup_contents)
self.config_popup.open()
def _do_ai_popup(self):
self.controls.timer.paused = True
if not self.ai_settings_popup: # persist state of popup etc
self.ai_settings_popup = Popup(title="Edit AI Settings", size_hint=(0.7, 0.8)).__self__
self.ai_settings_popup.add_widget(ConfigAIPopupContents(self, self.ai_settings_popup))
self.ai_settings_popup.open()
def _do_teacher_popup(self):
self.controls.timer.paused = True
if not self.teacher_settings_popup:
self.teacher_settings_popup = Popup(title="Edit Teacher Settings", size_hint=(0.7, 0.8)).__self__
self.teacher_settings_popup.add_widget(ConfigTeacherPopup(self, self.teacher_settings_popup))
self.teacher_settings_popup.open()
def _do_timer_popup(self):
self.controls.timer.paused = True
if not self.timer_settings_popup:
self.timer_settings_popup = Popup(title="Edit Timer Settings", size_hint=(0.4, 0.4)).__self__
self.timer_settings_popup.add_widget(ConfigTimerPopup(self, self.timer_settings_popup))
self.timer_settings_popup.open()
def _do_output_sgf(self):
for pl in Move.PLAYERS:
if not self.game.root.get_property(f"P{pl}"):
@@ -329,6 +364,10 @@ class KaTrainGui(Screen):
"p": ("play", None),
"right": ("switch-branch", 1),
"left": ("switch-branch", -1),
"f5": ("timer-popup",),
"f6": ("teacher-popup",),
"f7": ("ai-popup",),
"f8": ("config-popup",),
}
def _on_keyboard_down(self, _keyboard, keycode, _text, modifiers):
+7
View File
@@ -0,0 +1,7 @@
PLAYER_HUMAN, PLAYER_AI = "player:human", "player:ai"
PLAYER_TYPES = [PLAYER_HUMAN, PLAYER_AI]
PLAYING_NORMAL, PLAYING_TEACHING = "game:normal", "game:teach"
GAME_TYPES = [PLAYING_NORMAL, PLAYING_TEACHING]
AI_DEFAULT = "default"
+1 -5
View File
@@ -9,6 +9,7 @@ from katrain.core.utils import var_to_grid, OUTPUT_INFO, OUTPUT_DEBUG, i18n
from katrain.core.engine import KataGoEngine
from katrain.core.game_node import GameNode
from katrain.core.sgf_parser import SGF, Move
from katrain.core.constants import *
class IllegalMoveException(Exception):
@@ -19,11 +20,6 @@ class KaTrainSGF(SGF):
_NODE_CLASS = GameNode
PLAYER_HUMAN, PLAYER_AI = "Player", "AI"
PLAYING_NORMAL, PLAYING_TEACHING = "Normal game", "Teaching game"
AI_DEFAULT = "default"
class Player:
def __init__(self, player="B", player_type=PLAYER_HUMAN, player_subtype=PLAYING_NORMAL, periods_used=0):
self.player = player
+4 -8
View File
@@ -57,8 +57,6 @@ def find_package_resource(path):
return path # absolute path
class Lang(Observable):
observers = []
callbacks = []
@@ -69,8 +67,8 @@ class Lang(Observable):
self.switch_lang(lang)
def _(self, text):
if text=='':
return '' # just for font change
if text == "":
return "" # just for font change
return self.ugettext(text)
def fbind(self, name, func, *args):
@@ -90,9 +88,8 @@ class Lang(Observable):
else:
return super(Lang, self).funbind(name, func, *args)
def add_callback(self,callback_fn: Callable):
def add_callback(self, callback_fn: Callable):
self.callbacks.append(callback_fn)
print("ADDING CB")
def switch_lang(self, lang):
# get the right locales directory, and instantiate a gettext
@@ -113,9 +110,8 @@ class Lang(Observable):
for cb in self.callbacks:
try:
cb(self)
print("CALLING CB")
except Exception as e:
print(f"Failed callback on language change: {e}",file=sys.stderr)
print(f"Failed callback on language change: {e}", file=sys.stderr)
DEFAULT_LANGUAGE = "en"
+142 -71
View File
@@ -9,6 +9,7 @@
#:set GRAPH_DOT_COLOR [0.85, 0.3, 0.3,1]
#-- NEW
#:import PLAYER_TYPES __main__.PLAYER_TYPES
#:import RED __main__.RED
#:import WHITE __main__.WHITE
@@ -124,8 +125,7 @@
<AutoSizedRoundedRectangleButton@AutoSizedRectangleButton>:
background_radius: self.height/3.5
<BGMDBoxLayout@MDBoxLayout+BackgroundMixin>:
<BGMDBoxLayout>:
background_color: BOX_BACKGROUND_COLOR
<TransparentIconButton>:
@@ -140,14 +140,35 @@
mipmap: True
<StyledSpinnerOption@SpinnerOption>:
background_color: BACKGROUND_COLOR
background_normal: ''
lang_change_tracking: i18n._('') # for font
color: WHITE
canvas.after:
Color:
rgba: LIGHTGREY
Line
points: self.pos[0],self.pos[1],self.pos[0]+self.width,self.pos[1]
width: 1
<StyledSpinner>:
text: self.values[0] if self.values else ''
font_size: self.height * 0.5
sync_height_frac: 1.0
background_color: [*[c*255/88 for c in BACKGROUND_COLOR[:3]], 1] # compensate for texture
option_cls: 'StyledSpinnerOption'
# -- old widgets
<StyledButton>:
color: WHITE
font_size: self.size[1] * 0.45
radius: (self.size[1]/7,)
font_size: self.height * 0.45
radius: (self.height/7,)
button_color: BUTTON_COLOR
button_color_down: [0.105, 0.14, 0.155, 1]
button_color_highlight: [(a+b)/2 for a,b in zip(self.button_color,self.button_color_down)]
@@ -157,27 +178,10 @@
Color:
rgba: self.button_color if root.state=='normal' else self.button_color_down
RoundedRectangle:
size: self.size[0],self.size[1]
size: self.size[0],self.height
pos: (self.pos[0],self.pos[1])
radius: root.radius
<StyledSpinnerOption@SpinnerOption>:
background_color: BUTTON_COLOR
background_normal: ''
color: WHITE
canvas.after:
Color:
rgba: WHITE
Line
points: self.pos[0],self.pos[1],self.pos[0]+self.width,self.pos[1]
width: 1
<StyledSpinner>:
text: self.values[0] if self.values else ''
font_size: self.size[1] * 0.33
sync_height_frac: 0.7
background_color: [*[c*255/88 for c in BUTTON_COLOR[:3]], 1] # compensate for texture
option_cls: 'StyledSpinnerOption'
<StyledToggleButton>:
max_lines: 1
@@ -185,19 +189,19 @@
<ToggleButtonContainer>:
<LabelledTextInput>:
padding: 3, 0.27*self.size[1]
font_size: 0.4*self.size[1]
padding: 3, 0.27*self.height
font_size: 0.4*self.height
<LabelledIntInput>:
font_size: 0.5*self.size[1]
padding: 7, 0.2*self.size[1]
font_size: 0.5*self.height
padding: 7, 0.2*self.height
<LabelledFloatInput>:
font_size: 0.5*self.size[1]
padding: 7, 0.2*self.size[1]
font_size: 0.5*self.height
padding: 7, 0.2*self.height
<LabelledTextArea>
font_size: 0.2*self.size[1]
font_size: 0.2*self.height
<CheckBox>:
color: BLACK
@@ -211,7 +215,7 @@
button_color_down: ICON_BUTTON_COLOR_DOWN
icon_margin: 0.15 * self.size[0]
icon: ''
icon_size: min(self.size[0]-2*self.icon_margin,self.size[1]-2*self.icon_margin)
icon_size: min(self.size[0]-2*self.icon_margin,self.height-2*self.icon_margin)
Image:
size: (root.icon_size or 0,root.icon_size or 0) # square
pos: [root.pos[i] + (root.size[i] - root.icon_size)/2 for i in [0,1]] if root.icon_size else [0,0]
@@ -228,10 +232,10 @@
<ScaledLightLabel>: # popups
color: TEXT_COLOR
font_size: 0.45*self.size[1]/self.num_lines
font_size: 0.45*self.height/self.num_lines
<LightHelpLabel>:
font_size: self.size[1]/10
font_size: self.height/10
halign: 'center'
valign: 'middle'
multiline: True
@@ -249,7 +253,7 @@
id: image
pos: (root.pos[0] + (root.width - root.min_size)/2,root.pos[1] + (root.height - root.min_size)/2)
size: (root.min_size,root.min_size)
source: 'img/white.png' if root.player=='White' else 'img/black.png'
source: 'img/white.png' if root.player=='W' else 'img/black.png'
mipmap: True
Label:
id: lbl
@@ -257,7 +261,7 @@
text_size: None, root.min_size
bold: True
valign: 'center'
color: BLACK if root.player=='White' else WHITE
color: BLACK if root.player=='W' else WHITE
pos: (image.x, image.y)
size: image.size
font_size: root.min_size * 1.2 / (1 + 1 * len(self.text))
@@ -271,7 +275,7 @@
<NavIconButton@TransparentIconButton>:
size_hint: 0.06, 0.4
icon_size: [min(self.size[0],self.size[1]),min(self.size[0],self.size[1])]
icon_size: [min(self.size[0],self.height),min(self.size[0],self.height)]
pos_hint: {'center_y': 0.5}
<BadukPanControls>:
@@ -308,13 +312,13 @@
size_hint: 5/8, 1
pos_hint: {'center_x': 0.5-3/16}
id: black_circle
player: 'Black'
player: 'B'
text: ''
CircleWithText:
size_hint: 5/8, 1
pos_hint: {'center_x': 0.5+3/16}
id: white_circle
player: 'White'
player: 'W'
text: ''
NavIconButton:
icon: 'img/flaticon/next.png'
@@ -326,7 +330,7 @@
icon: 'img/flaticon/next999.png'
on_press: root.katrain('redo',999)
NavIconButton:
icon: 'img/flaticon/route.png'
icon: 'img/forward_-_child.png'
on_press: root.katrain('switch-branch',1)
ClickableLabel:
pos_hint: {'center_x': 0.85,'center_y':0.5}
@@ -349,13 +353,13 @@
<HamburgerButton@TransparentIconButton>:
icon: 'img/hamburger.png'
width: self.height
icon_size: [self.height * 0.8, self.height * 0.8]
icon_size: [self.height * 0.6, self.height * 0.6]
# ---------- components of right pane -------
<PlayerInfo>:
captures: 0
player: 'Black'
player: 'B'
player_type: 'Player'
player_subtype: 'Normal game'
background_color: BOX_BACKGROUND_COLOR if self.active else BACKGROUND_COLOR
@@ -420,23 +424,38 @@
color: GREEN
markup: True
multiline: False
font_name: 'fonts/digital-7.ttf'
font_name: 'fonts/digital-7 (mono).ttf'
<Timer@BGMDBoxLayout>:
state: (30,5,1)
<Timer>:
spacing: CP_SPACING
padding: CP_PADDING * 4, CP_PADDING * 2
paused: True
MDBoxLayout:
size_hint: 0.7,1
TimerLabel:
MDFloatLayout:
canvas.before:
Color:
rgba: GREEN
Line:
rectangle: (*self.pos,*self.size)
width: 1
size_hint: 0.4,1
id: timer
text_size: self.size
halign: 'right'
valign: 'middle'
font_size: 0.85*self.size[1]
text: f"{root.state[0]//60}:{int(root.state[0] % 60):02d}"
TimerLabel:
color: BACKGROUND_COLOR
text: '8:88'
text_size: self.size
font_size: 0.85*self.height
pos_hint: {'right':1,'center_y':0.5}
halign: 'right'
valign: 'middle'
TimerLabel:
id: timer
text: "{:01d}:{:02d}".format(int(root.state[0])//60,int(root.state[0] % 60) )
text_size: self.size
font_size: 0.85*self.height
pos_hint: {'right':1,'center_y':0.5}
halign: 'right'
valign: 'middle'
TimerLabel:
size_hint: 0.05,1
text: "x"
@@ -552,7 +571,7 @@
size_hint: 0.6,1
id: desc
text: root.label if not root.hidden else ''
font_size: self.size[1] * 0.7
font_size: self.height * 0.7
font_name: root.font_name
text_size: self.size
valign: 'middle'
@@ -658,10 +677,10 @@
height: root.player_box_height
PlayerInfo:
id: B_player
player: 'Black'
player: 'B'
PlayerInfo:
id: W_player
player: 'White'
player: 'W'
BoxLayout:
size_hint_y: None
height: root.timer_box_height
@@ -867,22 +886,54 @@
size_hint: 1,None
<PlayerSetup@MDBoxLayout>:
<PlayerSetup>:
orientation: 'horizontal'
CircleWithText:
text: root.player[0]
player: root.player
Label:
text: 'type'
Label:
text: 'subtype'
spacing: CP_SPACING
padding: 0, CP_PADDING
player_type: player_type
player_subtype: player_subtype
player_subtype_label: player_subtype_label
MDBoxLayout:
size_hint: 0.25, 1
CircleWithText:
size_hint: 0.8, 0.8
pos_hint: {'center_x':0.5,'center_y':0.5}
text: root.player[0]
player: root.player
MDBoxLayout:
size_hint: 0.5, 1
orientation: 'vertical'
spacing: CP_SPACING
Label:
text: i18n._('player:type')
font_size: self.height * 0.5
StyledSpinner:
id: player_type
value_refs: PLAYER_TYPES
on_text: root.setup_options(*args)
MDBoxLayout:
size_hint: 0.5, 1
orientation: 'vertical'
spacing: CP_SPACING
Label:
text: 'Player Type'
id: player_subtype_label
font_size: self.height * 0.5
StyledSpinner:
id: player_subtype
value_refs: []
on_text: root.set_player()
<PlayerSetupBlock@MDBoxLayout>:
orientation: 'vertical'
size_hint_y: None
spacing: 3*CP_SPACING
padding: CP_PADDING
height: (self.parent.item_height or 50) * 5
PlayerSetup:
player: 'Black'
player: 'B'
PlayerSetup:
player: 'White'
player: 'W'
<ContentNavigationDrawer@MDBoxLayout+BackgroundMixin>:
katrain: app.gui
@@ -892,6 +943,8 @@
MenuLabel:
text: i18n._('menu:playersetup')
PlayerSetupBlock:
MenuLabel:
size_hint: 1,1
MenuLabel:
MDBoxLayout:
orientation: 'vertical'
@@ -906,17 +959,33 @@
height: root.item_height
MainMenuItem:
text: i18n._('menu:save')
icon: 'img/flaticon/savegame.png'
icon: 'img/flaticon/floppy-disk.png'
shortcut: 'Ctrl-S'
on_action: root.katrain("analyze-sgf-popup")
MainMenuItem:
text: i18n._('menu:load')
icon: 'img/flaticon/loadgame.png'
icon: 'img/flaticon/folder.png'
shortcut: 'Ctrl-L'
on_action: root.katrain("analyze-sgf-popup")
MainMenuItem:
text: i18n._('menu:clocksettings')
icon: 'img/flaticon/cogwheel.png'
shortcut: 'F5'
on_action: root.katrain('timer-popup')
MainMenuItem:
text: i18n._('menu:teachsettings')
icon: 'img/flaticon/graduate.png'
shortcut: 'F6'
on_action: root.katrain('teacher-popup')
MainMenuItem:
text: i18n._('menu:aisettings')
icon: 'img/flaticon/ai.png'
shortcut: 'F7'
on_action: root.katrain('ai-popup')
MainMenuItem:
text: i18n._('menu:settings')
icon: 'img/flaticon/settings.png'
shortcut: 'F8'
on_action: root.katrain('config-popup')
MenuLabel:
text: i18n._('menu:lang')
@@ -949,6 +1018,8 @@
allow_no_selection: False
<PlayAnalyzeSelect>:
play: play
analyze: analyze
OutlineBox:
outline_color: WHITE
size_hint: 0.7,0.7
@@ -1072,8 +1143,8 @@
text: "Size"
LabelledTextInput:
text: '19'
font_size: 0.5*self.size[1]
padding: 7, 0.2*self.size[1]
font_size: 0.5*self.height
padding: 7, 0.2*self.height
input_property: 'SZ'
BoxLayout:
spacing: 1
@@ -1125,21 +1196,21 @@
color: WHITE
id: restart
ScaledLightLabel:
font_size: 0.35*self.size[1]
font_size: 0.35*self.height
text: 'avoids replaying\nidentical games'
LightHelpLabel:
text: "Use x:y (e.g. 19:9) to play on a non-square board."
size_hint: 1,2
text_size: self.width-6, None
font_size: self.size[1]/6
font_size: self.height/6
id: info
LightHelpLabel:
text: "Note that handicaps above 9 are not supported on non-square boards."
font_size: self.size[1]/6
font_size: self.height/6
text_size: self.width-6, None
id: info
StyledButton:
halign: 'center'
text: 'Start\nGame'
font_size: 0.3 * self.size[1]
font_size: 0.3 * self.height
on_left_press: if not self.last_touch or self.last_touch.button=="left": root.new_game()
+8 -31
View File
@@ -7,9 +7,7 @@ from kivy.uix.popup import Popup
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from katrain.core.utils import MODE_PLAY, MODE_ANALYZE
from katrain.gui.popups import ConfigTeacherPopup, ConfigTimerPopup
from katrain.gui.ai_settings import ConfigAIPopupContents
from katrain.core.utils import MODE_PLAY, MODE_ANALYZE, i18n
class PlayAnalyzeSelect(MDFloatLayout):
@@ -18,13 +16,13 @@ class PlayAnalyzeSelect(MDFloatLayout):
@property
def play_analyze_mode(self):
return MODE_PLAY if self.play_mode.play.status == "down" else MODE_ANALYZE
return MODE_PLAY if self.play.active else MODE_ANALYZE
def switch_mode(self): # TODO: load settings
if self.play_analyze_mode == MODE_PLAY:
self.play.trigger_action(duration=0)
else:
self.analyze.trigger_action(duration=0)
else:
self.play.trigger_action(duration=0)
class ControlsPanel(BoxLayout):
@@ -35,15 +33,14 @@ class ControlsPanel(BoxLayout):
super(ControlsPanel, self).__init__(**kwargs)
self.status_msg = None
self.status_node = None
self.ai_settings_popup = None
self.teacher_settings_popup = None
self.active_comment_node = None
self.timer_settings_popup = None
self.last_timer_update = (None, 0)
Clock.schedule_interval(self.update_timer, 0.07)
def check_hide_show(self, *_args):
pass
def update_players(self, *_args):
for player, info in self.katrain.game.players.items():
self.players[player].player_type = i18n._(info.player_type)
self.players[player].player_subtype = i18n._(info.player_subtype)
def set_status(self, msg, at_node=None):
self.status_msg = msg
@@ -62,7 +59,6 @@ class ControlsPanel(BoxLayout):
self.status.text = ""
self.status_node = None
both_players_are_robots = all(p.ai for p in game.players.values())
last_player_was_ai_playing_human = game.last_player.ai and game.next_player.human
self.active_comment_node = current_node
@@ -92,18 +88,6 @@ class ControlsPanel(BoxLayout):
self.note.text = current_node.note
self.info.text = info
def configure_ais(self):
if not self.ai_settings_popup: # persist state of popup etc
self.ai_settings_popup = Popup(title="Edit AI Settings", size_hint=(0.7, 0.8)).__self__
self.ai_settings_popup.add_widget(ConfigAIPopupContents(self.katrain, self.ai_settings_popup, self.katrain.config("ai")))
self.ai_settings_popup.open()
def configure_teacher(self):
if not self.teacher_settings_popup:
self.teacher_settings_popup = Popup(title="Edit Teacher Settings", size_hint=(0.7, 0.8)).__self__
self.teacher_settings_popup.add_widget(ConfigTeacherPopup(self.katrain, self.teacher_settings_popup))
self.teacher_settings_popup.open()
def update_timer(self, _dt):
current_node = self.katrain and self.katrain.game and self.katrain.game.current_node
if current_node:
@@ -127,10 +111,3 @@ class ControlsPanel(BoxLayout):
time_remaining = byo_len - current_node.time_used
periods_rem = byo_num - player.periods_used
self.timer.state = (time_remaining, periods_rem, ai)
def configure_timer(self):
self.pause.state = "down"
if not self.timer_settings_popup:
self.timer_settings_popup = Popup(title="Edit Timer Settings", size_hint=(0.4, 0.4)).__self__
self.timer_settings_popup.add_widget(ConfigTimerPopup(self.katrain, self.timer_settings_popup))
self.timer_settings_popup.open()
+88 -28
View File
@@ -13,7 +13,7 @@ from kivy.uix.filechooser import FileChooserLayout, FileChooserListLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.spinner import Spinner
from kivy.uix.spinner import Spinner, SpinnerOption
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
@@ -25,6 +25,8 @@ from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import BasePressedButton, BaseFlatButton
from kivymd.uix.navigationdrawer import MDNavigationDrawer
from kivy.core.text import Label as CoreLabel
from katrain.core.constants import GAME_TYPES
from katrain.core.utils import i18n
#
@@ -97,6 +99,10 @@ class ToggleButtonMixin(ToggleButtonBehavior):
inactive_background_color = ListProperty([0.5, 0.5, 0.5, 1])
active_background_color = ListProperty([1, 1, 1, 1])
@property
def active(self):
return self.state == "down"
class SizedToggleButton(ToggleButtonMixin, SizedButton):
pass
@@ -156,24 +162,101 @@ class MyNavigationDrawer(MDNavigationDrawer): # in PR - closes NavDrawer on any
class CircleWithText(Widget):
text = StringProperty("0")
player = OptionProperty("Black", options=["Black", "White"])
player = OptionProperty("B", options=["B", "W"])
min_size = NumericProperty(50)
class BGMDBoxLayout(MDBoxLayout, BackgroundMixin):
pass
# -- new gui elements
class StyledSpinner(Spinner):
sync_height_frac = NumericProperty(1.0)
value_refs = ListProperty()
font_name = StringProperty(DEFAULT_FONT)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(size=self.update_dropdown_props, pos=self.update_dropdown_props, value_refs=self.i18n_values)
self.i18n_values()
@property
def selected(self):
try:
selected = self.values.index(self.text)
return selected, self.value_refs[selected], self.values[selected]
except (ValueError, IndexError):
return 0, "", ""
def i18n_values(self, *_args):
if self.value_refs:
selected = self.selected[0]
self.values = [i18n._(ref) for ref in self.value_refs]
print(self.selected, self.values, self.value_refs)
self.text = self.values[selected]
self.font_name = i18n.font_name
self.update_dropdown_props()
def update_dropdown_props(self, *largs):
if not self.sync_height_frac:
return
dp = self._dropdown
if not dp:
return
container = dp.container
if not container:
return
h = self.height
fsz = self.font_size
for item in container.children[:]:
item.height = h * self.sync_height_frac
item.font_size = fsz
item.font_name = self.font_name
class PlayerSetup(MDBoxLayout):
player = OptionProperty("Black", options=["Black", "White"])
player = OptionProperty("B", options=["B", "W"])
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self.setup_options, 0)
def setup_options(self, *_args):
self.player_subtype.clear_widgets()
if self.player_type.selected[0] == 0: # human
self.player_subtype_label.text = i18n._("gametype")
self.player_subtype.value_refs = GAME_TYPES
else:
self.player_subtype_label.text = i18n._("aistrategy")
self.player_subtype.value_refs = MDApp.get_running_app().gui.ai_strategies # TODO:
self.player_subtype.text = self.player_subtype.values[0]
self.set_player()
def set_player(self):
katrain = MDApp.get_running_app().gui
game = katrain and katrain.game
if game:
game.players[self.player].player_type = self.player_type.selected[1]
game.players[self.player].player_subtype = self.player_subtype.selected[1]
katrain.controls.update_players()
katrain.update_state()
class PlayerInfo(MDBoxLayout, BackgroundMixin):
captures = NumericProperty(0)
player = OptionProperty("Black", options=["Black", "White"])
player = OptionProperty("B", options=["B", "W"])
player_type = StringProperty("Player")
player_subtype = StringProperty("")
active = BooleanProperty(True)
class Timer(BGMDBoxLayout):
state = ListProperty([30, 5, 1])
class AnalysisToggle(MDBoxLayout):
text = StringProperty("")
default_active = BooleanProperty(False)
@@ -398,29 +481,6 @@ class StyledToggleButton(StyledButton, ToggleButtonBehavior, ToolTipBehavior):
self.state = "normal" if self.state == "down" else "down"
class StyledSpinner(Spinner):
sync_height_frac = NumericProperty(1.0)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(size=self._update_dropdown_size_frac, pos=self._update_dropdown_size_frac)
def _update_dropdown_size_frac(self, *largs):
if not self.sync_height_frac:
return
dp = self._dropdown
if not dp:
return
container = dp.container
if not container:
return
h = self.height
fsz = self.font_size
for item in container.children[:]:
item.height = h * self.sync_height_frac
item.font_size = fsz
class ToggleButtonContainer(GridLayout):
__events__ = ("on_selection",)
@@ -544,7 +604,7 @@ class LabelledIntInput(LabelledTextInput):
def draw_text(pos, text, font_name=None, **kw):
label = CoreLabel(text=text, bold=True, font_name=font_name or i18n.font, **kw) #
label = CoreLabel(text=text, bold=True, font_name=font_name or i18n.font_name, **kw) #
label.refresh()
Rectangle(texture=label.texture, pos=(pos[0] - label.texture.size[0] / 2, pos[1] - label.texture.size[1] / 2), size=label.texture.size)
Binary file not shown.
@@ -22,12 +22,43 @@ msgstr "Load Game"
msgid "menu:settings"
msgstr "General Settings"
msgid "menu:clocksettings"
msgstr "Timer Settings"
msgid "menu:teachsettings"
msgstr "Teaching Game Settings"
msgid "menu:aisettings"
msgstr "AI Settings"
msgid "menu:lang"
msgstr "Language"
msgid "menu:support"
msgstr "Support or Contribute"
#. player options in the setup and on the right
msgid "player:type"
msgstr "Player"
msgid "player:human"
msgstr "Human"
msgid "player:ai"
msgstr "AI"
msgid "aistrategy"
msgstr "AI Strategy"
msgid "gametype"
msgstr "Game Type"
msgid "game:normal"
msgstr "Normal Game"
msgid "game:teach"
msgstr "Teaching Game"
#. buttons at the top - should all include a line break
msgid "analysis:nextmoves"
msgstr ""
Binary file not shown.
@@ -227,3 +227,47 @@ msgstr "Support or Contribute"
#. TODO
msgid "wait-before-equalize"
msgstr "Wait for initial analysis to complete before requesting a refinement."
#. TODO
msgid "game:teaching"
msgstr "Teaching Game"
#. TODO
msgid "aistrategy"
msgstr "AI Strategy"
#. TODO
msgid "game:normal"
msgstr "Normal Game"
#. TODO
msgid "player:human"
msgstr "AI"
#. TODO
msgid "player:type"
msgstr "Player"
#. TODO
msgid "gametype"
msgstr "Game Type"
#. TODO
msgid "player:ai"
msgstr "AI"
#. TODO
msgid "game:teach"
msgstr "Teaching Game"
#. TODO
msgid "menu:clocksettings"
msgstr "Timer Settings"
#. TODO
msgid "menu:teachsettings"
msgstr "Teaching Game Settings"
#. TODO
msgid "menu:aisettings"
msgstr "AI Settings"
Binary file not shown.
@@ -259,3 +259,47 @@ msgstr "Support or Contribute"
#. TODO
msgid "wait-before-equalize"
msgstr "Wait for initial analysis to complete before requesting a refinement."
#. TODO
msgid "game:teaching"
msgstr "Teaching Game"
#. TODO
msgid "aistrategy"
msgstr "AI Strategy"
#. TODO
msgid "game:normal"
msgstr "Normal Game"
#. TODO
msgid "player:human"
msgstr "AI"
#. TODO
msgid "player:type"
msgstr "Player"
#. TODO
msgid "gametype"
msgstr "Game Type"
#. TODO
msgid "player:ai"
msgstr "AI"
#. TODO
msgid "game:teach"
msgstr "Teaching Game"
#. TODO
msgid "menu:clocksettings"
msgstr "Timer Settings"
#. TODO
msgid "menu:teachsettings"
msgstr "Teaching Game Settings"
#. TODO
msgid "menu:aisettings"
msgstr "AI Settings"
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB