Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kvui: add autocompleting new hint text input #3535

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions data/client.kv
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,8 @@
rectangle: self.x-2, self.y-2, self.width+4, self.height+4
<ServerToolTip>:
pos_hint: {'center_y': 0.5, 'center_x': 0.5}
<AutocompleteHintInput>
size_hint_y: None
height: dp(30)
multiline: False
write_tab: False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing newline at end of file

61 changes: 58 additions & 3 deletions kvui.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from kivy.base import ExceptionHandler, ExceptionManager
from kivy.clock import Clock
from kivy.factory import Factory
from kivy.properties import BooleanProperty, ObjectProperty
from kivy.properties import BooleanProperty, ObjectProperty, NumericProperty
from kivy.metrics import dp
from kivy.effects.scroll import ScrollEffect
from kivy.uix.widget import Widget
Expand All @@ -61,6 +61,7 @@
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.animation import Animation
from kivy.uix.popup import Popup
from kivy.uix.dropdown import DropDown

fade_in_animation = Animation(opacity=0, duration=0) + Animation(opacity=1, duration=0.25)

Expand Down Expand Up @@ -299,6 +300,47 @@ def apply_selection(self, rv, index, is_selected):
self.selected = is_selected


class AutocompleteHintInput(TextInput):
min_chars = NumericProperty(3)

Berserker66 marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self, **kwargs):
super().__init__(**kwargs)

self.dropdown = DropDown()
self.dropdown.bind(on_select=lambda instance, x: setattr(self, 'text', x))
self.bind(on_text_validate=self.on_message)

def on_message(self, instance):
App.get_running_app().commandprocessor("!hint "+instance.text)

def on_text(self, instance, value):
if len(value) >= self.min_chars:
self.dropdown.clear_widgets()
ctx: context_type = App.get_running_app().ctx
item_names = ctx.item_names._game_store[ctx.game].values()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces a new mypy issue:

Invalid index type "str | None" for "dict[str, ChainMap[int, str]]"; expected type "str" [index]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically purely a typing issue, as the underlying class is a defaultdict. Maybe @ThePhar for comment, as he made the typing.

Berserker66 marked this conversation as resolved.
Show resolved Hide resolved

def on_press(button: Button):
split_text = MarkupLabel(text=button.text).markup
return self.dropdown.select("".join(text_frag for text_frag in split_text
if not text_frag.startswith("[")))
lowered = value.lower()
for item_name in item_names:
try:
index = item_name.lower().index(lowered)
except ValueError:
pass # substring not found
else:
text = escape_markup(item_name)
text = text[:index] + "[b]" + text[index:index+len(value)]+"[/b]"+text[index+len(value):]
btn = Button(text=text, size_hint_y=None, height=dp(30), markup=True)
btn.bind(on_release=on_press)
self.dropdown.add_widget(btn)
if not self.dropdown.attach_to:
self.dropdown.open(self)
else:
self.dropdown.dismiss()


class HintLabel(RecycleDataViewBehavior, BoxLayout):
selected = BooleanProperty(False)
striped = BooleanProperty(False)
Expand Down Expand Up @@ -535,7 +577,9 @@ def connect_bar_validate(sender):
self.tabs.add_widget(panel)

hint_panel = TabbedPanelItem(text="Hints")
self.log_panels["Hints"] = hint_panel.content = HintLog(self.json_to_kivy_parser)
self.hint_log = HintLog(self.json_to_kivy_parser)
self.log_panels["Hints"] = hint_panel.content = HintLayout()
hint_panel.content.add_widget(self.hint_log)
self.tabs.add_widget(hint_panel)

if len(self.logging_pairs) == 1:
Expand Down Expand Up @@ -654,7 +698,7 @@ def set_new_energy_link_value(self):

def update_hints(self):
hints = self.ctx.stored_data[f"_read_hints_{self.ctx.team}_{self.ctx.slot}"]
self.log_panels["Hints"].refresh_hints(hints)
self.hint_log.refresh_hints(hints)

# default F1 keybind, opens a settings menu, that seems to break the layout engine once closed
def open_settings(self, *largs):
Expand Down Expand Up @@ -709,6 +753,17 @@ def fix_heights(self):
element.height = element.texture_size[1]


class HintLayout(BoxLayout):
orientation = "vertical"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
boxlayout = BoxLayout(orientation="horizontal", size_hint_y=None, height=dp(30))
boxlayout.add_widget(Label(text="New Hint:", size_hint_x=None, size_hint_y=None, height=dp(30)))
boxlayout.add_widget(AutocompleteHintInput())
self.add_widget(boxlayout)


class HintLog(RecycleView):
header = {
"receiving": {"text": "[u]Receiving Player[/u]"},
Expand Down
Loading