Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scintilla for ImGui #108

Closed
emoon opened this issue Jan 6, 2015 · 38 comments
Closed

Scintilla for ImGui #108

emoon opened this issue Jan 6, 2015 · 38 comments

Comments

@emoon
Copy link
Contributor

emoon commented Jan 6, 2015

I wonder if there would be any interest in supporting Scintilla http://www.scintilla.org in ImGui. It would likely need to be some form of optional component as it's fairly big.

From my understand is that it's fairly abstracted and can have several backend implementations so this would be a quite advanced text control for ImGui.

@ocornut
Copy link
Owner

ocornut commented Jan 6, 2015

Having looked briefly my understanding it that it would be more a case of adding an ImGui backend for Scintilla ? aka porting porting Scintilla to a new "platform".

Also those two components for wxWidgets are probably good additional references
http://wxcode.sourceforge.net/showcomp.php?name=wxStEdit
http://wxcode.sourceforge.net/showcomp.php?name=wxScintilla
Second one looks more modern (184 KB of code though, ouch)

I might investigate more in the future but this looks like a fairly large piece of work and may be rather low in the priority list.

@emoon
Copy link
Contributor Author

emoon commented Jan 6, 2015

Yeah that is correct. It would be porting Scintilla to a new "platform" and yes it requires quite a bit of code.

Looking at http://svn.code.sf.net/p/wxcode/code/trunk/wxCode/components/wxscintilla/src/wxscintilla.cpp it looks like a big chunk of it is boiler-plate code doing SendMsg(...)

But needs work indeed.

I wonder how one would go about implementing it for ImGui. I guess ImGui would need to expose quite a bit more things in order for this to work (rendering of various primitives, etc)

@emoon
Copy link
Contributor Author

emoon commented Jan 6, 2015

Just a small note:

https://github.com/Gargaj/ScintillaGL

It seems that someone has ported it to OpenGL which would likely save quite a bit of work brining it to ImGui.

Most code is in here:

https://github.com/twinshadow/ScintillaGL/blob/master/Demo/ScPlatform.cxx

I have yet to test how well it works but if one only needs to implement that it doesn't look too bad.

@ocornut
Copy link
Owner

ocornut commented Jan 6, 2015

ImGui::GetWindowDrawList() allows you to render primitives but it may or not be totally suited. But yes I imagine it may requires ImGui it expose some more stuff.

@emoon
Copy link
Contributor Author

emoon commented Jan 6, 2015

Just managed to build the ScintillaGL code after some fixes and this is how it looks:

scintillagl

@emoon
Copy link
Contributor Author

emoon commented Jan 6, 2015

Alright. Good to know.

@emoon
Copy link
Contributor Author

emoon commented Jan 13, 2015

I'm going a head and implementing this but the rendering will likely use bgfx directly just to bring it up and running. That would at least give an idea of what's needed for a full implementation inside ImGui later on.

@ocornut
Copy link
Owner

ocornut commented Jan 13, 2015

Nice!

@emoon
Copy link
Contributor Author

emoon commented Apr 12, 2015

Just want some design ideas for this.

The way the underlying Scintilla code works is that it's based on sending messages.

Like this

SendCommand(SCI_ADDTEXT, textSize, text);
SendCommand(SCI_SETREADONLY, 1);
SendCommand(SCI_SETLEXER, SCLEX_CPP);
...

It's a bit hard to diverge from this and I wonder how to implement this in a good way for ImGui. One way would be something like this (untested)

ScEditorInterface* interface = 0;

ImGui::ScEditor(..., &interface, &myCallbacks); // myCallbacks gets call with messages from the editor

interface->SendCommand(...); // Send stuff to the editor

What I don't like of this approach is that it breaks the "statelessness" of ImGui. As for example

SendCommand(ADD_TEXT, ...);

Should only be sent when text is changed which means the app needs to track when it needs to be changed or not.

Suggestions?

@emoon
Copy link
Contributor Author

emoon commented Apr 12, 2015

Some more details about this:

https://github.com/emoon/ProDBG/blob/master/src/prodbg/ui/imgui_extra.inl#L117

This is how I create the Scintilla widget that is being used in ImGui. Because of the way Scintilla works you don't want to re-create this every frame because that would be expensive (and not likely work correctly)

