Skip to content

Instantly share code, notes, and snippets.

@Bakterija
Created June 27, 2017 17:51
Show Gist options
  • Save Bakterija/5b38997be51a5e9c8c6b383a7c575058 to your computer and use it in GitHub Desktop.
Save Bakterija/5b38997be51a5e9c8c6b383a7c575058 to your computer and use it in GitHub Desktop.
RecycleView line splitting behavior exampl app
from kivy.properties import NumericProperty, ListProperty, StringProperty
from time import time
import copy
class LineSplitBehavior(object):
split_text_key = StringProperty('text')
split_text_indent = NumericProperty(4)
chars_per_line = NumericProperty(100)
_unsplit_data = ListProperty()
def __init__(self, **kwargs):
super(LineSplitBehavior, self).__init__(**kwargs)
self.fbind('chars_per_line', self.line_split_reload)
def set_data(self, data_full, update_unsplitted=True):
if update_unsplitted:
if data_full:
key = self.split_text_key
self._unsplit_data = [copy.copy(x) for x in data_full]
else:
self._unsplit_data = []
if data_full:
data_full = self.get_line_split_data(data_full)
try:
super(LineSplitBehavior, self).set_data(data_full)
except AttributeError:
self.data = data_full
def get_line_split_data(self, data_full):
new_data0 = []
new_data = []
cpl = self.chars_per_line
key = self.split_text_key
# Do fast splitting with new line characters before doing word
# length calculations
for x in data_full:
split_text = x[key].splitlines()
if len(split_text) > 1:
for text in split_text:
new_dict = copy.copy(x)
new_dict[key] = text
new_data0.append(new_dict)
else:
new_data0.append(x)
for x in new_data0:
# If text does not fit in one line, start splitting it
if len(x[key]) > cpl:
words = x[key].split(' ')
new_lines = []
new_line = ''
for word in words:
len_line = len(new_line)
len_word = len(word)
# When word fits in line character limit,
# add it to current line
if len_word + len_line < cpl:
if new_line:
new_line = '%s %s' % (new_line, word)
else:
new_line = word
# When word does not fit in line character limit
# append current line and start a new line
else:
new_lines.append(new_line)
new_line = ''
# When word fits in the new empty line, add it
if len_word < cpl:
if new_line:
new_line = '%s %s' % (new_line, word)
else:
new_line = word
# When word is longer then character limit,
# split it and add multiple lines
else:
# Calculate line count
split_parts = float(len_word) / float(cpl)
split_remain = split_parts % int(split_parts)
if split_remain:
split_parts = int(split_parts) + 1
else:
split_parts = int(split_parts)
# Split word into calculated line count
word_split = [
word[cpl*i:cpl*(i+1)] for i in range(
split_parts)
]
# Add parts of split word to new_lines
if split_remain:
for word in word_split[:-1]:
new_lines.append(word)
new_line = word
else:
for word in word_split:
new_lines.append(word)
# Add any remaining text
if new_line:
new_lines.append(new_line)
# Make data copies and put in text for each line
for new_line in new_lines:
new_dict = copy.copy(x)
new_dict[key] = new_line
new_data.append(new_dict)
else:
# Skip splitting for short text and append the data
new_data.append(x)
return new_data
def line_split_reload(self, _, chars_per_line):
self.set_data(self._unsplit_data)
from kivy.uix.recycleview import RecycleView
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import NumericProperty
from line_split import LineSplitBehavior
from kivy.app import runTouchApp
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.logger import Logger
from random import randrange
from kivy.metrics import cm
from time import time
randata = '''Resources exquisite set arranging moonlight cuddle him household had. Months had too ham cousin remove far spirit. She procuring the why performed continual improving. Civil songs so large shade in cause. Lady an mr here must neat sold. Children greatest ye extended delicate of. No elderly passage earnest as in removed winding or.
Shot what able cold new the see hold. Friendly as an betrayed formerly he. Morning because as to society behaved moments. Put ladies design mrs sister was. Play on hill felt john no gate. Am passed figure to marked in. Prosperous middletons is ye inhabiting as assistance me especially. For looking two cousins regular amongst.
Carriage quitting securing be appetite it declared. High eyes kept so busy feel call in. Would day nor ask walls known. But preserved advantage are but and certainty earnestly enjoyment. Passage weather as up am exposed. And natural related man subject. Eagerness get situation his was delighted.
Compliment interested discretion estimating on stimulated apartments oh. Dear so sing when in find read of call. As distrusts behaviour abilities defective is. Never at water me might. On formed merits hunted unable merely by mr whence or. Possession the unpleasing simplicity her uncommonly.
Sportsman delighted improving dashwoods gay instantly happiness six. Ham now amounted absolute not mistaken way pleasant whatever. At an these still no dried folly stood thing. Rapid it on hours hills it seven years. If polite he active county in spirit an. Mrs ham intention promotion engrossed assurance defective. Confined so graceful building opinions whatever trifling in. Insisted out differed ham man endeavor expenses. At on he total their he songs. Related compact effects is on settled do.
Pasture he invited mr company shyness. But when shot real her. Chamber her observe visited removal six sending himself boy. At exquisite existence if an oh dependent excellent. Are gay head need down draw. Misery wonder enable mutual get set oppose the uneasy. End why melancholy estimating her had indulgence middletons. Say ferrars demands besides her address. Blind going you merit few fancy their.
Offered say visited elderly and. Waited period are played family man formed. He ye body or made on pain part meet. You one delay nor begin our folly abode. By disposed replying mr me unpacked no. As moonlight of my resolving unwilling.
Now for manners use has company believe parlors. Least nor party who wrote while did. Excuse formed as is agreed admire so on result parish. Put use set uncommonly announcing and travelling. Allowance sweetness direction to as necessary. Principle oh explained excellent do my suspected conveying in. Excellent you did therefore perfectly supposing described.
Little afraid its eat looked now. Very ye lady girl them good me make. It hardly cousin me always. An shortly village is raising we shewing replied. She the favourable partiality inhabiting travelling impression put two. His six are entreaties instrument acceptance unsatiable her. Amongst as or on herself chapter entered carried no. Sold old ten are quit lose deal his sent. You correct how cuddle several far distant believe journey parties. We shyness enquire uncivil affixed it carried to.
Style never met and those among great. At no or september sportsmen he perfectly happiness attending. Depending listening delivered off new she procuring satisfied cuddle existence. Person plenty answer to exeter it if. Law use assistance especially resolution cultivated did out sentiments unsatiable. Way necessary had intention happiness but september delighted his curiosity. Furniture furnished or on strangers neglected remainder engrossed.
'''
class RootWidget(FloatLayout):
font_size = NumericProperty(cm(0.4))
def on_ids(self, _, value):
self.fbind('font_size', self.schedule_line_split_update)
self.fbind('width', self.schedule_line_split_update)
Clock.schedule_once(self.ddd, 0.5)
def ddd(self, *args):
global randata
rv = self.ids.rv
randata = randata * 10
randata = randata.splitlines()
new_data = []
for x in randata:
randcolor = (
float(randrange(20, 255, 1)) / 255.0,
float(randrange(20, 255, 1)) / 255.0,
float(randrange(20, 255, 1)) / 255.0,
1)
new_data.append({'text': x, 'background_color': randcolor})
rv.set_data(new_data)
def _update_chars_per_line(self, *args):
value = int((self.width / self.font_size))
self.ids.rv.chars_per_line = value
Logger.info('_update_chars_per_line: %s' % (value))
def schedule_line_split_update(self, *args):
Clock.unschedule(self._update_chars_per_line)
Clock.schedule_once(self._update_chars_per_line, 0.3)
class LnRecycleView(LineSplitBehavior, RecycleView):
pass
runTouchApp(Builder.load_string('''
<TLabel@Label>:
size_hint: 1, None
height: int(cm(0.7))
font_size: int(cm(0.6))
font_name: 'RobotoMono-Regular.ttf'
text_size: self.width, None
padding: 10, 10
background_color: 0.2, 0.2, 0.2, 1
color: 1, 1, 1, 1
canvas.before:
Color:
rgba: self.background_color
Rectangle:
pos: self.pos
size: self.size
RootWidget:
LnRecycleView:
id: rv
size_hint: None, None
size: root.size
pos: 0, 0
viewclass: 'TLabel'
RecycleBoxLayout:
orientation: 'vertical'
size_hint_y: None
default_size_hint: 1, None
default_size: None, None
height: self.minimum_height
spacing: 2
'''))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment