Skip to content

Commit

Permalink
day 2 progress
Browse files Browse the repository at this point in the history
  • Loading branch information
T-Dynamos committed Mar 4, 2024
1 parent 973ac7a commit 3228304
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 69 deletions.
18 changes: 18 additions & 0 deletions kivymd/uix/carousel/carousel.kv
Original file line number Diff line number Diff line change
@@ -1 +1,19 @@
<MDCarouselImageItem>:

<MDCarousel>:
viewclass:"MDCarouselImageItem"
do_scroll_x:self.is_horizontal
do_scroll_y:not self.is_horizontal
bar_color:[0, 0, 0, 0]
bar_inactive_color:[0, 0, 0, 0]
effect_cls:"ScrollEffect"
MDCarouselContainer:
id:_container
is_horizontal:root.is_horizontal
alignment:root.alignment
default_size: [root._variable_item_size, self.height]
default_size_hint:[None, 1]
size_hint:[None, 1]
width:self.minimum_width
spacing:dp(8)
padding:[dp(16), dp(8)]
132 changes: 86 additions & 46 deletions kivymd/uix/carousel/carousel.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
import os

from kivy.properties import ColorProperty, ListProperty, BooleanProperty
from kivy.metrics import dp
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.metrics import dp
from kivy.properties import (
BooleanProperty,
StringProperty,
OptionProperty,
NumericProperty,
)
from kivy.uix.image import AsyncImage
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview import RecycleView

from kivymd import uix_path
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.behaviors import StencilBehavior
from kivymd.uix.scrollview import MDScrollView
from kivymd.uix.carousel.carousel_strategy import MultiBrowseCarouselStrategy
from kivymd.theming import ThemableBehavior
from kivymd.uix import MDAdaptiveWidget
from kivymd.uix.behaviors import (
BackgroundColorBehavior,
DeclarativeBehavior,
StencilBehavior,
)
from kivymd.uix.carousel.carousel_strategy import AvaliableStrategies

with open(
os.path.join(uix_path, "carousel", "carousel.kv"), encoding="utf-8"
os.path.join(uix_path, "carousel", "carousel.kv"),
encoding="utf-8",
) as kv_file:
Builder.load_string(kv_file.read())

Expand All @@ -24,55 +37,82 @@ def __init__(self, *arg, **kwargs):
self.radius = [10] * 4


class MDCarousel(MDScrollView):
images = ListProperty([])
class MDCarouselContainer(
DeclarativeBehavior,
ThemableBehavior,
BackgroundColorBehavior,
RecycleBoxLayout,
MDAdaptiveWidget,
):
pass


class MDCarousel(RecycleView):
strategy = OptionProperty(
"MultiBrowseCarouselStrategy", options=[AvaliableStrategies.avaliable]
)
is_horizontal = BooleanProperty(True)
alignment = "none"
# Axis
axis = "x"
alignment = StringProperty("default")
desired_item_size = NumericProperty(120)

_child_layout = None
_item_widgets = []
_strategy = None
_container = None
_distance_scroll = NumericProperty(0.0)
_variable_item_size = dp(50)

def __init__(self, *arg, **kwargs):
super().__init__(*arg, **kwargs)

self.do_scroll_x = True
self.do_scroll_y = False
self.bar_color = [0, 0, 0, 0]
self.bar_inactive_color = [0, 0, 0, 0]

# Container
self._child_layout = MDBoxLayout()
self._child_layout.size_hint = [None, None]
self._child_layout.size = self.size
self._child_layout.spacing = dp(8)
self._child_layout.padding = [dp(16), dp(8)]
self._child_layout.is_horizontal = self.is_horizontal
self._child_layout.alignment = self.alignment
self.add_widget(self._child_layout)

def init_images(self, images, start_from=0):
for image in images:
self._child_layout.add_widget( MDCarouselImageItem(size_hint_x=None, width=dp(100), source = image["source"]) )