So I cache it in the Storage section so I don't need to recreate it.

Now once we have the control the Scintilla code support many message you can send to it (set text, style, line, etc, etc)

And my question is how one should expose that from ImGui? That is why I suggested the idea above.

Does that make sense?

@ocornut
Copy link
Owner

ocornut commented Apr 12, 2015

Should only be sent when text is changed which means the app needs to track when it needs to be changed or not.

So you mean that the application needs to send those commands to the underlying Scintilla editor. Is your problem that you don't know what is a neat way to send the initial setup messages? or the subsequent "application/user is doing something" messages?

Your idea above sounds fine, I suppose lots of those messages are the responsibility of the application. The ImGui::ScEditor function could maybe send some of those messages for you. Does ADD_TEXT means "add the initial/current blob of text" or "keyboard input happened", or both? For the later this is the sort of thing the ImGui-side function could perhaps do for the user.

(
You have such a complex widget here you might even need to ask the user to do things in a certain order eventually. Like perhaps you want ScEditor() to only do the creation and placement, and the returned interface has a ->Draw() function that the user needs to call after some initial setup is done (so you don't have a 1-frame lag). Not ideal obviously but I imagine you may run into this sort of thing.
)

May not be a really useful answer, I'm still confused about the nature of the interactions involved here. But your initial approach sounds ok.

@emoon
Copy link
Contributor Author

emoon commented Apr 12, 2015

As you say both initial and user doing something is my problem here.

Because that the Scintilla code supports lots of things you can do during setup (themes, text, layout, etc, etc) it becomes a bit troublesome to put all these settings inside a struct/input params.

Yeah I thought about having it return an Interface also as otherwise you would get a frame lag.

I think that is almost the way to go. I think it may be a good trade-off and if the user want a "advanced edit" control with all the features I guess it may be ok to require a bit more from the user.

@ocornut
Copy link
Owner

ocornut commented Apr 12, 2015

Sounds good. When that's working and stable I suppose it could be revisited. I wouldn't suggest to try to wrap it all in a big data structure just to preserve the "one call" habit.

@emoon
Copy link
Contributor Author

emoon commented Apr 12, 2015

Agreed. I think it would be even more troublesome for the application to setup one big struct instead of providing an interface that can use the SendCommand(...) style and just do the calls needed.

@ocornut
Copy link
Owner

ocornut commented Jul 18, 2015

From @bkaradzic

Check this out:
https://github.com/bkaradzic/bgfx/blob/master/examples/common/imgui/scintilla.cpp#L1066

I think it's pretty clean way to expose Scintilla in ImGui style. Single function to get Scintilla editor, >and if user wants to access Scintilla it can be done directly, or with some wrapper (QScintilla is >good example of nice wrapper). Only problem is that leaks memory since ImGui there is no way to >release memory once internal storage is cleaned up. In bgfx for similar case I allow user to specify >release function and user data, and then that's called on release.
See: https://github.com/bkaradzic/bgfx/blob/master/include/bgfx.h#L656

Will have to look into pattern for storing and freeing memory. Here's it's only using the ImGuiStorage of the window to store a void* - that could be stored by the user as well and freed on Shutdown. The question is to decide what's the lifetime of a Scintilla widget and when do we clean it up, if you wwe want to do that BEFORE shutdown.

I suspect the call to AddDrawCmd() are creating unnecessary extra draw calls.

@emoon
Copy link
Contributor Author

emoon commented Jul 18, 2015

This is pretty much how I have implemented the code before it went into bgfx. I added the ImGuiStorage for void pointers to just support this.

https://github.com/emoon/ProDBG/blob/master/src/prodbg/ui/bgfx/imgui_extra.inl#L86

My code also uses the ImGuiListClipper to provide proper scrolling of the text with a scrollbar.

@emoon
Copy link
Contributor Author

emoon commented Jul 19, 2015

I think we can close this issue though from my point of view. My current implementation works just fine with ImGui.

The only more thing I can think about is to have it as a "extension" for ImGui in some way but that would likely need some added functionally to the core library to support that in an more easy way. The current way with imgui_extra works fine when doing local extensions but if one wants to supply extensions to other people something more flexible would be needed.

@ocornut
Copy link
Owner

ocornut commented Jul 19, 2015

Yeah I think that'll be part of Cleanup (still experimenting with combinations here)

Interesting there's nothing left in that function that's can't be done from the public API. By using the clipper and declaring a size you are moving the cursor so you don't need to call ItemAdd/itemSize which are the main functions that are still private.

    ImGuiWindow* window = GetCurrentWindow();
    const ImGuiID id = window->GetID(label);

becomes

   ImGuiID ImGui::GetID(label);
window->Size.x - 20, (int)window->Size.y

becomes

ImGuI::GetWindowSize()

It's still a bit wrong in the sense that it doesn't honor all layout features consistently with other widgets but it's probably all you need in that context.

@emoon
Copy link
Contributor Author

emoon commented Jul 19, 2015

Yeah. quite a bunch of code in there is currently just testing things around which I haven't cleaned up yet but right now I'm not really missing anything I need to do the cleanup, I just haven't got around doing it yet.

@ocornut
Copy link
Owner

ocornut commented Aug 24, 2015

I'll close this now. With imgui_internal.h it should be easier/natural to just do this sort of stuff.
Eventually it would be nice to include a Scintilla example, that may come when we structures ourselves better to share imgui code/extensions.

On the memory freeing I think it is best tracked by the user and then the user wouldn't use the storage helper but their own storage and have control over lifetime (especially as Scintilla components are likely to be heavy and you want your app to be able to clean them up).

@ocornut ocornut closed this as completed Aug 24, 2015
@emoon
Copy link
Contributor Author

emoon commented Aug 24, 2015

Yeah this is fine. For my point of view I have everything I need to get this working good.

@r-lyeh-archived
Copy link

hey @emoon, it seems I came a lil bit too late to the party :)

