This repository has been archived on 2021-12-22. You can view files and clone it, but cannot push or open issues or pull requests.
tkGemini/renderEngine.py

134 lines
4.9 KiB
Python

# Copyright 2020 Romain de Laage
#
# This file is part of tkGemini.
#
# tkGemini is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# tkGemini is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with tkGemini. If not, see <https://www.gnu.org/licenses/>.
import tkinter as tk
import tkinter.font as tkFont
# Renderer class to transform a Gemini text into a visual text formatted
class Renderer():
def __init__(self, parent, text):
# Some global variable
self.parent = parent
self.text = text
self.currX = 0
self.currY = 1
self.content = tk.Text(self.parent.root)
# Definition for some styles
self.h1Font = tkFont.Font(weight="bold", size="26")
self.content.tag_config("h1", font=self.h1Font)
self.h2Font = tkFont.Font(weight="bold", size="20")
self.content.tag_config("h2", font=self.h2Font)
self.h3Font = tkFont.Font(weight="bold", size="16")
self.content.tag_config("h3", font=self.h3Font)
self.underlineFont = tkFont.Font(underline=1)
def addNormalText(self, text):
# Draw normal text on the current line and go to the next line
self.content.insert(str(self.currY)+'.'+str(self.currX), text+"\n")
self.currY+=1
def addLink(self, text, url):
# Calculate current index (position)
index1 = str(self.currY)+'.'+str(self.currX)
#prepare tag for this link (format + action when clicking)
self.content.tag_config("link-"+index1, foreground="#00f", font=self.underlineFont)
self.content.tag_bind("link-"+index1, "<Button-1>", lambda event, url=url, parent=self.parent:
parent.linkClick(url))
# Add text, add tag from the beginning to the end and go to a new line
self.content.insert(index1, text+"\n")
self.content.tag_add("link-"+index1, index1, str(self.currY)+'.'+str(self.currX+len(text)))
self.currY+=1
def addHeading1(self, text):
# Calculate current index
index1 = str(self.currY)+'.'+str(self.currX)
# Insert text then apply tag and go to a new line
self.content.insert(index1, text+"\n")
self.content.tag_add("h1", index1, str(self.currY)+'.'+str(self.currX+len(text)))
self.currY+=1
def addHeading2(self, text):
# Calculate current index
index1 = str(self.currY)+'.'+str(self.currX)
# Insert text then apply tag and go to a new line
self.content.insert(index1, text+"\n")
self.content.tag_add("h2", index1, str(self.currY)+'.'+str(self.currX+len(text)))
self.currY+=1
def addHeading3(self, text):
# Calculate current index
index1 = str(self.currY)+'.'+str(self.currX)
# Inset text then apply tag and go to a new line
self.content.insert(index1, text+"\n")
self.content.tag_add("h3", index1, str(self.currY)+'.'+str(self.currX+len(text)))
self.currY+=1
def addListItem(self, text):
# Same as drawing a normal line but with a tab and a bullet point at the beginning
self.content.insert(str(self.currY)+'.'+str(self.currX), "\t"+text+"\n")
self.currY+=1
def parse(self):
# Make text editable
self.content['state'] = 'normal'
# Reinitialize position
self.currY=1
self.currX=0
# Delete all the current text
self.content.delete("1.0", tk.END)
# Cut the text into line
lines = self.text.split("\n")
# Parse each line
for line in lines:
if(line.startswith("###")):
self.addHeading3(line[3:].strip())
elif(line.startswith("##")):
self.addHeading2(line[2:].strip())
elif(line.startswith("#")):
self.addHeading1(line[1:].strip())
elif(line.startswith("*")):
self.addListItem(line[1:].strip())
elif(line.startswith("=>")):
line = line[2:].strip()
# Link location is before the first whitespace
url = line.split()[0]
# Link text is after the first whitespace
text = line[len(url):len(line)].strip()
# If there is no text, then the link location become the text
if text == "":
text = url
self.addLink(text, url)
else:
self.addNormalText(line)
# Now the text should not be edited
self.content['state'] = 'disabled'