# 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 . 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, "", 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'