It seems you switched to bgfx rendering, then moved to Rust lately. So, can you point me the commit id to the best/most stable imgui code w/ scintillaGL you had available (pure imgui/C++ I assume)?

Thanks in advance :)

@emoon
Copy link
Contributor Author

emoon commented Apr 11, 2016

@r-lyeh I can point you to the relevant files :) Notice that the code still need a bunch of work but its actually working. Also while I do use Rust for ProDBG now a bunch of the "external" code will still be C++ as there is no point to rewrite that which I don't "own" directly or if it would be too much headache.

https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/sc_platform_bgfx.cpp
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/ui_sc_editor.cpp
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/ui_sc_editor.h
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/imgui_extra.inl

ScInputText is the "control" for ImGui.

I hope this helps!

Also notice I don't use ScintillaGL (based on fairly old Scintilla version) but more like the regular one with own backend for it.

@r-lyeh-archived
Copy link

woo, ty very much :D

@emoon
Copy link
Contributor Author

emoon commented Apr 11, 2016

np :)

@colesnicov
Copy link

Hello emoon. It is possible to use a multicolored text that right? What are the customization options - Can sam choose the color for the text. Me would have liked it used as a wysiwyg editor. Set the text color, size, etc .. Is it then possible to use in combination with ImGui. It should be as an addon? Code would be available? Link to git no longer valid. Thank you;-)

@emoon
Copy link
Contributor Author

emoon commented Jan 9, 2017

Yeah so I have been wanting to get around to make it available for people to use. Regarding multi-colored text yes that works. Scintilla has some built-in lexers for various programming languages and those are used to color the text and one can write own lexers as well.

I will make a a note to try to do it in the weekend.

@colesnicov
Copy link

Now that I find https://github.com/emoon/ProDBG/tree/f026d1d65e8161ddbf68d6e429465b396540c39b/src/prodbg/ui. It is 2 years old but at least the good out of it. Still, I tried to look at how to make it a standard addon/component for ImGui. That would be terrific. Of course this is also dependent on how it will be with the regulations, allowing longer text (framerate, memory etc.). But it probably will take a couple of days ...

Ala Google Translate.

@cesss
Copy link

cesss commented May 8, 2019

@r-lyeh I can point you to the relevant files :) Notice that the code still need a bunch of work but its actually working. Also while I do use Rust for ProDBG now a bunch of the "external" code will still be C++ as there is no point to rewrite that which I don't "own" directly or if it would be too much headache.

