simple display (from: GUI library for D)

Cliff Hudson cliff.s.hudson at gmail.com
Fri Apr 8 18:40:47 PDT 2011


Why develop yet another GUI API with yet another interface?  While I
understand there are reasons to re-implement an API to use D idioms, there
are plenty of good APIs out there whose designs could be lifted.  Reminds me
of the quote: "The nice thing about standards is there are so many of them."

Have you considered patterning your API off an existing (preferably popular)
one?

- Cliff

On Fri, Apr 8, 2011 at 1:26 PM, Adam D. Ruppe <destructionator at gmail.com>wrote:

> We discussed this first in the GUI library thread, but since it
> meandered so much, I decided to split off into a new subject. Much
> of what I say here will be old to anyone who saw the previous thread.
> There's some new stuff nearer to the bottom though.
>
> I, with input from others, have started writing a little module
> for simple uses of a display. You can write to a bitmap, display it
> to a window, and handle events all in an easy way. The basics are
> cross platform, but you can use native function calls too.
>
> http://arsdnet.net/dcode/simpledisplay.d
>
> It's still very much in progress, but I think it's now at the point
> where the direction I'm taking it is clear.
>
> First, the simplest usage:
>
> ====
> import simpledisplay;
>
> void main() {
>        auto image = new Image(255, 255);
>
>        foreach(a; 0..255)
>        foreach(b; 0..255)
>                image.putPixel(a, b, Color(a, b, ((a + b) % 16) * 16));
>
>        image.display();
> }
> ===
>
> Compile: dmd test.d simpledisplay.d
>
>
> When run, it will pop up a window with a gradient thing with little
> bars through it. Press any key and the window closes, exiting the
> program.
>
> On Windows, it uses GDI functions. On other systems, it tries to
> use X Windows. Linux is the only one I've personally tested, but it
> should work on OSX and FreeBSD too (without changing the code).
>
>
> If you are making some data, then just want to display it, this
> works. But, what if you want some interactivity?
>
> Here's a simple HSL color picker:
> http://arsdnet.net/dcode/simpledisplay_test2.d
>
> Use these keys to pick your color: q/a change hue. s/w changes S.
> e/d changes L. Press ESC to exit. Your color in rgb is printed to
> stdout.
>
>
> Here's the relevant parts of the code:
>
> void main() {
>        auto image = new Image(255, 255);
>        auto win = new SimpleWindow(image);
>        win.eventLoop(0,
>                (dchar c) {
>                        writeln("Got a char event: ", c);
>
>                        if(c == 'q')
>                                h += 15;
>                        // ...snip...
>
>                        foreach(a; 0..255)
>                        foreach(b; 0..255)
>                                image.putPixel(a, b, fromHsl(h, s, l));
>
>                        win.image = image;
>                },
>                (int key) {
>                        writeln("Got a keydown event: ", key);
>                        if(key == KEY_ESCAPE) {
>                                auto color = fromHsl(h, s, l);
>                                writefln("%02x%02x%02x", color.r, color.g,
> color.b);
>                                win.close();
>                        }
>                });
> }
>
> First, we create an image. Then, a window based on that image. At
> line two, your window will show up on the screen, just like
> image.display() did above. But, here, instead of blocking, it
> moves on to a user specified event loop.
>
> SimpleWindow.eventLoop was inspired by std.concurrency.receive.
> The first parameter is a pulse timer amount (not yet implemented).
> If you set one, you'll get one of your delegates called at the
> requested interval. The idea there is to make animations or games
> easy to get started.
>
> After that comes a list of delegates. They are matched to different
> events by their signature. (dchar c) {} means a key was pressed,
> and it passes you the character corresponding to that key.
>
> (int c) {} is almost certain to change, but right now it matches
> to key press events, and passes the platform-specific keycode. I'm
> planning to put symbolic constants in with the same name across
> platform to make that easier to use, but the values themselves are
> likely to be platform-specific.
>
>
>
> When we get a key event here, the image is redrawn with a new
> color. win.image = image tells it you want the image redrawn with
> the new image. It's a blunt instrument, but a simple and fairly
> effective one.
>
>
>
> The advantage of this approach is you can just have fun with
> those pixels and handle keys, all right there inside main() - no
> need to do subclasses just for a simple program. At the same time,
> you can move those event handlers around easily enough, or even
> change them at runtime, simply by using named delegates and assignment.
>
> I plan to add more event possibilities so you can actually
> make this do some good work for you. Ultimately, they'll also
> be an (XEvent) {} and (HWND, LPARAM, WPARAM) event for when what
> I provide isn't good enough, so you can always build more off it.
> It's meant to be simple, but not horribly limiting.
>
>
> ======
>
>
> Since last time I posted, I've reorganized the code inside
> simpledisplay.d quite a bit. Instead of version Windows vs version
> linux, it's now Windows and X11, reflecting the fact that X is
> available on many operating systems. (Including Windows, actually,
> but meh).
>
> The Color struct is now rgba, but it doesn't use a. I like the
> suggestion to template on different color spaces, but haven't gotten
> around to that yet.
>
> Next, Image and SimpleWindow are done pretty differently than before.
> Now, the platform specific parts are put into a separate mixin
> template: NativeImageImplementation!() and NativeSimpleWindowImpl...().
> The public methods forward to those.
>
> The reason for this is three fold:
>
> a) It makes the public code a lot easier on the eyes. It was getting
> into spaghetti version territory for a bit there... now it's nice
> and clean.
>
> b) The implementations can now be moved to their own modules. I haven't
> simply because a single file is easier to distribute and play with,
> but the final thing probably should split it up, and now it can.
>
> c) It should be more obvious when something isn't implemented for an
> operating system, while keeping the public ddoc all in one place.
> versions
>
>
> Before, Image was simply a byte array in a single format, meaning
> to get to the native OS format for blitting, it had to be copied. Now,
> the actual format is hidden inside impl. I'll add operator overloads
> or structs (I really like Nick's idea of a fast vs cropped access
> point) to hide it.
>
> In the mean time though, the putPixel function forwards to the OS
> implementation, which writes right to the image format expected there.
>
> It's still not ultimately efficient, but it's better than copying
> it twice every time we make a change.
>
> I still like the idea of a set binary format being available so
> we can save as a file, but that will be made a conversion function
> instead of the default use. Actually, probably some kind of forward
> range. Then the file save functions can accept those ranges and
> translate them into .bmp or .png files as it streams in. (probably
> image.byScanLine would be pretty useful for this!)
>
> My HSL -> RGB converter is also in simpledisplay.d. It's actually
> less than 500 lines, excluding the bindings pasted in at the bottom.
> Not too bad.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20110408/a5399888/attachment-0001.html>


More information about the Digitalmars-d mailing list