clas = MultiBrowseCarouselStrategy().on_first_child_measured_with_margins(
self._child_layout, MDCarouselImageItem(size_hint_x=None, width=dp(100))
self.bind(data=self.update_strategy)
self.bind(size=self.update_strategy)
self.bind(ids=self.set_container)

def set_container(self, *args):
self._container = self.ids._container

def fit_count(self, type_item, child_count):
suitable_count = getattr(self._strategy, f"{type_item}_count")
#if type_item == "large":
#if (self.width-dp(32))/getattr(self._strategy, f"{type_item}_size") <= suitable_count:
# suitable_count -= self._strategy.small_count - self._strategy.medium_count -1
return range(suitable_count)

def set_init_size(self, *arg):
child_count = len(self._container.children)
if child_count <= (
self._strategy.small_count
+ self._strategy.medium_count
+ self._strategy.large_count
):
return

print(self.size,self._strategy, len(self._container.children))

index = 0
for type_item in ["large", "medium", "small"]:
item_size = getattr(self._strategy, f"{type_item}_size")
for _, widget in zip(
self.fit_count(type_item, child_count),
self._container.children[::-1][index:],
):
widget.width = item_size
index += 1

def on__distance_scroll(self, instance, distance):
pass

def update_strategy(self, *args):
self._strategy = AvaliableStrategies.get(self.strategy).arrange(
self, self.desired_item_size, len(self.data)
)
print(clas)

def on_images(self, instance, images):
self.init_images(images)

def on_size(self, instance, size):
self._child_layout.size = self.size
self.init_images(self.images)
Clock.schedule_once(self.set_init_size)
return self._strategy

_last_touch_pos = []
_last_touch_point = [0, 0]

def on_touch_down(self, touch):
self._last_touch_pos = list(touch.pos)
self._last_touch_point = list(touch.pos)
super().on_touch_down(touch)

def on_touch_move(self, touch):
super().on_touch_move(touch)
self._distance_scroll = touch.pos[0] - self._last_touch_point[0]
34 changes: 22 additions & 12 deletions kivymd/uix/carousel/carousel_strategy.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import math

from kivy.metrics import dp
from kivy.uix.widget import Widget

from kivymd.uix.carousel.arrangement import Arrangement


Expand Down Expand Up @@ -41,12 +43,11 @@ def set_small_item_size_max(self, max_small_item_size: float):


class MultiBrowseCarouselStrategy(CarouselStrategy):
SMALL_COUNTS = [1]
MEDIUM_COUNTS = [1, 0]
small_counts = [1]
medium_counts = [1, 0]

def on_first_child_measured_with_margins(self, carousel: Widget, child: Widget):
available_space = carousel.height if carousel.is_horizontal else carousel.width
measured_child_size = child.height if carousel.is_horizontal else child.width
def arrange(self, carousel: Widget, measured_child_size, item_len):
available_space = (carousel.width-dp(40)) if carousel.is_horizontal else carousel.height
small_child_size_min = self.small_size_min
small_child_size_max = max(self.small_size_max, small_child_size_min)
target_large_child_size = min(measured_child_size, available_space)
Expand All @@ -56,10 +57,10 @@ def on_first_child_measured_with_margins(self, carousel: Widget, child: Widget):
target_medium_child_size = (
target_large_child_size + target_small_child_size
) / 2
small_counts = self.SMALL_COUNTS
small_counts = self.small_counts
if available_space < small_child_size_min * 2:
small_counts = [0]
medium_counts = self.MEDIUM_COUNTS
medium_counts = self.medium_counts

if carousel.alignment == "center":
small_counts = self.double_counts(small_counts)
Expand All @@ -73,8 +74,9 @@ def on_first_child_measured_with_margins(self, carousel: Widget, child: Widget):
large_count_min = max(1, min_available_large_space // target_large_child_size)
large_count_max = math.ceil(available_space / target_large_child_size)
large_counts = [
large_count_max - i for i in range(large_count_max - large_count_min + 1)
]
large_count_max - i
for i in range(int(large_count_max - large_count_min + 1))
]
arrangement = Arrangement.find_lowest_cost_arrangement(
available_space,
target_small_child_size,
Expand All @@ -88,8 +90,7 @@ def on_first_child_measured_with_margins(self, carousel: Widget, child: Widget):
)

keyline_count = arrangement.get_item_count()
print( len(carousel.children) )
if self.ensure_arrangement_fits_item_count(arrangement, len(carousel.children)):
if self.ensure_arrangement_fits_item_count(arrangement, item_len):
arrangement = Arrangement.find_lowest_cost_arrangement(
available_space,
target_small_child_size,
Expand All @@ -101,7 +102,6 @@ def on_first_child_measured_with_margins(self, carousel: Widget, child: Widget):
target_large_child_size,
[arrangement.large_count],
)

return arrangement

def ensure_arrangement_fits_item_count(
Expand All @@ -127,3 +127,13 @@ def should_refresh_keyline_state(carousel: Widget, old_item_count: int):
old_item_count >= keyline_count
and carousel.get_item_count() < keyline_count
)


class AvaliableStrategies:
avaliable = ["MultiBrowseCarouselStrategy"]

@staticmethod
def get(strategy_name):
return {"MultiBrowseCarouselStrategy": MultiBrowseCarouselStrategy}[
strategy_name
]()
13 changes: 2 additions & 11 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
from examples.common_app import CommonApp, KV

MAIN_KV = """
<Item>:
size_hint_y:None
height:dp(50)
MDScreen:
md_bg_color: app.theme_cls.backgroundColor
BoxLayout:
Expand All @@ -22,20 +18,15 @@
Widget:
"""


class Item(BoxLayout):
pass


class Example(MDApp, CommonApp):
def build(self):
self.theme_cls.theme_style = "Dark"
return Builder.load_string(MAIN_KV)

def on_start(self):
super().on_start()
self.root.ids.carousel.images = [
{"source":path} for path in glob("/home/tdynamos/Pictures/Screenshots/*")
self.root.ids.carousel.data = [
{"source":path} for path in glob("/home/tdynamos/Pictures/Screenshots/*")[:20]
]

Example().run()

0 comments on commit 3228304

Please sign in to comment.