https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/sc_platform_bgfx.cpp
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/ui_sc_editor.cpp
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/ui_sc_editor.h
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/imgui_extra.inl

ScInputText is the "control" for ImGui.

I hope this helps!

Also notice I don't use ScintillaGL (based on fairly old Scintilla version) but more like the regular one with own backend for it.

I’d like to do a simple code editor with ImGui. Have you been using your ImGui Scintilla widget? You say it needs work, but, does it have bugs or missing functionality? Do you think I can use it for a simple code editor, or should I expect any issues?

Thanks!!

@bkaradzic
Copy link
Contributor

@cesss See: https://github.com/BalazsJako/ImGuiColorTextEdit#imguicolortextedit

@cesss
Copy link

cesss commented May 9, 2019

@cesss See: https://github.com/BalazsJako/ImGuiColorTextEdit#imguicolortextedit

Thanks a lot. I was confusing ImGuiColorTextEdit with the one in the Flix01 add-ons branch (which says "WIP, doesn't work"), but now I realize it's a different editor.

One limitation of ImGuiColorTextEdit is that it doesn't support UTF8. Opened an issue about that.

@cesss
Copy link

cesss commented Jun 9, 2019

@r-lyeh I can point you to the relevant files :) Notice that the code still need a bunch of work but its actually working. Also while I do use Rust for ProDBG now a bunch of the "external" code will still be C++ as there is no point to rewrite that which I don't "own" directly or if it would be too much headache.

https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/sc_platform_bgfx.cpp
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/ui_sc_editor.cpp
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/ui_sc_editor.h
https://github.com/emoon/ProDBG/blob/master/src/native/ui/bgfx/imgui_extra.inl

ScInputText is the "control" for ImGui.

I hope this helps!

Also notice I don't use ScintillaGL (based on fairly old Scintilla version) but more like the regular one with own backend for it.

Although I'm enjoying ImGuiColorTextEdit, I'd like to play a bit with your Scintilla port because of its additional functionality, but, man,... ProDBG is complicated :^) ...rendering is done as shaders and programs through bgfx and then somehow tied to ImGui (I'm talking about the July 2015 version that still had the ScInputText control).

I'll try to understand the structure and port it to an ecosystem I can understand (pure ImGui :-) but it's going to take more than an afternoon I'm afraid...

@ocornut
Copy link
Owner

ocornut commented Jun 9, 2019 via email

@bkaradzic
Copy link
Contributor

@cesss See this commit: bkaradzic/bgfx@1198f73

Also I highly suggest moving ImGuiColorTextEdit.

@cesss
Copy link

cesss commented Jun 9, 2019

I know, I know... in fact I opened an issue about adding UTF8 support to ImGuiColorTextEdit, and it has been kindly implemented by the author, and it works fine for me. I'll probably use it, it's just that I'd also like to port the ScInputText control from ProDBG/bgfx into some other APIs I could understand... I just found an older ImGui-based Scintilla renderer at your KiQBalls repository (it also uses bgfx but less heavily than ProDBG). Anyway, maybe it will be quicker to just write my own backend from scratch than trying to re-port your ports ;-)

@cesss
Copy link

cesss commented Jun 9, 2019

@cesss See this commit: bkaradzic/bgfx@1198f73

Also I highly suggest moving ImGuiColorTextEdit.

@bkaradzic I succeeded in building your ImGui Scintilla control just before its removal commit (it used standard ImGui rendering calls, so it was easier for me to build it than to build emoon's code). Did you ever had any demo that created a ImGuiScintilla control? I searched for it in your bgfx tree and didn't find any, both in old and new versions. I ask mainly because I don't know what's the proper way for creating it... do you allocate and delete it per-frame? (I suppose not!) Do you store a pointer somewhere? How is it connected to the usual ImGui loop?

@bkaradzic
Copy link
Contributor

See ImGuiScintilla header... There weren't any examples in bgfx since some other project used it. But everything you need is in .h file.

@emoon
Copy link
Contributor Author

emoon commented Jun 11, 2019

@cesss it's worth pointing out that rendering using shaders was done to make it as fast as possible. Also the code by now is pretty old and ProDBG doesn't is ImGui at all anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants