goblinfactory / konsole

Home of the simple console library consisting of ProgressBar, Window, Form, Draw & MockConsole (C# console progress bar with support for single or multithreaded progress updates) Window is a 100%-ish console compatible window, supporting all normal console writing to a windowed section of the screen, supporting scrolling and clipping of console output.
718 stars 62 forks source link

Ability to close boxes. #85

Open Johannestegner opened 3 years ago

Johannestegner commented 3 years ago

It would be quite nice to be able to remove a box from the render view. Say, you want to use the box as some type of alert, but when the user have confirmed, it "closes" the box.

This would basically be worthwile to add on the IConsole/IWindow interface (or a new IClosable maybe?), and could be either a dispose thing or a Close() method. I might create a PR for this if it falls within the scope of the library, so let me know!

goblinfactory commented 3 years ago

Hi Johannes sorry for slow reply, I've been on a long non-tech sabbatical, (2 months) mostly without laptop, ... gettting back to home office tomorrow and I'll take a look at your message and reply soon.

To properly do a a windowed console popup, without blocking background threads runs against the design principles behind the library; specifically that the current windows work and function in-place relative div's in html. and wont in parallel with any other thread that writes to the console.

for example e.g. your thread... creates a snall 40 x 5 window called winCompress, and inside that window has a progress bar and some text, that pushes the current console cursor bottom down 6 lines allowing your main thread (or any thread)to continue to write to the System.Console ...oblivious to the fact there's a window that's being written to by thread Foo. If you want to indicate a process has completed, then simply call winCompress.Clear(); winCompress.WriteLine("finished compressing images"); Opening a specific window at location x,y with width and height, doing something and then "closing" that window, would require that you

a) read the buffer behind where you're about to open the window b) block any threads from writing to the window that is being overlapped, or update the konsole windowing library to detect overlaps during writing and not write to the overlapped area.

This would require double buffers, one for actual writes, and one for display writes. This is beyond the scope of the current library.

you can already call myWindow.Clear() which would "clear" any opened window with the currently set fore/background colour.

Lastly;

I need to make some significant breaking changes to Konsole in upcoming versions to support scrolling, and keyboard event handling, and dialogs would need to be worked into that change.

i've already started with some of that work, you can see there's a new base "control" that has been introduced in the beta 7 branch, and that has suspendLayout and resumeLayout methods, that are not in current v6.

The purpose of suspendLayout is to allow for me to create a powerful set of themeable controls that work with the new highspeedwriter, allowing me to fix the missing scrolling functionality in OSX/Nix. (long story)

basically, v7, v8 are going to be totally new beasts and will have dialog like behaviors, but there's a lot of work for me to do to make that happen. No shortcuts that I can push into V6. So V6 api and functionality is pretty much frozen, apart from any bugfixes.

It's possible I've misunderstood what you mean by "close box" but the above are my thoughts. Happy to keep discussing further.

regards, Alan

Johannestegner commented 3 years ago

Hi there!

Thank you for the response, and totally understandable with vacation. It's open source, you shouldn't be available 24/7! :)

When it comes to the issue, I think that I have just not got the Clear() command to work as I expected it to. I will keep on trying and if I understand it right, and get it working, I'll close this issue! Looking forward to V7 release! And will try to jump in and help out when/where I can :)

goblinfactory commented 3 years ago

Clear will clear printed contents of the window, but not clear the window itself if it has a border. In V6 if if you want to totally hide the window frame, like some type of modal that's now closing, you could do that using 2 windows somethink like the following (pseudo code, so please excuse me if this is quite a bit off, but you should get the gist )

  var eraser = new Window(10, 10, 40, 5, ...);
  var (left, right) = eraser.SplitLeftRight("debits", "credits");
  ... do some work
  // now hide modal, call eraser, because eraser is the modal's parent.
  eraser.Clear()

The reason for the extra eraser window is because otherwise the "parent" of that window is the main console itself, and when you Clear() that, it will clear the whole window, and not just the dialog you just opened.

In later Konsole release I will provide a simple blocking and non blocking modals that will make that easier to do, and still be threadsafe.

Be aware that the issue with any floating window is that there is no "hidden line" removal logic, i.e. if box 1 is at absolute position 10, 10 and some other thread is writing to the main console, that threads console writes will happily write over the floating window.

That is something i will address in later releases.

The design philosophy for early konsole releases was to have each thread allocated very unique window areas that never overlap and the floating window is an artifact that is used to deliver that, it's not meant as a key first class citizen.

The philosophy is to quickly break a screen into a few windows, and then have them run normal C# code that writes to a window that is oblivious, to avoid having to write seperate server/client console apps when testing libraries and launching them manually or automated, ...this way you can spin up multiple services, and test lots of complex code with a single console application, and see the output cleanly.

Since then Konsole has been used for a lot of applications, games etc. later releases are aimed at making Konsole a complete cross platform rapid prototyping library.

cheers, Alan

mmm, just thinking, idiomatically the code above could simply be written as

  var modal = new Window(10, 10, 40, 5, ...);
  var (left, right) =modal.SplitLeftRight("debits", "credits");
  ... do some work
  // now hide modal
  modal.Clear()

this works because using SplitLeftRight returns 2 new windows with borders that are both children of the borderless floating window created in the var modal line.

Konsole Ver 7 alpha now allows you to pass in a theme to a window. New child windows inherit the theme of the parent. You will have an issue with V6 if you create a floating window with a different background color, because Clear() will empty the window ..well, actually FILL the floating window with the windows fore and back colors. V7 alpha allows you to create a modal with the parent window, and then override the theme when creating child windows, which you couldnt (currently cannot do in V6).

V6 may need an additional window to clear using the real parents colors, and then a theme window that fills that window so that the splitLeftRight will have the correct colors for the dialog.

Does that make sense?

If this is important to do, let me know and I'll create a working spike / gist to demo how to do that if you need it. regards,

Alan

Johannestegner commented 3 years ago

Awesome! That will most likely do exactly what I need. Luckily, all of this type of windows that I will need in this application are during "pause" in the rest of the application (i.e., after validation but before run etc), so I will have no issues with other threads overwriting.

All makes sense and I think what you wrote will be more than enough to get me going!

Thank you very much for the help :)

goblinfactory commented 3 years ago

Ah! great!...glad to be able to help...

Are you using the latest alpha v7 release, it's actually quite stable? There are a lot of overloads for window creation and colouring (theming) I've not written documentation yet, because It's a really massive change. A

Johannestegner commented 3 years ago

@goblinfactory currently on the v6 branch, but I did take a look at the new features in v7 and it looks very promising! :) I'll try upgrade the current project to v7 and see how it fares! :)

goblinfactory commented 3 years ago

Is your project open so that I could look at how you're using Konsole? That would be very helpful for me in determining which features to work on, and also what examples and documentation to write to help users of the library use it idiomatically (as designed) and get the most from the library :D

Johannestegner commented 3 years ago

Sadly not this one. But since finding Konsole, I have been considered using it for a few other projects that I have, which are more open. Will gladly let you know when I got something to show :)

I do love using and building CLI applications, so this will likely give me much fun during the evenings ;D

goblinfactory commented 3 years ago

ah! Understood. Great to hear you want to use it in your own projects and other new ideas. Cheers, Alan