From d285635870d0af74a667f9143fab6c91946e329e Mon Sep 17 00:00:00 2001 From: "Jeison Yehuda Amihud (Blender Dumbass)" Date: Wed, 3 Mar 2021 14:45:27 +0000 Subject: [PATCH] Implementing Markdown This was hard. But now I can post documentation directly into the help dialogue. Instead of it being links to outside sources. I will do this for the next update. --- UI/UI_Markdown.py | 765 ++++++++++++++++++++++++++++++++++++++++++++ UI/UI_elements.py | 150 +++++++-- UI/UI_helpDialog.py | 103 +++++- 3 files changed, 991 insertions(+), 27 deletions(-) create mode 100644 UI/UI_Markdown.py diff --git a/UI/UI_Markdown.py b/UI/UI_Markdown.py new file mode 100644 index 0000000..c0e0669 --- /dev/null +++ b/UI/UI_Markdown.py @@ -0,0 +1,765 @@ +#################################### +# # +# COPYRIGHT NOTICE # +# # +# This file is a part of Victori- # +# ous Children Studio Organizer. # +# Or simply VCStudio. Copyright # +# of J.Y.Amihud. But don't be sad # +# because I released the entire # +# project under a GNU GPL license. # +# You may use Version 3 or later. # +# See www.gnu.org/licenses if your # +# copy has no License file. Please # +# note. Ones I used the GPL v2 for # +# it. It's no longer the case. # +# # +#################################### + +import os + +# GTK module ( Graphical interface +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk +from gi.repository import GLib +from gi.repository import Gdk +import cairo + +# Own modules +from settings import settings +from settings import talk +from settings import oscalls +from project_manager import pm_project + +#UI modules +from UI import UI_elements +from UI import UI_color + + +################################################################################ + +# Markdown. Or .md file format is an easy way to give your simple text documents +# a bit of flare. Stuff like links, images and quotes are supported. Also bold +# an italic characters. + + + +def Open(win, filename, name): + + # This function will parse a Markdown (.md) file into a readable python + # dictionary object. That you can use for various things. + try: + + # If the file is local. AKA exists in the folder. And can be read. + # Also it could be not .md + if not filename.endswith(".md"): + 1/0 # Quick fail switch + + md = open(filename) + md = md.read() + + except: + + # If reading fails. For example if it's a link to something on the + # web. Then try just opening it in the standard application. + + md = "" + oscalls.Open(filename) + win.current["mdfs"][name] = win.current["mdfs"]["failsafe"] + + + md = md.split("\n") + + # First thing is I was to read the headings and convert it into a tree. + + + tree = [] + indent = 1 + c = [] + + for line in md: + + ty = "text" + te = line + + # Here I want to simply get a type of each line. Later we going to parse + # the links and other things. But first. Let's parse stuff based on + # lines. + + if line.startswith("#"): + # The titles of the chapter. The Headers are usually written similar + # to how here in python you write comments. It's a # , space, and the + # text. + + # The amount of hashes. ## or ### gives different sized text. Officialy + # it should support up to 6 hashes. ######. But why not make it more + # just in case. + + ty = line.count("#") # This might give bugs + + elif line.startswith("> "): + + # The > sign in the Markdown language is used for quatations. + + ty = "quote" + + tree.append([ty, te+"\n"]) + + # Now the stage 0 is over and we parsed the basic things. Now is the hard + # part to parse out all the images and stuff inside them. It's going to be + # done per part. And we are going to use the same technique I used for the + # conversion of the legacy projects. See : studio/story.py + + # We are going to itterate over each letter. And decide what to do by that + + newtree = [] + + for block in tree: + + part = "" + skip = 0 + + for n, l in enumerate(block[-1]): + + if skip > n: + continue + + part = part + l + + # Here we are going to do something if a give condition is met. + # Usually I gonna do something if [part] ends with a given markdown + # thing. I don't have a mnual of markdown on me. So please make it + # more supported. I guess. I might forget things I rarely use. + + # Links are made with [stuff you click on](https://example.com) + # but similar to it. Images are done ![Tooltip](Image.png) + # and even weirder you can put one into the other. Like + # [![Tooltip](Image.png)](https://example.com) + # Which going to give you a clickable image. + + # For this version what we are going to do is next. + # If we got [![ then it's a clickable image + # If we got ![ then it's just image + # and if we got [ then it's a link. + + if part.endswith("[!["): + + # IMAGE LINK + newtree.append([block[0], part[:-3]]) + + tooltip = "" + imageurl = "" + url = "" + t = False + iu = False + skip = n + for le in block[-1][n:]: # For letters in the rest of text + + skip = skip + 1 + + if le == "]": + t = True + elif le == ")" and t and not iu: + iu = True + elif le == ")" and t and iu: + break + elif not t: + tooltip = tooltip +le + elif t and not iu: + imageurl = imageurl + le + else: + url = url+le + + tooltip = tooltip[tooltip.find("[")+1:] + imageurl = imageurl[imageurl.find("(")+1:] + url = url[url.find("(")+1:] + + apnd = ["image_link", tooltip, imageurl, url] + + newtree.append(apnd) + + part = "" + + + elif part.endswith("!["): + + # IMAGE + + newtree.append([block[0], part[:-2]]) + + tooltip = "" + url = "" + t = False + skip = n + for le in block[-1][n:]: # For letters in the rest of text + + skip = skip + 1 + + if le == "]": + t = True + elif le == ")" and t: + break + elif not t: + tooltip = tooltip +le + else: + url = url+le + + tooltip = tooltip[tooltip.find("[")+1:] + url = url[url.find("(")+1:] + + apnd = ["image", tooltip, url] + newtree.append(apnd) + + part = "" + + + elif part.endswith("[") and not block[-1][n:].startswith('[!['): + + # LINK + newtree.append([block[0], part[:-1]]) + + + tooltip = "" + url = "" + t = False + skip = n + for le in block[-1][n:]: # For letters in the rest of text + + skip = skip + 1 + + if le == "]": + t = True + elif le == ")" and t: + break + elif not t: + tooltip = tooltip +le + else: + url = url+le + + tooltip = tooltip[tooltip.find("[")+1:] + url = url[url.find("(")+1:] + + apnd = ["link", tooltip, url] + newtree.append(apnd) + + part = "" + + + + # Now I want to deal with `, *, ** and ***. If you want to help me you + # can implement other types. Such as _, __, ___ and so on. Markdown is + # a very rich language. I'm going to use the cut down version I see other + # people use. + + # BTW this is the time. Feb 28. When I switched from Gedit to GNU Emacs. + # Interesting feeling using this programm. I kind a love it even tho + # so many stuff in not intuitive. Like saving is not Ctrl - S but + # Ctrl - X -> Ctrl - S. + + # Things like Alt-; to comment multiple lines at ones is HUGE. Also it + # was built by programmers for programmers. So it's a very good tool. + + elif part.endswith("**") and not block[-1][n+2:].startswith('*'): + + # DOUBLE ** + + newtree.append([block[0], part[:-2]]) + + if block[0] == "text": + block[0] = "text_b" + else: + block[0] = "text" + + part = "" + + elif part.endswith("*") and not block[-1][n+1:].startswith('*'): + + # SINGLE * + + newtree.append([block[0], part[:-1]]) + + if block[0] == "text": + block[0] = "text_i" + else: + block[0] = "text" + + part = "" + + + elif part.endswith("`"): + + # SINGLE ` + + newtree.append([block[0], part[:-1]]) + + if block[0] == "text": + block[0] = "text_c" + else: + block[0] = "text" + + part = "" + + newtree.append([block[0], part]) + + + + tree = newtree + + return(tree) + +def search_convert(s): + l = " ./\|[]{}()?!@#$%^&*`~:;'\"=,<>" + s = s.lower().replace(" ","-") + r = "" + for i in s: + if i not in l: + r = r + i + return r + +def draw(outlayer, win, name, x, y, width, height): + + # Now you maybe woundering where is the filname to read from. Well. We are + # making it now. + + if "mdfs" not in win.current: + win.current["mdfs"] = {} + win.current["mdfs"]["failsafe"] = "" + + if name not in win.current["mdfs"]: + win.current["mdfs"][name] = "" + + filename = win.current["mdfs"][name] + + # The # sing usually calls for search with in the text. + + if "#" in filename: + filename, search = filename.split("#") + win.current["mdfs"][name] = filename + else: + search = "" + + # First we don't want to waste resources to parse the file on each frame + # so let's load it ones. + + if "mds" not in win.current: + win.current["mds"] = {} + + if filename not in win.current["mds"]: + win.current["mds"][filename] = Open(win, filename, name) + + md = win.current["mds"][filename] + + # This peace of code outputs the parsed object into terminal for reading. + + # for i in md: + # if type(i) == str: + # print("'"+i+"' ,") + # else: + # print(i, ",") + + + # Background + UI_color.set(outlayer, win, "node_background") + UI_elements.roundrect(outlayer, win, + x, + y, + width, + height, + 10) + outlayer.fill() + + # The name of the file first. I think it's gonna make sense to make it in + # an entry. So people could insert any filename, or link in future. + + try: + UI_elements.text(outlayer, win, "markdown_name", + x+10, + y+5, + int(width)-20, + 40, + set_text=filename, + fill=False) + + if win.text["markdown_name"]["text"] != filename \ + and win.textactive != "markdown_name": + win.text["markdown_name"]["text"] = filename + + # Let me make it user editable as well. Because I'm a nerd + # and I want to see how it handles various problems. + + elif win.text["markdown_name"]["text"] != filename: + + def do(): + win.current["mdfs"]["failsafe"] = filename + win.current["mdfs"][name] = win.text["markdown_name"]["text"] + + UI_elements.roundrect(outlayer, win, + x+int(width)-50, + y+5, + 40, + 40, + 10, + button=do, + icon="ok", + tip=talk.text("checked")) + + + except: + pass + + # Now let's draw the bastard. We are going to do it the same way as in the + # script writer. But rather simplified. For example we are not making an + # editor. But only a reader. So we don't need the selection. And we don't + # need to calculate every letter preciselly. With something like codes + # I can do that every ` object will be drawn in a text entry object. Why + # not. + + # I need to make a new Layer because we are going to clip it for the text. + + textsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height)) + layer = cairo.Context(textsurface) + layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) + layer_i = cairo.Context(textsurface) + layer_i.select_font_face("Monospace", cairo.FONT_SLANT_ITALIC, cairo.FONT_WEIGHT_NORMAL) + layer_b = cairo.Context(textsurface) + layer_b.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) + layer_bi = cairo.Context(textsurface) + layer_bi.select_font_face("Monospace", cairo.FONT_SLANT_ITALIC, cairo.FONT_WEIGHT_BOLD) + + + + UI_elements.roundrect(layer, win, 0,50,width, height-50, 10,fill=False) + layer.clip() + UI_elements.roundrect(layer_b, win, 0,50,width, height-50, 10,fill=False) + layer_b.clip() + UI_elements.roundrect(layer_bi, win, 0,50,width, height-50, 10,fill=False) + layer_bi.clip() + UI_elements.roundrect(layer_i, win, 0,50,width, height-50, 10,fill=False) + layer_i.clip() + + ############################################################################ + # HERE WE DRAWING TEXT TO THE SCREEN # + ############################################################################ + + if "markdown" not in win.scroll: + win.scroll["markdown"] = 0 + + current_Y = 70 + tyleX = 10 + newX = 10 + newY = 0 + + for block in md: + + # THE # HEADERS + + if type(block[0]) == int: + + current_Y = current_Y + newY + 100 + + UI_color.set(layer_b, win, "text_normal") + layer_b.set_font_size(30-(block[0]*4)) + layer_b.move_to( + 10, + current_Y + win.scroll["markdown"] + ) + layer_b.show_text(block[1].replace("\n", "").replace("#", " ")) + + current_Y = current_Y + 40 + + if search and search in search_convert(block[1].replace("\n", "").replace("#", "")): + win.scroll["markdown"] = 0 - current_Y + 140 + search = "" + + newX = 10 + newY = 0 + + # IMAGES + + # This going to be hard. I have an interesting idea about it. + # 1.) Make the images whos links are in the internet loadable. + # This will require some clever thinking. Because not all + # users want to automatically download images from a source + # that they don't trust. I'm hosting most of the images + # at the moment on NotABug.org with the project's code. + # But. That I trust it. Doesn't mean everybody trust it + # or should trust it. So Downloading of images should be + # optional. We can make a button to download a given image + # and a setting in the settings to download them automatically. + # + # Now thinking about it. The Update system should use something + # similar. + # + # 2.) Warping of text around the image. This is something original + # markdown not really supports. On NotABug the images in the text + # look a bit ugly because they stretch the line height. + # I propose using a kind of warp around system. Let me demonstrate. + + # ############### This is a sample text about the Image.png. That + # # # is going to warp around the image like so. + # # Image.png # More text is needed to show the extent of this + # # # effect. So I'm going to ramble about something. + # # # Hello World! Are you a true hacker? I hope you + # ############### are. And not a cracker. Now see what's going to + # happen when the image is ended. The next line is written under + # the image. Which is a cool look. Now ... + + # I have no idea what to do if the image is going to be rendered in + # the middle of the paragraph. Maybe the image in the middle should + # act like in a normal implementation. And only at the start as + # what I showed you now. + + elif "image" in block[0]: + + + if newY: + current_Y = current_Y + newY + 40 + tyleX = 10 + newX = 10 + newY = 0 + + # ICONS + + # Sometimes I link Icons from OldSchool theme to the text. They + # look good on a white background in the NotABug.org page. + # But. Since they are icons that might have different themes for + # the users let's make them theme respecting. + + if "settings/themes/" in block[2] and "/icons/" in block[2]: + iconname = block[2][block[2].rfind('/')+1:] + block[2] = "settings/themes/"+win.settings["Theme"]+"/icons/"+iconname + + UI_elements. image(layer, win, "settings/themes/"\ + +win.settings["Theme"]+"/icons/"+iconname, + tyleX, + current_Y + win.scroll["markdown"]-30) + tyleX = tyleX + 40 + + # OTHER IMAGES + + # I think the handling of the images loading should be done in the + # UI_elements.py file. So I could easy reimplement this feature + # else where. + + else: + + UI_elements. image(layer, win, block[2], + tyleX, + current_Y + win.scroll["markdown"]-15, + cell="markdown",offset=[x,y],width=width-40,fit="fit_width") + try: + imH = win.images["markdown"][block[2]]['image'].get_height() + imW = win.images["markdown"][block[2]]['image'].get_width() + except: + imH = 40 + imW = 40 + + tyleX = tyleX + imW + + newX = imW + 40 + newY = imH - 20 + + # LINKED IMAGES + + if "link" in block[0]: + + # If the image is linked. We are going to separate it in 2 categoies. + # If automatic downloading is on. There is no difference. Else. There + # will be a difference. Since the image from the Internet going to be + # a button to download it. We need to offset the link button. SO. + + def do(): + if block[2].endswith(".md"): + win.current["mdfs"]["failsafe"] = filename + win.current["mdfs"][name] = block[3] + win.current["current_help_selected"] = "" + else: + oscalls.Open(block[3]) + + try: + downloadbutton = win.images["markdown"][block[2]]["image"] == "download_button" + except: + downloadbutton = False + + + if not win.settings["auto_download_images"]\ + and block[2].startswith("http")\ + and downloadbutton: + + # Here goes the offsetted link. + + UI_elements.roundrect(layer, win, tyleX, + current_Y + win.scroll["markdown"]-15,40,40,10, + icon="internet", + button=do, + offset=[x,y], + tip=block[3]) + + tyleX = tyleX + 60 + + else: + + # Full on image + + UI_elements.roundrect(layer, win, tyleX-imW, + current_Y + win.scroll["markdown"]-15,imW, imH,10, + button=do, + offset=[x,y], + tip=block[3], + fill=False) + layer.stroke() + + # TEXT + + elif block[0] in ["text", "text_i", "text_b", "text_ib", "text_c", "link"]: + for word in block[1].split(" "): + + if tyleX + len(word)*12+12 > width : + tyleX = newX + newY = max(0, newY-30) + if newY == 0: + newX = 10 + current_Y = current_Y + 30 + + # Any type of Text. Whether it's Normal, Bold or Italic gonna + # have the same color. + + if "text" in block[0]: + UI_color.set(layer, win, "text_normal") + UI_color.set(layer_i, win, "text_normal") + UI_color.set(layer_b, win, "text_normal") + UI_color.set(layer_bi, win, "text_normal") + + # Unless it's a link. Then I have a special color for it in the + # theme. I tried reusing pre-existing. Non of them works across + # multiple themes. + + else: + + + # Here I gonna introduce the logic of the links. Because + # I'm lazy. + + if "markdown_mouse_link" not in win.current: + win.current["markdown_mouse_link"] = "" + + if win.current["mx"] in range(int(x+tyleX-6), int(x+tyleX-6+len(word)*12+12))\ + and win.current["my"] in range(int(y+current_Y + win.scroll["markdown"]-20), + int(y+current_Y + win.scroll["markdown"]+5)): + win.current["markdown_mouse_link"] = block[2] + + UI_elements.tooltip(win,block[2]) + + # AHh... I'll do a clicker here. + if not win.current["LMB"] and win.previous["LMB"]: + + if block[2].endswith(".md"): + win.current["mdfs"]["failsafe"] = filename + win.current["mdfs"][name] = block[2] + win.current["current_help_selected"] = "" + elif block[2].startswith("#"): + win.current["mdfs"][name] = win.current["mdfs"][name] + block[2] + win.current["current_help_selected"] = "" + else: + oscalls.Open(block[2]) + + + elif win.current["mx"] not in range(win.previous["mx"]-5, win.previous["mx"]+5): + win.current["markdown_mouse_link"] = "" + + + + # If mouse hovering over a link. Draw a line under the link. + + if win.current["markdown_mouse_link"] == block[2]: + UI_color.set(layer, win, "text_normal") + UI_elements.roundrect(layer, win, + tyleX-6, + current_Y + win.scroll["markdown"], + len(word)*12+12, + 4, + 2) + + UI_color.set(layer, win, "text_link") + + + # Italic text + + if "_i" in block[0]: + layer_i.set_font_size(20) + layer_i.move_to( + tyleX, + current_Y + win.scroll["markdown"] + ) + layer_i.show_text(word.replace("\n", "")) + + # Bold text + + elif "_b" in block[0]: + layer_b.set_font_size(20) + layer_b.move_to( + tyleX, + current_Y + win.scroll["markdown"] + ) + layer_b.show_text(word.replace("\n", "")) + + # Any other text + + else: + + if "_c" in block[0]: + + UI_color.set(layer, win, "node_background") + UI_elements.roundrect(layer, win, + tyleX-6, + current_Y + win.scroll["markdown"]-20, + len(word)*12+12, + 25, + 5) + UI_color.set(layer, win, "text_normal") + + layer.set_font_size(20) + layer.move_to( + tyleX, + current_Y + win.scroll["markdown"] + ) + layer.show_text(word.replace("\n", "")) + + # Moving of to the next word. + + if "\n" in word: + tyleX = newX + newY = max(0, newY-30) + if newY == 0: + newX = 10 + current_Y = current_Y + 30 + else: + + tyleX = tyleX + len(word)*12+12 + + + + + + ############################################################################ + + # Scroll + UI_elements.scroll_area(outlayer, win, "markdown", + x+0, + y+0, + width+30, + height-0, + current_Y, + bar=True, + mmb=True, + bar_always=True) + + + # Outputting the layer + outlayer.set_source_surface(textsurface, x, y) + outlayer.paint() + + + + diff --git a/UI/UI_elements.py b/UI/UI_elements.py index 345eb15..af34499 100644 --- a/UI/UI_elements.py +++ b/UI/UI_elements.py @@ -5,6 +5,7 @@ import os import math +import urllib3 import hashlib import threading @@ -232,13 +233,71 @@ def hash_file(f): return "FOLDER" def loadimage(layer, win ,path, x, y, width, height, fit, cell=0): + + # Before we load an image we have to know whether the image is local + # in the Internet. Markdown files for example can have links to a + # picture in the internet. And so if a given Image URL is not local + # we have to be able to download it. + + # For reasons we all can relate to. I don't want such downloading to + # happen automatically. Unless the user is going to enable auto + # download in the settings. + + # Let's set up a setting. I'm doing it here because Images drawn + # first. On the main screen. And the setting does not exists in + # the earlier settings file from the earlier version. + + if "auto_download_images" not in win.settings: + win.settings["auto_download_images"] = False + settings.write("auto_download_images", win.settings["auto_download_images"]) + + filename = "/tmp/"+path.replace("/","_") + tmppath = "" + + if path.startswith("http") and not os.path.exists(filename): + + + if win.images[cell][path]["image"] != "downloading": + + # If the button is not pressed yet. Then we need to + # put a downlod button. Look down where implement + # the drawing of the image for the button it self. + + win.images[cell][path]["loading"] = False + win.images[cell][path]["image"] = "download_button" + return + + else: + + # Now somebody either pressed the button. Or it set to + # automatic downloads. Then, let's get the file. + + win.images[cell][path]["image"] = None + + http = urllib3.PoolManager() + r = http.request('GET', path, preload_content=False) + with open(filename, 'wb') as out: + while True: + data = r.read(1024) + if not data: + break + out.write(data) + + r.release_conn() + + + elif path.startswith("http"): + tmppath = path + path = filename + + + # Also I don't want downloading to happen here. Since if it's not + # downloaded # So multiple types of the image could be loaded. It could be either # an image file. Like png or jpeg. Either a video file. Or a blend file # each with it's own loading problems. - - - + # While cairo can read pngs directly. It's not the best way of doing it # since it's not capable of reading jpegs and other files. So let's do # something about it. @@ -260,6 +319,7 @@ def loadimage(layer, win ,path, x, y, width, height, fit, cell=0): try: load1 = GdkPixbuf.Pixbuf.new_from_file(path) except: + try: load1 = GdkPixbuf.Pixbuf.new_from_file("settings/themes/"+win.settings["Theme"]+"/icons/image.png") except: @@ -395,7 +455,25 @@ def loadimage(layer, win ,path, x, y, width, height, fit, cell=0): imagedraw.scale(factor, factor) dx = (width/2)/factor -(load2.get_width() /2) dy = (height/2)/factor -(load2.get_height()/2) + + # Finally I need to implement something but the Crop. + # Fit Width I want to use in MarkDowns. Maybe also in the + # text of the script. Makes sense. + elif fit == "fit_width" and load2.get_width() > width: + factor = width / load2.get_width() + dx = 0 + dy = 0 + imagesurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(load2.get_height()*factor)) + imagedraw = cairo.Context(imagesurface) + imagedraw.scale(factor, factor) + elif fit == "fit_width": + dx = 0 + dy = 0 + imagesurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(load2.get_width()), int(load2.get_height())) + imagedraw = cairo.Context(imagesurface) + + # Let's make an ability for theme makers to simply color the standard # icons into any shade. @@ -405,6 +483,8 @@ def loadimage(layer, win ,path, x, y, width, height, fit, cell=0): imagesurface = load2 # Saving it into the win.images + if tmppath: + path = tmppath win.images[cell][path]["loading"] = False win.images[cell][path]["image"] = imagesurface win.images[cell][path]["hash"] = hash_file(path) @@ -426,7 +506,7 @@ def reload_images(win): pass -def image(layer, win ,path, x, y, width=0, height=0, fit="crop", cell=0): +def image(layer, win ,path, x, y, width=0, height=0, fit="crop", cell=0, offset=[0,0]): # This module will handle drawing images to the layers. It's not that hard # to do in cairo by default. But i'm doing it at every frame. And so it @@ -444,7 +524,7 @@ def image(layer, win ,path, x, y, width=0, height=0, fit="crop", cell=0): win.images[cell] = {} if int(x) not in range(int(0-width ), int(win.current["w"])) or \ - int(y) not in range(int(0-height), int(win.current["h"])) : + int(y) not in range(int(0-height-win.current["h"]), int(win.current["h"])) : return # If you ran this software you probably noticed that images are loading @@ -493,26 +573,28 @@ def image(layer, win ,path, x, y, width=0, height=0, fit="crop", cell=0): #loading it back else: - if win.images[cell][path]["image"]: + if win.images[cell][path]["image"] and win.images[cell][path]["image"] != "download_button": imagesurface = win.images[cell][path]["image"] # Writting the image to the screen - - if "icons" in win.color and "settings/themes/" in path: - - UI_color.set(layer, win, "icons") - layer.rectangle(x,y,0,0) - layer.fill() - - layer.mask_surface(imagesurface, x, y) - - UI_color.set(layer, win, "icons") - layer.fill() - else: - layer.set_source_surface(imagesurface, x, y) - layer.paint() + try: + if "icons" in win.color and "settings/themes/" in path: + + UI_color.set(layer, win, "icons") + layer.rectangle(x,y,0,0) + layer.fill() + + layer.mask_surface(imagesurface, x, y) + + UI_color.set(layer, win, "icons") + layer.fill() + else: + layer.set_source_surface(imagesurface, x, y) + layer.paint() + except: + pass # And if testing @@ -520,6 +602,34 @@ def image(layer, win ,path, x, y, width=0, height=0, fit="crop", cell=0): UI_color.set(layer, win, "testing_image") layer.rectangle(x,y,imagesurface.get_width(),imagesurface.get_height()) layer.stroke() + + elif win.images[cell][path]["image"] == "download_button": + + # If the image is online. By default it will not load it unless the + # user presses a download button. So here it is. + + def do(): + win.images[cell][path]["image"] = "downloading" + loadimage(layer, win ,path, x, y, width, height, fit, cell) + win.images[cell][path]["loading"] = True + + # Some link image will be automatically clicked. This + # fixes the problem. + win.current["LMB"] = False + win.previous["LMB"] = False + + + if win.settings["auto_download_images"]: + t = threading.Thread(target=do) + t.start() + else: + + roundrect(layer, win, x,y,40,40,10, + icon="image_link", + button=do, + offset=offset, + tip=path) + def tooltip(win, text): diff --git a/UI/UI_helpDialog.py b/UI/UI_helpDialog.py index 4634ba7..b149ff2 100644 --- a/UI/UI_helpDialog.py +++ b/UI/UI_helpDialog.py @@ -25,6 +25,7 @@ from project_manager import pm_project from UI import UI_elements from UI import UI_color from UI import UI_math +from UI import UI_Markdown # Studio from studio import studio_dialogs @@ -62,7 +63,7 @@ def layer(win, call): UI_color.set(layer, win, "node_background") UI_elements.roundrect(layer, win, - win.current["w"]/2-250, + 100, 100, 500, win.current["h"]-200, @@ -70,13 +71,15 @@ def layer(win, call): + + # Exit button def do(): win.current["calls"][call]["var"] = False UI_elements.roundrect(layer, win, - win.current["w"]/2-20, + 560, win.current["h"]-140, 40, 40, @@ -86,7 +89,7 @@ def layer(win, call): tip=talk.text("cancel")) - x = win.current["w"]/2-250 + 10 + x = 110 y = 170 width = 500 - 20 height = win.current["h"]-270 @@ -106,6 +109,17 @@ def layer(win, call): width/2-50, 40) + ### MARKDOWN + + + + UI_Markdown.draw(layer, win, "help_markdown", + 700, + 100, + win.current["w"]-800, + win.current["h"]-200) + + # Clip UI_elements.roundrect(layer, win, @@ -142,11 +156,20 @@ def layer(win, call): # create a little dictionary documentations = { + talk.text("readme"):[ + ["Markdown", "README.md"], + ["scene", "https://notabug.org/jyamihud/VCStudio/src/master/README.md"] + ], + talk.text("license"):[ + ["Markdown", "LICENSE.md"], + ], talk.text("documentation_installation"):[ - ["scene", "https://notabug.org/jyamihud/VCStudio/wiki/Documenation+%7C+Installation+%7C+Version+20.128"] + ["scene", "https://notabug.org/jyamihud/VCStudio/wiki/Documenation+%7C+Installation+%7C+Version+20.128"], + ["video", "https://open.lbry.com/@blender-organizer:5/rnd0001-4061:1?r=7YADjAZEbHJg8n4qV5rAuBh5Hca7cZQK"] ], talk.text("documentation_project_manager"):[ - ["scene", "https://notabug.org/jyamihud/VCStudio/wiki/Documenation+%7C+Project+Manager+%7C+Version+20.128"] + ["scene", "https://notabug.org/jyamihud/VCStudio/wiki/Documenation+%7C+Project+Manager+%7C+Version+20.128"], + ["video", "https://open.lbry.com/@blender-organizer:5/Victorious-Children-Studio-Organizer-%28-VCStudio-%29---Project-Manager-Tutorial---Creating-Projects---Scanning-the-OS---Settings:7?r=7YADjAZEbHJg8n4qV5rAuBh5Hca7cZQK"] ], talk.text("documentation_story_editor"):[ ["scene", "https://notabug.org/jyamihud/VCStudio/wiki/Documenation+%7C+Story+Editor+%7C+Version+20.128+"] @@ -186,9 +209,9 @@ def layer(win, call): # Let's make the search work. # First I want it to automatically select the stuff with the right name - if win.text["in_help"]["text"] != win.current["current_help_selected"]\ - and win.text["in_help"]["text"].lower() == name.lower(): + if win.text["in_help"]["text"].lower() == name.lower(): win.current["current_help_selected"] = name + win.text["in_help"]["text"] = "" # Now let's ignore all those not in the search if win.text["in_help"]["text"] and win.text["in_help"]["text"].lower() not in name.lower(): @@ -242,6 +265,23 @@ def layer(win, call): # Let's not list all the entries. for entry in doc: + + + + if entry[0] == "Markdown": + + # Sometimes a language File is provided. let's + # look for it. + + l = win.settings["Language"] + + if os.path.exists(os.getcwd()+"/"+entry[1][:-3]+"_"+l+".md"): + entry[1] = entry[1][:-3]+"_"+l+".md" + + win.current["mdfs"]["help_markdown"] = entry[1] + #win.current["current_help_selected"] = "" + + continue # Launch button def do(): @@ -268,7 +308,56 @@ def layer(win, call): else: current_Y = current_Y + 50 + + + # Call + def do(): + os.system("xdg-open https://meet.jit.si/VCStudioDevelopmentConference") + + UI_elements.roundrect(layer, win, + x, + y+current_Y + win.scroll["help"], + width, + 40, + 10, + button=do, + icon="call", + tip=talk.text("contact_us_tip")) + + + UI_color.set(layer, win, "text_normal") + layer.set_font_size(20) + layer.move_to(x+50, + y+current_Y + win.scroll["help"]+25) + layer.show_text(talk.text("contact_us_now")) + + current_Y = current_Y + 50 + + # Report Bug Button + def do(): + os.system("xdg-open https://notabug.org/jyamihud/VCStudio/issues/new") + + + UI_elements.roundrect(layer, win, + x, + y+current_Y + win.scroll["help"], + width, + 40, + 10, + button=do, + icon="bug", + tip=talk.text("report_bug_tip")) + + + UI_color.set(layer, win, "text_normal") + layer.set_font_size(20) + layer.move_to(x+50, + y+current_Y + win.scroll["help"]+25) + layer.show_text(talk.text("report_bug_now")) + + current_Y = current_Y + 50 + ########################### UI_elements.scroll_area(layer, win, "help",