134 lines
4.9 KiB
Python
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'
|