Jump to page: 1 213  
Page
Thread overview
simple display (from: GUI library for D)
Apr 08, 2011
Adam D. Ruppe
Apr 08, 2011
bearophile
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
bearophile
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
bearophile
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
bearophile
Apr 10, 2011
Adam D. Ruppe
Apr 10, 2011
Cliff Hudson
Apr 10, 2011
spir
Apr 10, 2011
spir
Apr 10, 2011
spir
Apr 09, 2011
spir
Apr 09, 2011
Michel Fortin
Apr 10, 2011
Jacob Carlborg
Apr 08, 2011
Andrej Mitrovic
Apr 09, 2011
Adam D. Ruppe
Apr 08, 2011
dsimcha
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
Michel Fortin
Apr 09, 2011
Andrej Mitrovic
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
Michel Fortin
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
Matthias Pleh
Apr 09, 2011
Michel Fortin
Apr 09, 2011
Matthias Pleh
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
Daniel Gibson
Apr 09, 2011
Adam D. Ruppe
Apr 09, 2011
spir
Apr 09, 2011
Cliff Hudson
Apr 10, 2011
KennyTM~
Apr 11, 2011
Adam D. Ruppe
Apr 11, 2011
KennyTM~
Apr 11, 2011
spir
[OT] Spaces/tabs (Was: simple display (from: GUI library for D))
Apr 11, 2011
Nick Sabalausky
Apr 11, 2011
Daniel Gibson
Apr 11, 2011
bearophile
Apr 11, 2011
Jonathan M Davis
Apr 11, 2011
Daniel Gibson
Apr 11, 2011
Jonathan M Davis
Apr 11, 2011
Kagamin
Apr 11, 2011
Jonathan M Davis
Apr 11, 2011
Daniel Gibson
Apr 11, 2011
Jonathan M Davis
Apr 11, 2011
Kagamin
Apr 12, 2011
Daniel Gibson
Apr 11, 2011
Kagamin
Re: [OT] Spaces/tabs (Was: simple display (from: GUI library for
Apr 11, 2011
Kagamin
Apr 11, 2011
Nick Sabalausky
Re: dmd2-2.052 is only for i386, while you are running amd64 (or dmd2 on FreeBSD)
Apr 11, 2011
Ruben
Apr 11, 2011
Nick Sabalausky
Apr 12, 2011
Jacob Carlborg
Apr 12, 2011
spir
Apr 11, 2011
spir
Re: [OT] Spaces/tabs (Was: simple display (from: GUI library for
Apr 11, 2011
Kagamin
Apr 11, 2011
spir
Jun 03, 2011
Walter Bright
Jun 03, 2011
Adam D. Ruppe
Jun 04, 2011
Jeff Nowakowski
Apr 11, 2011
bearophile
Apr 11, 2011
spir
Apr 13, 2011
Bruno Medeiros
Apr 11, 2011
Adam D. Ruppe
Apr 11, 2011
spir
Apr 11, 2011
Andrej Mitrovic
Apr 11, 2011
Nick Sabalausky
Apr 11, 2011
Jérôme M. Berger
Apr 11, 2011
David Gileadi
Apr 12, 2011
Daniel Gibson
Apr 12, 2011
Andrej Mitrovic
Re: [OT] Spaces/tabs (Was: simple display (from: GUI library for
Apr 12, 2011
Kagamin
Apr 13, 2011
Bruno Medeiros
Apr 12, 2011
Jérôme M. Berger
Jun 03, 2011
Walter Bright
Jun 03, 2011
Daniel Gibson
Jun 03, 2011
Timon Gehr
Jun 04, 2011
Stewart Gordon
Jun 04, 2011
Walter Bright
Jun 03, 2011
Adam Richardson
Jun 03, 2011
Walter Bright
Apr 11, 2011
Jacob Carlborg
Apr 11, 2011
KennyTM~
Apr 11, 2011
Jacob Carlborg
Apr 11, 2011
Michel Fortin
Apr 11, 2011
teo
Apr 11, 2011
Adam D. Ruppe
Apr 12, 2011
teo
Apr 11, 2011
Nick Sabalausky
Apr 12, 2011
Jérôme M. Berger
Re: [OT] Spaces/tabs (Was: simple display (from: GUI library for D))
Apr 12, 2011
Jonathan M Davis
Apr 12, 2011
Daniel Gibson
Apr 12, 2011
Jonathan M Davis
Apr 12, 2011
Nick Sabalausky
Apr 12, 2011
Jonathan M Davis
Apr 12, 2011
Cliff Hudson
Apr 12, 2011
Nick Sabalausky
Jun 03, 2011
Bruno Medeiros
Jun 03, 2011
Jonathan M Davis
Jun 03, 2011
Andrej Mitrovic
Apr 12, 2011
Andrej Mitrovic
Apr 12, 2011
spir
Apr 12, 2011
Jérôme M. Berger
Apr 12, 2011
Nick Sabalausky
Apr 13, 2011
Jérôme M. Berger
Apr 13, 2011
Nick Sabalausky
Apr 13, 2011
Jérôme M. Berger
Apr 14, 2011
spir
Apr 14, 2011
Jérôme M. Berger
Apr 14, 2011
spir
Apr 12, 2011
Jacob Carlborg
Apr 13, 2011
Jonathan M Davis
Apr 12, 2011
spir
Apr 12, 2011
spir
Apr 12, 2011
Jérôme M. Berger
Apr 12, 2011
Nick Sabalausky
Apr 12, 2011
Adam D. Ruppe
Apr 12, 2011
Kagamin
Apr 12, 2011
spir
Apr 13, 2011
Bruno Medeiros
Jun 03, 2011
Jonathan M Davis
Jun 04, 2011
Stewart Gordon
April 08, 2011
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.
April 08, 2011
Adam D. Ruppe:

> 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.

I'd like something like this in Phobos, or if this is not possible, a cabal-install-like command away. I sometimes use Python PyGame or Processing.


> 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();
> }

Instead of:
image.putPixel(a, b, Color(a, b, ((a + b) % 16) * 16));
I suggest something simpler like:
image[a, b] = std.typecons.tuple(a, b, ((a + b) % 16) * 16);

Instead of:
image.display();
I suggest something like this, to swap the two image buffers:
image.flip();

Plus maybe some image.event(); reader with callbacks...

Bye,
bearophile
April 08, 2011
simpledisplay.d - line 267:
int lol, wtf;

lol, wtf? :p

Btw, an exception will be thrown on unhandled key events, e.g. just hit CTRL: object.Exception@.\simpledisplay.d(299): GetMessage failed

Not a good thing if you use shortcut keys to move windows around.
April 08, 2011
== Quote from Adam D. Ruppe (destructionator@gmail.com)'s article
> 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.

Can it render text?  If so, I'll probably port Plot2kill to it if it becomes part of Phobos at some point.  It would be kind of cool to have minimal Plot2kill functionality with zero third-party dependencies.  If it's so basic that it can't even do text rendering, then I have my doubts about whether there are very many use cases for something so simple.
April 09, 2011
bearophile wrote:
> I'd like something like this in Phobos

Me too. It's still pretty far from good enough right now, but that's where I want ultimately want it.

My only concern is I don't want Phobos to depend on Xlib unless
the module is actually imported. I don't think it will be a problem,
but if it means a hello world won't run on a text only machine, that
won't be ok.

> I suggest something simpler like:

Yeah, moving to opIndex is something I plan to do. But, I don't
really like using a tuple for this - a regular struct makes it
a little clearer what's going on, and can be made more efficient.
(In the other thread, Nick suggested making it a simple uint
internally, using property functions to emulate other outside
faces. I like that.)

A struct might also have accessors with different color types too.

> I suggest something like this, to swap the two image buffers

That's not really what you're doing there - display actually pops up a new window and waits for the user to close it.

> Plus maybe some image.event(); reader with callbacks...

What would it do?
April 09, 2011
dsimcha wrote:
> Can it render text?

Not yet, but it's on the list. Anything that's reasonably easy
in both Windows API and Xlib should be supported here. At the least,
text, lines, rectangles - all the basics.
April 09, 2011
Andrej Mitrovic:
> lol, wtf? :p

My brilliant variable names! It reflects my feelings toward parts of the bmp format I forgot about when first writing it. I didn't account for the padding at first, then said "wtf" and added it... then "lol"'ed at myself for not doing it right the first time.

You should have saw the original C version though:

if(hbmp == NULL)
     goto fuck;

:)

> Btw, an exception will be thrown on unhandled key events, e.g. just hit CTRL:

That's weird, I've never seen GetMessage fail... ever. I'll have to try it in real Windows later (I'm on linux / Wine right now).
April 09, 2011
Adam D. Ruppe:

> My only concern is I don't want Phobos to depend on Xlib unless
> the module is actually imported. I don't think it will be a problem,
> but if it means a hello world won't run on a text only machine, that
> won't be ok.

I agree.


> But, I don't
> really like using a tuple for this - a regular struct makes it
> a little clearer what's going on, and can be made more efficient.

OK. (But for this module I think usage simplicity is more important than raw speed. Users that need more performance or more features are going to use something else and better. The idea here is to keep simple the things that are simple).


> (In the other thread, Nick suggested making it a simple uint internally, using property functions to emulate other outside faces. I like that.)

OK.


> > I suggest something like this, to swap the two image buffers
> 
> That's not really what you're doing there - display actually pops up a new window and waits for the user to close it.

Indeed, I was suggesting to open the window at the top of the program, and at the bottom of the program to swap the two buffers and show the drawn one.


> > Plus maybe some image.event(); reader with callbacks...
> 
> What would it do?

Read the events, like window closing, key pressed, mouse movements, etc. Take a look at Processing API, for ideas.

There are many situations where a simple built-in graphics is useful. Beside the example of Processing (that has anti-aliasing), there are many programs/small games that need just some 2D graphics:
http://rosettacode.org/wiki/Animate_a_pendulum

Bye,
bearophile
April 09, 2011
bearophile wrote:
> OK. (But for this module I think usage simplicity is more important than raw speed.

The struct is at least equal in simplicity:

image[x, y] = Color(r, g, b);

vs

image[x, y] = tuple(r, g, b);

> Indeed, I was suggesting to open the window at the top of the program, and at the bottom of the program to swap the two buffers and show the drawn one.

Sure, that's what happens in my second example.

Right now it uses "window.image = newImage;" to flip it but I think I want to change that.

> Read the events, like window closing, key pressed, mouse movements, etc. Take a look at Processing API, for ideas.

Yes, my window object does this too. See the example here: http://arsdnet.net/dcode/simpledisplay_test2.d

win.eventLoop() does it.

> http://rosettacode.org/wiki/Animate_a_pendulum

Heh, I think D will be winning that by Monday!
April 09, 2011
Adam D. Ruppe:

> The struct is at least equal in simplicity:
> 
> image[x, y] = Color(r, g, b);
> 
> vs
> 
> image[x, y] = tuple(r, g, b);

A tuple is simpler, there is no new name to remember and use, new type to define, and 3-tuples come out of other generic computations, like zip:

foreach (col; zip(reds, greens, blues))
    image[x, y] = col;

Generally D programmers probably need to learn to use tuples a bit more seriously and often :-)


> Yes, my window object does this too. See the example here: http://arsdnet.net/dcode/simpledisplay_test2.d
> 
> win.eventLoop() does it.

I see. But those lambdas are a bit too much large put there. I suggest true named function moved elsewhere.

Some other notes to your code:
- generic imports like stdio are probably better before the most specific ones (this is done in well written Python code);
- Inside the (dchar c) {} a switch seems better.
- In Wrapped struct why are you using a checkLimits() instead of an invariant()?


> > http://rosettacode.org/wiki/Animate_a_pendulum
> 
> Heh, I think D will be winning that by Monday!

Good, but Rosettacode site isn't a competition :-)

Bye,
bearophile
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11