From 8d58a7576d83bac9806c96df2fb06e2c36563855 Mon Sep 17 00:00:00 2001 From: gucio321 <73652197+gucio321@users.noreply.github.com> Date: Mon, 11 Nov 2024 12:36:46 +0100 Subject: [PATCH 1/6] markdown: partially re-enable markdown now it at least renders something By something I mean the following works: - plain text - bullet points - indent --- Markdown.go | 230 ++++++++++++++++++++++++++++++++-------------------- go.mod | 4 +- go.sum | 2 + 3 files changed, 144 insertions(+), 92 deletions(-) diff --git a/Markdown.go b/Markdown.go index 9aa407fc..d064654a 100644 --- a/Markdown.go +++ b/Markdown.go @@ -1,20 +1,55 @@ //nolint:gocritic,govet,wsl,revive // this file is TODO. We don't want commentedOutCode lint issues here. package giu +import ( + "image" + "net/http" + "strings" + "time" + + "github.com/AllenDang/cimgui-go/imgui" + "github.com/AllenDang/cimgui-go/immarkdown" +) + +type markdownState struct { + cfg immarkdown.MarkdownConfig +} + +func (m *markdownState) Dispose() { + // noop +} + +func (m *MarkdownWidget) getState() *markdownState { + if s := GetState[markdownState](Context, m.id); s != nil { + return s + } + + newState := m.newState() + SetState[markdownState](Context, m.id, newState) + return newState +} + +func (m *MarkdownWidget) newState() *markdownState { + cfg := immarkdown.NewMarkdownConfigEmpty() + fmtCb := immarkdown.MarkdownFormalCallback(mdFormatCallback) + cfg.SetFormatCallback(&fmtCb) + return &markdownState{ + cfg: *cfg, + } +} + // MarkdownWidget implements DearImGui markdown extension // https://github.com/juliettef/imgui_markdown // It is like LabelWidget but with md formatting. -// TODO: re-implement this. type MarkdownWidget struct { - md *string - linkCb func(url string) - // headers []imgui.MarkdownHeaderData + md string + id ID + linkCb func(url string) + headers []immarkdown.MarkdownHeadingFormat } // Markdown creates new markdown widget. -func Markdown(md *string) *MarkdownWidget { - panic("MarkdownWidget is not implemented yet!") - +func Markdown(md string) *MarkdownWidget { return &MarkdownWidget{ md: md, linkCb: OpenURL, @@ -31,97 +66,112 @@ func (m *MarkdownWidget) OnLink(cb func(url string)) *MarkdownWidget { // NOTE: level (counting from 0!) is header level. (for instance, header `# H1` will have level 0). func (m *MarkdownWidget) Header(level int, font *FontInfo, separator bool) *MarkdownWidget { // ensure if header data are at least as long as level - // if m.headers == nil { - // m.headers = make([]imgui.MarkdownHeaderData, level) - //} + if m.headers == nil { + m.headers = make([]immarkdown.MarkdownHeadingFormat, level) + } - // if level <= len(m.headers) { - // m.headers = append(m.headers, make([]imgui.MarkdownHeaderData, len(m.headers)-level+1)...) - //} + if level <= len(m.headers) { + m.headers = append(m.headers, make([]immarkdown.MarkdownHeadingFormat, len(m.headers)-level+1)...) + } - // if font != nil { - // if f, ok := Context.FontAtlas.extraFontMap[font.String()]; ok { - // m.headers[level].Font = *f - // } - //} + m.headers[level] = *immarkdown.NewMarkdownHeadingFormatEmpty() + if font != nil { + if f, ok := Context.FontAtlas.extraFontMap[font.String()]; ok { + m.headers[level].SetFont(f) + } + } - // m.headers[level].HasSeparator = separator + m.headers[level].SetSeparator(separator) return m } // Build implements Widget interface. func (m *MarkdownWidget) Build() { - // imgui.Markdown(Context.FontAtlas.RegisterStringPointer(m.md), m.linkCb, loadImage, m.headers) + state := m.getState() + immarkdown.Markdown( + Context.FontAtlas.RegisterString(m.md), + uint64(len(m.md)), + state.cfg, + ) + // m.linkCb, loadImage, m.headers) } -//func loadImage(path string) imgui.MarkdownImageData { -// var img *image.RGBA -// -// var err error -// -// switch { -// case strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://"): -// Load image from url -//client := &http.Client{Timeout: 5 * time.Second} -//resp, respErr := client.Get(path) -// -//if respErr != nil { -// return imgui.MarkdownImageData{} -//} -// -//defer func() { -// closeErr := resp.Body.Close() -// Assert((closeErr == nil), "MarkdownWidget", "loadImage", "Could not close http request!") -//}() -// -//rgba, _, imgErr := image.Decode(resp.Body) -//if imgErr != nil { -// return imgui.MarkdownImageData{} -//} -// -//img = ImageToRgba(rgba) -//default: -// img, err = LoadImage(path) -// if err != nil { -// return imgui.MarkdownImageData{} -// } -//} -// -//size := img.Bounds() -// -//nolint:gocritic // TODO/BUG: figure out, why it doesn't work as expected and consider -//if current workaround is save -///* -// tex := &Texture{} -// NewTextureFromRgba(img, func(t *Texture) { -// fmt.Println("creating texture") -// tex.id = t.id -// }) -//*/ -// -//var id imgui.TextureID -// -//mainthread.Call(func() { -// var err error -// id, err = Context.renderer.LoadImage(img) -// if err != nil { -// return -// } -//}) -// -//return imgui.MarkdownImageData{ -// TextureID: &id, -// Scale: true, -// Size: imgui.Vec2{ -// X: float32(size.Dx()), -// Y: float32(size.Dy()), -// }, -// UseLinkCallback: true, -// default values -//Uv0: ToVec2(image.Point{0, 0}), -//Uv1: ToVec2(image.Point{1, 1}), -//TintColor: ToVec4Color(color.RGBA{255, 255, 255, 255}), -//BorderColor: ToVec4Color(color.RGBA{0, 0, 0, 0}), -//} -//} +func loadImage(path string) immarkdown.MarkdownImageData { + var ( + img *image.RGBA + err error + ) + + switch { + case strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://"): + // Load image from url + + client := &http.Client{Timeout: 5 * time.Second} + resp, respErr := client.Get(path) + if respErr != nil { + return *immarkdown.NewMarkdownImageDataEmpty() + } + + defer func() { + closeErr := resp.Body.Close() + Assert((closeErr == nil), "MarkdownWidget", "loadImage", "Could not close http request!") + }() + + rgba, _, imgErr := image.Decode(resp.Body) + if imgErr != nil { + return *immarkdown.NewMarkdownImageDataEmpty() + } + + img = ImageToRgba(rgba) + default: + img, err = LoadImage(path) + if err != nil { + return *immarkdown.NewMarkdownImageDataEmpty() + } + } + + size := img.Bounds() + + // if current workaround is save + /* + tex := &Texture{} + NewTextureFromRgba(img, func(t *Texture) { + fmt.Println("creating texture") + tex.id = t.id + }) + */ + + var id imgui.TextureID + + mainthreadCallPlatform(func() { + // TODO: actually load this hehe + /* + var err error + id, err = Context.renderer.LoadImage(img) + if err != nil { + return + } + */ + }) + + result := immarkdown.NewMarkdownImageDataEmpty() + result.SetUsertextureid(id) + // Scale: true, + result.SetSize(imgui.Vec2{ + X: float32(size.Dx()), + Y: float32(size.Dy()), + }) + // UseLinkCallback: true, + // default values + // + // Uv0: ToVec2(image.Point{0, 0}), + // Uv1: ToVec2(image.Point{1, 1}), + // TintColor: ToVec4Color(color.RGBA{255, 255, 255, 255}), + // BorderColor: ToVec4Color(color.RGBA{0, 0, 0, 0}), + return *result +} + +func mdFormatCallback(f immarkdown.MarkdownFormatInfo, start bool) { + // noop +} diff --git a/go.mod b/go.mod index 5000f4e0..e3afc307 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/AllenDang/giu -go 1.23.2 +go 1.23.3 require ( - github.com/AllenDang/cimgui-go v1.1.1-0.20241105214716-82a5c1ae9712 + github.com/AllenDang/cimgui-go v1.1.1-0.20241110184948-72c467a7f306 github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8 github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 github.com/gucio321/glm-go v0.0.0-20241029220517-e1b5a3e011c8 diff --git a/go.sum b/go.sum index 6e3aca82..9d72cfc6 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/AllenDang/cimgui-go v1.1.1-0.20241105214716-82a5c1ae9712 h1:Qog9ZG14NbkuzbqzwT7zX9u+yi1fTU8ZIlesefYmc40= github.com/AllenDang/cimgui-go v1.1.1-0.20241105214716-82a5c1ae9712/go.mod h1:/gM0PosnwlgK0Fc3UFALXWPEIu+cW2DC3YU0Z4EwV2Y= +github.com/AllenDang/cimgui-go v1.1.1-0.20241110184948-72c467a7f306 h1:B0zIFc0Y0kp5kYlI0gtZXh10bIhtWy0ClDzexJlCnxY= +github.com/AllenDang/cimgui-go v1.1.1-0.20241110184948-72c467a7f306/go.mod h1:/gM0PosnwlgK0Fc3UFALXWPEIu+cW2DC3YU0Z4EwV2Y= github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8 h1:dKZMqib/yUDoCFigmz2agG8geZ/e3iRq304/KJXqKyw= github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8/go.mod h1:b4uuDd0s6KRIPa84cEEchdQ9ICh7K0OryZHbSzMca9k= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= From ad5cb283d56563c7bff8aaa9208e72a27f586a06 Mon Sep 17 00:00:00 2001 From: gucio321 <73652197+gucio321@users.noreply.github.com> Date: Mon, 11 Nov 2024 12:41:41 +0100 Subject: [PATCH 2/6] examples/markdown: handle a tiny api change now the Markdown creator doesn't require string pointer --- examples/markdown/markdown.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/markdown/markdown.go b/examples/markdown/markdown.go index a6b9bdc4..b2a9bf60 100644 --- a/examples/markdown/markdown.go +++ b/examples/markdown/markdown.go @@ -67,7 +67,7 @@ func loop() { giu.InputTextMultiline(&markdown).Size(availableW, availableH).Build() }), }, - giu.Markdown(&markdown). + giu.Markdown(markdown). Header(0, (giu.Context.FontAtlas.GetDefaultFonts())[0].SetSize(28), true). Header(1, (giu.Context.FontAtlas.GetDefaultFonts())[0].SetSize(26), false). Header(2, nil, true), From 87c8aaa497bb959bfec79653efbaf7398a6c739e Mon Sep 17 00:00:00 2001 From: gucio321 <73652197+gucio321@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:31:49 +0100 Subject: [PATCH 3/6] markdown: finish markdown workflow adds the following: - images support - a bit redesign headings (still doesn't work) --- Markdown.go | 99 +++++++++++++++++++++++++++-------------------------- go.mod | 2 +- go.sum | 4 +++ 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/Markdown.go b/Markdown.go index d064654a..c127630b 100644 --- a/Markdown.go +++ b/Markdown.go @@ -3,16 +3,19 @@ package giu import ( "image" + "image/color" "net/http" "strings" "time" + "github.com/AllenDang/cimgui-go/backend" "github.com/AllenDang/cimgui-go/imgui" "github.com/AllenDang/cimgui-go/immarkdown" ) type markdownState struct { - cfg immarkdown.MarkdownConfig + cfg immarkdown.MarkdownConfig + images map[string]immarkdown.MarkdownImageData } func (m *markdownState) Dispose() { @@ -30,11 +33,26 @@ func (m *MarkdownWidget) getState() *markdownState { } func (m *MarkdownWidget) newState() *markdownState { - cfg := immarkdown.NewMarkdownConfigEmpty() - fmtCb := immarkdown.MarkdownFormalCallback(mdFormatCallback) + cfg := immarkdown.NewEmptyMarkdownConfig() + fmtCb := immarkdown.MarkdownFormalCallback(immarkdown.DefaultMarkdownFormatCallback) cfg.SetFormatCallback(&fmtCb) + + imgCb := immarkdown.MarkdownImageCallback(func(data immarkdown.MarkdownLinkCallbackData) immarkdown.MarkdownImageData { + link := data.Link()[:data.LinkLength()] // this is because imgui_markdown returns the whole text starting on link and returns link length (for some reason) + if existing, ok := m.getState().images[link]; ok { + return existing + } + + result := loadImage(link) + m.getState().images[link] = result + return result + }) + + cfg.SetImageCallback(&imgCb) + return &markdownState{ - cfg: *cfg, + cfg: *cfg, + images: make(map[string]immarkdown.MarkdownImageData), } } @@ -45,7 +63,7 @@ type MarkdownWidget struct { md string id ID linkCb func(url string) - headers []immarkdown.MarkdownHeadingFormat + headers [3]immarkdown.MarkdownHeadingFormat } // Markdown creates new markdown widget. @@ -53,6 +71,12 @@ func Markdown(md string) *MarkdownWidget { return &MarkdownWidget{ md: md, linkCb: OpenURL, + id: GenAutoID("MarkdownWidget"), + headers: [3]immarkdown.MarkdownHeadingFormat{ + *immarkdown.NewEmptyMarkdownHeadingFormat(), + *immarkdown.NewEmptyMarkdownHeadingFormat(), + *immarkdown.NewEmptyMarkdownHeadingFormat(), + }, } } @@ -64,17 +88,14 @@ func (m *MarkdownWidget) OnLink(cb func(url string)) *MarkdownWidget { // Header sets header formatting // NOTE: level (counting from 0!) is header level. (for instance, header `# H1` will have level 0). +// NOTE: since cimgui-go there are only 3 levels (so level < 3 here). This will panic if level >= 3! +// TODO: it actually doesn't work. func (m *MarkdownWidget) Header(level int, font *FontInfo, separator bool) *MarkdownWidget { - // ensure if header data are at least as long as level - if m.headers == nil { - m.headers = make([]immarkdown.MarkdownHeadingFormat, level) - } + // ensure level is in range + Assert(level < 3, "MarkdownWidget", "Header", "Header level must be less than 3!") - if level <= len(m.headers) { - m.headers = append(m.headers, make([]immarkdown.MarkdownHeadingFormat, len(m.headers)-level+1)...) - } + m.headers[level] = *immarkdown.NewEmptyMarkdownHeadingFormat() - m.headers[level] = *immarkdown.NewMarkdownHeadingFormatEmpty() if font != nil { if f, ok := Context.FontAtlas.extraFontMap[font.String()]; ok { m.headers[level].SetFont(f) @@ -83,6 +104,9 @@ func (m *MarkdownWidget) Header(level int, font *FontInfo, separator bool) *Mark m.headers[level].SetSeparator(separator) + state := m.getState() + state.cfg.SetHeadingFormats(&m.headers) + return m } @@ -94,7 +118,6 @@ func (m *MarkdownWidget) Build() { uint64(len(m.md)), state.cfg, ) - // m.linkCb, loadImage, m.headers) } func loadImage(path string) immarkdown.MarkdownImageData { @@ -106,11 +129,10 @@ func loadImage(path string) immarkdown.MarkdownImageData { switch { case strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://"): // Load image from url - client := &http.Client{Timeout: 5 * time.Second} resp, respErr := client.Get(path) if respErr != nil { - return *immarkdown.NewMarkdownImageDataEmpty() + return *immarkdown.NewEmptyMarkdownImageData() } defer func() { @@ -120,58 +142,37 @@ func loadImage(path string) immarkdown.MarkdownImageData { rgba, _, imgErr := image.Decode(resp.Body) if imgErr != nil { - return *immarkdown.NewMarkdownImageDataEmpty() + return *immarkdown.NewEmptyMarkdownImageData() } img = ImageToRgba(rgba) default: img, err = LoadImage(path) if err != nil { - return *immarkdown.NewMarkdownImageDataEmpty() + return *immarkdown.NewEmptyMarkdownImageData() } } size := img.Bounds() // if current workaround is save - /* - tex := &Texture{} - NewTextureFromRgba(img, func(t *Texture) { - fmt.Println("creating texture") - tex.id = t.id - }) - */ - var id imgui.TextureID - mainthreadCallPlatform(func() { - // TODO: actually load this hehe - /* - var err error - id, err = Context.renderer.LoadImage(img) - if err != nil { - return - } - */ - }) + id = backend.NewTextureFromRgba(img).ID - result := immarkdown.NewMarkdownImageDataEmpty() + result := immarkdown.NewEmptyMarkdownImageData() result.SetUsertextureid(id) - // Scale: true, result.SetSize(imgui.Vec2{ X: float32(size.Dx()), Y: float32(size.Dy()), }) - // UseLinkCallback: true, - // default values - // - // Uv0: ToVec2(image.Point{0, 0}), - // Uv1: ToVec2(image.Point{1, 1}), - // TintColor: ToVec4Color(color.RGBA{255, 255, 255, 255}), - // BorderColor: ToVec4Color(color.RGBA{0, 0, 0, 0}), - return *result -} + result.SetUseLinkCallback(true) + result.SetUv0(ToVec2(image.Point{0, 0})) + result.SetUv1(ToVec2(image.Point{1, 1})) + result.SetTintcol(ToVec4Color(color.RGBA{255, 255, 255, 255})) + result.SetBordercol(ToVec4Color(color.RGBA{0, 0, 0, 0})) -func mdFormatCallback(f immarkdown.MarkdownFormatInfo, start bool) { - // noop + result.SetIsValid(true) + + return *result } diff --git a/go.mod b/go.mod index e3afc307..f23ded4a 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AllenDang/giu go 1.23.3 require ( - github.com/AllenDang/cimgui-go v1.1.1-0.20241110184948-72c467a7f306 + github.com/AllenDang/cimgui-go v1.1.1-0.20241111163245-8c039e187bcc github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8 github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 github.com/gucio321/glm-go v0.0.0-20241029220517-e1b5a3e011c8 diff --git a/go.sum b/go.sum index 9d72cfc6..1a127f2e 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,10 @@ github.com/AllenDang/cimgui-go v1.1.1-0.20241105214716-82a5c1ae9712 h1:Qog9ZG14N github.com/AllenDang/cimgui-go v1.1.1-0.20241105214716-82a5c1ae9712/go.mod h1:/gM0PosnwlgK0Fc3UFALXWPEIu+cW2DC3YU0Z4EwV2Y= github.com/AllenDang/cimgui-go v1.1.1-0.20241110184948-72c467a7f306 h1:B0zIFc0Y0kp5kYlI0gtZXh10bIhtWy0ClDzexJlCnxY= github.com/AllenDang/cimgui-go v1.1.1-0.20241110184948-72c467a7f306/go.mod h1:/gM0PosnwlgK0Fc3UFALXWPEIu+cW2DC3YU0Z4EwV2Y= +github.com/AllenDang/cimgui-go v1.1.1-0.20241111141409-85e6553b3257 h1:Mel/E72ffrPxH+FAYgKTTIkbzRFfia6Dp8W+DvuTFk8= +github.com/AllenDang/cimgui-go v1.1.1-0.20241111141409-85e6553b3257/go.mod h1:KT0QhbfG00LVdgN/eOGhnrSSG8lMfdBvYmZJCBgp2JM= +github.com/AllenDang/cimgui-go v1.1.1-0.20241111163245-8c039e187bcc h1:z19BKKTjz+yJtaXGiu2xsziMuDt7k1td3v17kauJHqE= +github.com/AllenDang/cimgui-go v1.1.1-0.20241111163245-8c039e187bcc/go.mod h1:KT0QhbfG00LVdgN/eOGhnrSSG8lMfdBvYmZJCBgp2JM= github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8 h1:dKZMqib/yUDoCFigmz2agG8geZ/e3iRq304/KJXqKyw= github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8/go.mod h1:b4uuDd0s6KRIPa84cEEchdQ9ICh7K0OryZHbSzMca9k= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= From 4c38b33f88d5d6c714b95636da50fa6762cef050 Mon Sep 17 00:00:00 2001 From: gucio321 <73652197+gucio321@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:32:40 +0100 Subject: [PATCH 4/6] Markdown: rename loadImage -> mdLoadImage --- Markdown.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Markdown.go b/Markdown.go index c127630b..50837774 100644 --- a/Markdown.go +++ b/Markdown.go @@ -43,7 +43,7 @@ func (m *MarkdownWidget) newState() *markdownState { return existing } - result := loadImage(link) + result := mdLoadImage(link) m.getState().images[link] = result return result }) @@ -120,7 +120,7 @@ func (m *MarkdownWidget) Build() { ) } -func loadImage(path string) immarkdown.MarkdownImageData { +func mdLoadImage(path string) immarkdown.MarkdownImageData { var ( img *image.RGBA err error @@ -137,7 +137,7 @@ func loadImage(path string) immarkdown.MarkdownImageData { defer func() { closeErr := resp.Body.Close() - Assert((closeErr == nil), "MarkdownWidget", "loadImage", "Could not close http request!") + Assert((closeErr == nil), "MarkdownWidget", "mdLoadImage", "Could not close http request!") }() rgba, _, imgErr := image.Decode(resp.Body) From 7e9ac697825c24cdd8aecb891898413aa4604a74 Mon Sep 17 00:00:00 2001 From: gucio321 <73652197+gucio321@users.noreply.github.com> Date: Mon, 11 Nov 2024 21:39:39 +0100 Subject: [PATCH 5/6] markdown: add link callback support --- Markdown.go | 21 ++++++++++++++------- MasterWindow.go | 5 +++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Markdown.go b/Markdown.go index 50837774..6b2d6b29 100644 --- a/Markdown.go +++ b/Markdown.go @@ -62,27 +62,34 @@ func (m *MarkdownWidget) newState() *markdownState { type MarkdownWidget struct { md string id ID - linkCb func(url string) headers [3]immarkdown.MarkdownHeadingFormat } // Markdown creates new markdown widget. func Markdown(md string) *MarkdownWidget { - return &MarkdownWidget{ - md: md, - linkCb: OpenURL, - id: GenAutoID("MarkdownWidget"), + return (&MarkdownWidget{ + md: md, + id: GenAutoID("MarkdownWidget"), headers: [3]immarkdown.MarkdownHeadingFormat{ *immarkdown.NewEmptyMarkdownHeadingFormat(), *immarkdown.NewEmptyMarkdownHeadingFormat(), *immarkdown.NewEmptyMarkdownHeadingFormat(), }, - } + }).OnLink(OpenURL) } // OnLink sets another than default link callback. +// NOTE: due to cimgui-go's limitation https://github.com/AllenDang/cimgui-go?tab=readme-ov-file#callbacks +// we clear MarkdownLinkCallback pool every frame. No further action from you should be required (just feel informed). +// ref (*MasterWindow).beforeRender func (m *MarkdownWidget) OnLink(cb func(url string)) *MarkdownWidget { - m.linkCb = cb + igCb := immarkdown.MarkdownLinkCallback(func(data immarkdown.MarkdownLinkCallbackData) { + link := data.Link()[:data.LinkLength()] + cb(link) + }) + + m.getState().cfg.SetLinkCallback(&igCb) + return m } diff --git a/MasterWindow.go b/MasterWindow.go index 95089b7e..bd43c138 100644 --- a/MasterWindow.go +++ b/MasterWindow.go @@ -10,6 +10,7 @@ import ( "github.com/AllenDang/cimgui-go/backend/glfwbackend" "github.com/AllenDang/cimgui-go/imgui" "github.com/AllenDang/cimgui-go/imguizmo" + "github.com/AllenDang/cimgui-go/immarkdown" "github.com/AllenDang/cimgui-go/imnodes" "github.com/AllenDang/cimgui-go/implot" "golang.org/x/image/colornames" @@ -201,6 +202,10 @@ func (w *MasterWindow) sizeChange(_, _ int) { } func (w *MasterWindow) beforeRender() { + // Clean callbacks + // see https://github.com/AllenDang/cimgui-go?tab=readme-ov-file#callbacks + immarkdown.ClearMarkdownLinkCallbackPool() + Context.FontAtlas.rebuildFontAtlas() // process texture load requests From ccdcb4301723d9910d036dfafef4f0062bf8bc45 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 12 Nov 2024 18:21:31 +0100 Subject: [PATCH 6/6] markdown: linting --- Markdown.go | 35 +++++++-------- examples/markdown/markdown.go | 82 +++++++++++++++++------------------ go.mod | 2 +- go.sum | 2 + 4 files changed, 60 insertions(+), 61 deletions(-) diff --git a/Markdown.go b/Markdown.go index 6b2d6b29..0f55f167 100644 --- a/Markdown.go +++ b/Markdown.go @@ -1,4 +1,3 @@ -//nolint:gocritic,govet,wsl,revive // this file is TODO. We don't want commentedOutCode lint issues here. package giu import ( @@ -22,6 +21,15 @@ func (m *markdownState) Dispose() { // noop } +// MarkdownWidget implements DearImGui markdown extension +// https://github.com/juliettef/imgui_markdown +// It is like LabelWidget but with md formatting. +type MarkdownWidget struct { + md string + id ID + headers [3]immarkdown.MarkdownHeadingFormat +} + func (m *MarkdownWidget) getState() *markdownState { if s := GetState[markdownState](Context, m.id); s != nil { return s @@ -29,12 +37,16 @@ func (m *MarkdownWidget) getState() *markdownState { newState := m.newState() SetState[markdownState](Context, m.id, newState) + return newState } func (m *MarkdownWidget) newState() *markdownState { cfg := immarkdown.NewEmptyMarkdownConfig() - fmtCb := immarkdown.MarkdownFormalCallback(immarkdown.DefaultMarkdownFormatCallback) + fmtCb := immarkdown.MarkdownFormalCallback(func(data *immarkdown.MarkdownFormatInfo, start bool) { + immarkdown.DefaultMarkdownFormatCallback(*data, start) + }) + cfg.SetFormatCallback(&fmtCb) imgCb := immarkdown.MarkdownImageCallback(func(data immarkdown.MarkdownLinkCallbackData) immarkdown.MarkdownImageData { @@ -45,6 +57,7 @@ func (m *MarkdownWidget) newState() *markdownState { result := mdLoadImage(link) m.getState().images[link] = result + return result }) @@ -56,15 +69,6 @@ func (m *MarkdownWidget) newState() *markdownState { } } -// MarkdownWidget implements DearImGui markdown extension -// https://github.com/juliettef/imgui_markdown -// It is like LabelWidget but with md formatting. -type MarkdownWidget struct { - md string - id ID - headers [3]immarkdown.MarkdownHeadingFormat -} - // Markdown creates new markdown widget. func Markdown(md string) *MarkdownWidget { return (&MarkdownWidget{ @@ -81,7 +85,7 @@ func Markdown(md string) *MarkdownWidget { // OnLink sets another than default link callback. // NOTE: due to cimgui-go's limitation https://github.com/AllenDang/cimgui-go?tab=readme-ov-file#callbacks // we clear MarkdownLinkCallback pool every frame. No further action from you should be required (just feel informed). -// ref (*MasterWindow).beforeRender +// ref (*MasterWindow).beforeRender. func (m *MarkdownWidget) OnLink(cb func(url string)) *MarkdownWidget { igCb := immarkdown.MarkdownLinkCallback(func(data immarkdown.MarkdownLinkCallbackData) { link := data.Link()[:data.LinkLength()] @@ -137,6 +141,7 @@ func mdLoadImage(path string) immarkdown.MarkdownImageData { case strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://"): // Load image from url client := &http.Client{Timeout: 5 * time.Second} + resp, respErr := client.Get(path) if respErr != nil { return *immarkdown.NewEmptyMarkdownImageData() @@ -161,11 +166,7 @@ func mdLoadImage(path string) immarkdown.MarkdownImageData { } size := img.Bounds() - - // if current workaround is save - var id imgui.TextureID - - id = backend.NewTextureFromRgba(img).ID + id := backend.NewTextureFromRgba(img).ID result := immarkdown.NewEmptyMarkdownImageData() result.SetUsertextureid(id) diff --git a/examples/markdown/markdown.go b/examples/markdown/markdown.go index b2a9bf60..0afe22f1 100644 --- a/examples/markdown/markdown.go +++ b/examples/markdown/markdown.go @@ -3,55 +3,51 @@ package main import ( - "strings" - "github.com/AllenDang/giu" ) +const defaultMd = ` +Wrapping: +Text wraps automatically. To add a new line, use 'Return'. + +Headers: +# H1 +## H2 +### H3 + +Emphasis: +*emphasis* +_emphasis_ +**strong emphasis** +__strong emphasis__ + +Indents: +On a new line, at the start of the line, add two spaces per indent. + Indent level 1 + Indent level 2 + +Unordered lists: +On a new line, at the start of the line, add two spaces, an asterisks and a space. +For nested lists, add two additional spaces in front of the asterisk per list level increment. + * Unordered List level 1 + * Unordered List level 2 + +Link: +Here is [a link to some cool website!](https://github.com/AllenDang/giu) you must click it! +Image: +![gopher image](./gopher.png) +![gopher image link](https://raw.githubusercontent.com/AllenDang/giu/master/examples/loadimage/gopher.png) + +Horizontal Rule: +*** +___ +` + var ( - markdown = getExampleMarkdownText() + markdown = defaultMd splitLayoutPos float32 = 320 ) -func getExampleMarkdownText() string { - return strings.Join([]string{ - "Wrapping:", - "Text wraps automatically. To add a new line, use 'Return'.", - "", - "Headers:", - "# H1", - "## H2", - "### H3", - "", - "Emphasis:", - "*emphasis*", - "_emphasis_", - "**strong emphasis**", - "__strong emphasis__", - "", - "Indents:", - "On a new line, at the start of the line, add two spaces per indent.", - " Indent level 1", - " Indent level 2", - "", - "Unordered lists:", - "On a new line, at the start of the line, add two spaces, an asterisks and a space.", - "For nested lists, add two additional spaces in front of the asterisk per list level increment.", - " * Unordered List level 1", - " * Unordered List level 2", - "", - "Link:", - "Here is [a link to some cool website!](https://github.com/AllenDang/giu) you must click it!", - "Image:", - "![gopher image](./gopher.png)", - "![gopher image link](https://raw.githubusercontent.com/AllenDang/giu/master/examples/loadimage/gopher.png)", - "", - "Horizontal Rule:", - "***", - "___", - }, "\n") -} - func loop() { giu.SingleWindow().Layout( giu.SplitLayout(giu.DirectionHorizontal, &splitLayoutPos, @@ -59,7 +55,7 @@ func loop() { giu.Row( giu.Label("Markdown Edition:"), giu.Button("Reset").OnClick(func() { - markdown = getExampleMarkdownText() + markdown = defaultMd }), ), giu.Custom(func() { diff --git a/go.mod b/go.mod index f23ded4a..c60129e5 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AllenDang/giu go 1.23.3 require ( - github.com/AllenDang/cimgui-go v1.1.1-0.20241111163245-8c039e187bcc + github.com/AllenDang/cimgui-go v1.2.0 github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8 github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 github.com/gucio321/glm-go v0.0.0-20241029220517-e1b5a3e011c8 diff --git a/go.sum b/go.sum index 1a127f2e..e4c1d782 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/AllenDang/cimgui-go v1.1.1-0.20241111141409-85e6553b3257 h1:Mel/E72ff github.com/AllenDang/cimgui-go v1.1.1-0.20241111141409-85e6553b3257/go.mod h1:KT0QhbfG00LVdgN/eOGhnrSSG8lMfdBvYmZJCBgp2JM= github.com/AllenDang/cimgui-go v1.1.1-0.20241111163245-8c039e187bcc h1:z19BKKTjz+yJtaXGiu2xsziMuDt7k1td3v17kauJHqE= github.com/AllenDang/cimgui-go v1.1.1-0.20241111163245-8c039e187bcc/go.mod h1:KT0QhbfG00LVdgN/eOGhnrSSG8lMfdBvYmZJCBgp2JM= +github.com/AllenDang/cimgui-go v1.2.0 h1:xlsBNlGW2n4X6WYi0B84iOoAYWQT+iJFKWM2iZvpzNI= +github.com/AllenDang/cimgui-go v1.2.0/go.mod h1:KT0QhbfG00LVdgN/eOGhnrSSG8lMfdBvYmZJCBgp2JM= github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8 h1:dKZMqib/yUDoCFigmz2agG8geZ/e3iRq304/KJXqKyw= github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8/go.mod h1:b4uuDd0s6KRIPa84cEEchdQ9ICh7K0OryZHbSzMca9k= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=