bearophile wrote: > The length=150 too is better to be set as immutable.
Yeah, I made that change after copy/pasting the code into my newsgroup post. win, painter, angle, and angular velocity were the only things left mutable in the end. > The delegate inside eventLoop doesn't need the (). I put it there for consistency with other events. While there are no other handlers in this example, there can be, and all the other ones take arguments. > Color(255, 255, 255) ==> Color.white > painter.clearAll(Color.white) > auto win = new SimpleWindow(512, 512, "Pendulum"); Yeah, those are reasonable. > win.eventLoop(10, {...}) does this semantics work with more than > one window too? I believe so, yes, but I haven't tried it and wouldn't mind if it didn't. If you need to use multiple windows at the same time, it'd probably be better to use DFL, DWT, GTK, Qt, etc. etc. > drawRectangle => rectangle or even "box" Heh, I used to call it box in my DOS programs. But, the functions it forwards to are called Rectangle() and XDrawRectangle(), so I want to be consistent with them so it's not a surprise to someone already familiar with with the other APIs. The reason I went with drawShape instead of just Shape is that functions are verbs, so generally, I like their names to be verbs too. There's exceptions, of course, but I don't these fit. > outline => pen? Pens do more than just color. I guess the real question is how complex should it be able to get? In the underlying APIs, you can make a pen with a color, a width, and a style (solid, dashed, etc). Since they both can do it, I think I will add it. (Some more advanced APIs can even do things like gradient pens. I hope the image manipulation functions we write will eventually be able to do this too, but since plain old X can't, it won't happen for the display painter.) Perhaps: painter.pen = Pen(Color(r, g, b), 1, Pen.Style.solid); (Or maybe new Pen()... have to think about that.) And offer an overload for the simple case where you only care about color. (or keep the current fillColor property.) Then, of course, something similar for Brush, which is used to fill the background. But, here, the idea was to keep it simple, so I went with just color. I guess that might be too simple. > This is not so nice... I'm sympathetic, but I don't agree losing the struct would be good. Even if the struct proves to be unnecessary (which it might be - I think you can hold on to a window HDC as long as you like, but it's not something I see often so I think it's discouraged), I'd still keep it. Having an automatic constructor and destructor available gives some flexibility on the implementation side without inconveniencing the user beyond a single function. For example, the implicit double buffering done here. You don't have to think about flipping it. It just works. Better yet, the implementation can disable it at will. BitBlt is slow over Remote Desktop on Windows, making double buffering laggy. But, you, the user, don't really need to know that, since it wasn't your problem in the first place. The ScreenPainter can make it's own decision about it. > Reading keyboard chars, and mouse clicks & movements is very > useful. For that, you can pass other handlers to eventLoop. I still intend to define a few more you can use. > Another useful thing is to plot a matrix of rgb or int or ubyte > in grey shades, to speed up some basic usage. In PyGame/Numpy > there is surfarray for this. Sounds like what you'd use the Image class for, so I think we're good on that too. ==== A note: since I posted last, I changed my mind on something, and bearophile, I rather doubt you'll like it... Before, it was drawRectangle(int x1, int y2, int width, int height); Now, it is drawRectangle(Point upperLeft, Size size); So, at the usage, you now need to put in some more parenthesis and say what you mean: painter.drawRectangle(Point(0, 0), Size(win.width, win.height)); Why did I do this? Well, consider the following: drawRectangle(int x1, int y1, int x2, int y2); (This is, in fact, the signature in Windows GDI, whereas Xlib user width/height.) The types there are no different than the above, but meaning has changed. I'd be ok with saying "RTFM" to avoid having to use the structs. But, RTFM doesn't let you overload it, whereas the types do. Now, it can offer both drawRectangle(Point upperLeft, Size size); *and* drawRectangle(Point upperLeft, Point lowerRight); I'm sure you were thinking about named arguments for a moment there about width/height vs x2/y2. I did too. But, named arguments don't really exist in D (you can do them via library magic but not without) so it's moot, and I don't believe named arguments would offer the overloading possibilities, which I like. It can save some math while being quite natural. The Point struct also makes drawPolygon look a lot better, so it's of general use.