nov algoritem za prelom vrstic in postavljanje na stran #3
This commit is contained in:
152
projector.py
152
projector.py
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
from tkinter import font
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import math
|
import math
|
||||||
@@ -128,13 +129,18 @@ class SongProjector:
|
|||||||
self.right_frame.pack(side="right", fill="y")
|
self.right_frame.pack(side="right", fill="y")
|
||||||
|
|
||||||
font_weight = "bold" if self.settings.get("font_bold", False) else "normal"
|
font_weight = "bold" if self.settings.get("font_bold", False) else "normal"
|
||||||
|
self.custom_font = font.Font(
|
||||||
|
family=self.settings["font_name"],
|
||||||
|
size=int(self.settings["font_size"]),
|
||||||
|
weight=font_weight
|
||||||
|
)
|
||||||
|
|
||||||
self.display_text = tk.Label(
|
self.display_text = tk.Label(
|
||||||
self.color_frame,
|
self.color_frame,
|
||||||
text="",
|
text="",
|
||||||
bg=self.settings["bg_color"],
|
bg=self.settings["bg_color"],
|
||||||
fg=self.settings["fg_color"],
|
fg=self.settings["fg_color"],
|
||||||
font=(self.settings["font_name"], int(self.settings["font_size"]), font_weight),
|
font=self.custom_font,
|
||||||
wraplength=color_width,
|
wraplength=color_width,
|
||||||
justify="center"
|
justify="center"
|
||||||
)
|
)
|
||||||
@@ -228,37 +234,28 @@ class SongProjector:
|
|||||||
def split_long_line(self, line):
|
def split_long_line(self, line):
|
||||||
"""
|
"""
|
||||||
Vrne seznam pod-vrstic, ki skupaj tvorijo `line`,
|
Vrne seznam pod-vrstic, ki skupaj tvorijo `line`,
|
||||||
pri čemer so (približno) enako dolge glede na število znakov.
|
pri čemer so dolge največ `self.color_width` pikslov.
|
||||||
"""
|
"""
|
||||||
avg_char_width = int(self.settings["font_size"]) * 0.57
|
|
||||||
wraplength_px = self.color_width
|
|
||||||
# Koliko znakov približno gre v eno vrstico
|
|
||||||
approx_chars_per_line = max(1, int(wraplength_px / avg_char_width))
|
|
||||||
|
|
||||||
if len(line) <= approx_chars_per_line:
|
|
||||||
return [line]
|
|
||||||
|
|
||||||
# Potrebno število pod-vrstic
|
|
||||||
n_sub = math.ceil(len(line) / approx_chars_per_line)
|
|
||||||
|
|
||||||
words = line.split()
|
words = line.split()
|
||||||
total_chars = sum(len(w) for w in words) + len(words) - 1 # vključno s presledki
|
if not words:
|
||||||
target_len = total_chars / n_sub
|
return [""]
|
||||||
|
|
||||||
sub_lines = []
|
sub_lines = []
|
||||||
current_words = []
|
current_words = []
|
||||||
current_len = 0
|
|
||||||
|
|
||||||
for word in words:
|
for word in words:
|
||||||
added_len = len(word) + (1 if current_words else 0) # presledek pred besedo, če ni prva
|
test_line = " ".join(current_words + [word])
|
||||||
if current_len + added_len > target_len and len(sub_lines) < n_sub - 1:
|
# Izmerimo širino v pikslih
|
||||||
# Začni novo vrstico
|
if self.custom_font.measure(test_line) <= self.color_width:
|
||||||
sub_lines.append(" ".join(current_words))
|
|
||||||
current_words = [word]
|
|
||||||
current_len = len(word)
|
|
||||||
else:
|
|
||||||
current_words.append(word)
|
current_words.append(word)
|
||||||
current_len += added_len
|
else:
|
||||||
|
if current_words:
|
||||||
|
sub_lines.append(" ".join(current_words))
|
||||||
|
current_words = [word]
|
||||||
|
else:
|
||||||
|
# Beseda je sama po sebi predolga (zelo redko)
|
||||||
|
sub_lines.append(word)
|
||||||
|
current_words = []
|
||||||
|
|
||||||
if current_words:
|
if current_words:
|
||||||
sub_lines.append(" ".join(current_words))
|
sub_lines.append(" ".join(current_words))
|
||||||
@@ -330,75 +327,70 @@ class SongProjector:
|
|||||||
if result:
|
if result:
|
||||||
lyrics = result[0]
|
lyrics = result[0]
|
||||||
|
|
||||||
max_height = self.screen_height - (self.line_height * 1.5)
|
max_height = self.screen_height - (self.line_height * 2)
|
||||||
avg_char_width = int(self.settings["font_size"]) * 0.57
|
|
||||||
wraplength = self.color_width
|
|
||||||
|
|
||||||
# -------------------------------------------
|
# 1. Razdelimo na kitice (stanzas)
|
||||||
# 1. Razbijanje besedila na (pod-)vrstice
|
# Kitice so ločene z eno ali več praznimi vrsticami
|
||||||
# -------------------------------------------
|
import re
|
||||||
raw_lines = lyrics.strip().splitlines()
|
stanzas_raw = re.split(r'\n\s*\n', lyrics.strip())
|
||||||
processed_lines = []
|
|
||||||
for raw in raw_lines:
|
|
||||||
if raw.strip() == "":
|
|
||||||
processed_lines.append("") # ohranimo prazno vrstico
|
|
||||||
else:
|
|
||||||
processed_lines.extend(self.split_long_line(raw))
|
|
||||||
|
|
||||||
# -------------------------------------------
|
processed_stanzas = []
|
||||||
# 2. Razdeljevanje vrstic na strani
|
for stanza in stanzas_raw:
|
||||||
# -------------------------------------------
|
lines = stanza.splitlines()
|
||||||
|
stanza_lines = []
|
||||||
|
for line in lines:
|
||||||
|
if line.strip():
|
||||||
|
stanza_lines.extend(self.split_long_line(line))
|
||||||
|
if stanza_lines:
|
||||||
|
processed_stanzas.append(stanza_lines)
|
||||||
|
|
||||||
|
# 2. Razdeljevanje kitic na strani
|
||||||
pages = []
|
pages = []
|
||||||
current_page_lines = []
|
current_page_lines = []
|
||||||
current_height = 0
|
current_height = 0
|
||||||
blank_line_count = 0
|
|
||||||
|
|
||||||
for line in processed_lines:
|
for stanza in processed_stanzas:
|
||||||
is_blank = (line.strip() == "")
|
stanza_height = len(stanza) * self.line_height
|
||||||
if is_blank:
|
|
||||||
blank_line_count += 1
|
|
||||||
else:
|
|
||||||
blank_line_count = 0
|
|
||||||
|
|
||||||
approx_line_length = len(line)
|
# Če kitica sama po sebi presega max_height, jo moramo razdeliti
|
||||||
approx_line_count = 1 if is_blank else math.ceil((approx_line_length * avg_char_width) / wraplength)
|
if stanza_height > max_height:
|
||||||
needed_height = self.line_height * approx_line_count
|
# Če imamo že kaj na strani, to zaključimo
|
||||||
|
|
||||||
# Prazna vrstica več kot 1-krat pomeni nova kitica ⇒ nova stran
|
|
||||||
if blank_line_count >= 2:
|
|
||||||
if current_page_lines:
|
if current_page_lines:
|
||||||
pages.append("\n".join(current_page_lines).strip())
|
pages.append("\n".join(current_page_lines))
|
||||||
current_page_lines = []
|
|
||||||
current_height = 0
|
|
||||||
blank_line_count = 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Če čez spodnji rob strani …
|
|
||||||
if current_height + needed_height > max_height + self.line_height // 2:
|
|
||||||
# poskusimo prelomiti na prazni vrstici znotraj strani
|
|
||||||
found_split = False
|
|
||||||
for i in reversed(range(len(current_page_lines))):
|
|
||||||
if current_page_lines[i].strip() == "":
|
|
||||||
pages.append("\n".join(current_page_lines[:i]).strip())
|
|
||||||
current_page_lines = current_page_lines[i + 1:]
|
|
||||||
current_height = sum(
|
|
||||||
self.line_height * (
|
|
||||||
1 if l.strip() == "" else math.ceil(len(l) * avg_char_width / wraplength)
|
|
||||||
)
|
|
||||||
for l in current_page_lines
|
|
||||||
)
|
|
||||||
found_split = True
|
|
||||||
break
|
|
||||||
if not found_split:
|
|
||||||
pages.append("\n".join(current_page_lines).strip())
|
|
||||||
current_page_lines = []
|
current_page_lines = []
|
||||||
current_height = 0
|
current_height = 0
|
||||||
|
|
||||||
current_page_lines.append(line)
|
# Razdelimo predolgo kitico na več strani
|
||||||
current_height += needed_height
|
temp_stanza_lines = []
|
||||||
|
temp_height = 0
|
||||||
|
for line in stanza:
|
||||||
|
if temp_height + self.line_height > max_height:
|
||||||
|
pages.append("\n".join(temp_stanza_lines))
|
||||||
|
temp_stanza_lines = [line]
|
||||||
|
temp_height = self.line_height
|
||||||
|
else:
|
||||||
|
temp_stanza_lines.append(line)
|
||||||
|
temp_height += self.line_height
|
||||||
|
if temp_stanza_lines:
|
||||||
|
current_page_lines = temp_stanza_lines
|
||||||
|
current_height = temp_height
|
||||||
|
|
||||||
|
# Če kitica ne gre več na trenutno stran
|
||||||
|
elif current_height + stanza_height + (self.line_height if current_page_lines else 0) > max_height:
|
||||||
|
pages.append("\n".join(current_page_lines))
|
||||||
|
current_page_lines = stanza
|
||||||
|
current_height = stanza_height
|
||||||
|
|
||||||
|
# Kitica gre na trenutno stran
|
||||||
|
else:
|
||||||
|
if current_page_lines:
|
||||||
|
current_page_lines.append("") # Razmik med kiticami
|
||||||
|
current_height += self.line_height
|
||||||
|
current_page_lines.extend(stanza)
|
||||||
|
current_height += stanza_height
|
||||||
|
|
||||||
if current_page_lines:
|
if current_page_lines:
|
||||||
pages.append("\n".join(current_page_lines).strip())
|
pages.append("\n".join(current_page_lines))
|
||||||
|
|
||||||
self.pages = pages
|
self.pages = pages
|
||||||
self.current_page_index = 0
|
self.current_page_index = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user