1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2024-11-16 20:29:02 +00:00
dupeguru/hscommon/gui/text_field.py

111 lines
3.4 KiB
Python
Raw Normal View History

2019-09-10 00:54:28 +00:00
# Created On: 2012/01/23
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
2019-09-10 00:54:28 +00:00
# http://www.gnu.org/licenses/gpl-3.0.html
from .base import GUIObject
from ..util import nonone
2019-09-10 00:54:28 +00:00
class TextFieldView:
"""Expected interface for :class:`TextField`'s view.
2019-09-10 00:54:28 +00:00
*Not actually used in the code. For documentation purposes only.*
2019-09-10 00:54:28 +00:00
Our view is expected to sync with :attr:`TextField.text` "both ways", that is, update the
model's text when the user types something, but also update the text field when :meth:`refresh`
is called.
"""
2019-09-10 00:54:28 +00:00
def refresh(self):
"""Refreshes the contents of the input widget.
2019-09-10 00:54:28 +00:00
Ensures that the contents of the input widget is actually :attr:`TextField.text`.
"""
2019-09-10 00:54:28 +00:00
class TextField(GUIObject):
"""Cross-toolkit text field.
2019-09-10 00:54:28 +00:00
Represents a UI element allowing the user to input a text value. Its main attribute is
:attr:`text` which acts as the store of the said value.
2019-09-10 00:54:28 +00:00
When our model value isn't a string, we have a built-in parsing/formatting mechanism allowing
us to directly retrieve/set our non-string value through :attr:`value`.
2019-09-10 00:54:28 +00:00
Subclasses :class:`.GUIObject`. Expected view: :class:`TextFieldView`.
"""
2019-09-10 00:54:28 +00:00
def __init__(self):
GUIObject.__init__(self)
self._text = ""
2019-09-10 00:54:28 +00:00
self._value = None
# --- Virtual
2019-09-10 00:54:28 +00:00
def _parse(self, text):
"""(Virtual) Parses ``text`` to put into :attr:`value`.
2019-09-10 00:54:28 +00:00
Returns the parsed version of ``text``. Called whenever :attr:`text` changes.
"""
return text
2019-09-10 00:54:28 +00:00
def _format(self, value):
"""(Virtual) Formats ``value`` to put into :attr:`text`.
2019-09-10 00:54:28 +00:00
Returns the formatted version of ``value``. Called whenever :attr:`value` changes.
"""
return value
2019-09-10 00:54:28 +00:00
def _update(self, newvalue):
"""(Virtual) Called whenever we have a new value.
2019-09-10 00:54:28 +00:00
Whenever our text/value store changes to a new value (different from the old one), this
method is called. By default, it does nothing but you can override it if you want.
"""
# --- Override
2019-09-10 00:54:28 +00:00
def _view_updated(self):
self.view.refresh()
# --- Public
2019-09-10 00:54:28 +00:00
def refresh(self):
"""Triggers a view :meth:`~TextFieldView.refresh`."""
2019-09-10 00:54:28 +00:00
self.view.refresh()
2019-09-10 00:54:28 +00:00
@property
def text(self):
"""The text that is currently displayed in the widget.
2019-09-10 00:54:28 +00:00
*str*. *get/set*.
2019-09-10 00:54:28 +00:00
This property can be set. When it is, :meth:`refresh` is called and the view is synced with
our value. Always in sync with :attr:`value`.
"""
return self._text
2019-09-10 00:54:28 +00:00
@text.setter
def text(self, newtext):
self.value = self._parse(nonone(newtext, ""))
2019-09-10 00:54:28 +00:00
@property
def value(self):
"""The "parsed" representation of :attr:`text`.
2019-09-10 00:54:28 +00:00
*arbitrary type*. *get/set*.
2019-09-10 00:54:28 +00:00
By default, it's a mirror of :attr:`text`, but a subclass can override :meth:`_parse` and
:meth:`_format` to have anything else. Always in sync with :attr:`text`.
"""
return self._value
2019-09-10 00:54:28 +00:00
@value.setter
def value(self, newvalue):
if newvalue == self._value:
return
self._value = newvalue
self._text = self._format(newvalue)
self._update(self._value)
self.refresh()