Hi,
one of my biggest problems with Smalltalk remains to be UI design. I often see stuff like WinAmps Skin, which seems to be very non-standard UI, and I have no clue whatsoever how to do this in Dolphin. Could anybody hint me how to create a Skin/UI like the ones on this website: http://www.3dftp.com/skins/skins.htm How would one do that with Dolphin? Günther |
Günther,
> I often see stuff like WinAmps Skin, which seems to be very non-standard > UI, and I have no clue whatsoever how to do this in Dolphin. > > Could anybody hint me how to create a Skin/UI like the ones on this > website: > > http://www.3dftp.com/skins/skins.htm There are two aspects to this. One is how to create UIs with odd shapes and appearance, and the other is how to create skinnable UIs. There is no real connection between the two -- leaning how to do one won't help with doing the other. For creating weird-looking UIs, there are three main tools/techniques: clipping regions, transparency, and custom widgets. Clipping regions are used to tell Windows that a window isn't rectangular. You create an irregularly shaped region, and then tell Windows to clip your window to those bounds. Clipping regions are exposed in Dolphin as instances of Region. Unfortunately Dolphin doesn't include methods, by default, to create non-rectangular regions (such as ellipses or arbitrary shapes defined by a path), nor does it expose the interfaces needed to set the clipping region of a Shell view (afaik, this stuff is only applicable to top-level shells). I'll add a bit of code that exposes some of the simpler stuff at the end of this. See MSDN for the rest of the available API. With appended code loaded (and I take /no/ responsibility for the results ;-) you can try something like: chb := ClassBrowserShell show. r1 := Region ellipse: (0@0 corner: 500@300). r2 := Region ellipse: (0@200 corner: 300@500). r := r1 union: r2. chb view setRegion: r redraw: true. to get a Very Odd CHB. Transparency is used to get similar effects, or perhaps even more complicated ones. I have no idea which of the two techniques is recommended -- from limited experimenting I've generally found that clipping regions work better if they do what you want at all. Udo Schneider's 'US LayeredView' package from: http://udos.swiki.net/3 (when I last looked) exposed the interfaces necessary to use transparency. You tell a ShellView (again it has to be a top-level shell) that it is "layered" using the #isLayered: method from that package, and then you can choose a color that will be made transparent. E.g. chb := ClassBrowserShell show. (chb view) isLayered: true; colorKey: Color white. to get another Very Odd CHB. Once you've got a odd-shaped window, you either won't be able to see the menu bar and title bar, or you may not have asked Windows to create them at all. In that case you have to arrange for how the user can move your window around. One way is to set a handler for the #onLeftButtonPressed: event that starts a mouse-drag of the window. To do that you (in the event handler) create a MouseTracker, something like: (MouseTracker forPresenter: self startingAt: 0@0) origin: aMouseEvent position; startTracking: self. which will then call the #{start/continue/cancel/end}TrackingAt: methods of your presenter. #startTrackingAt: can just answer its argument. #endTrackingAt: and #cancelTrackingAt: can just be ignored. The other one (which actually moves the window to follow the mouse) can look something like: continueTrackingAt: newPoint from: oldPoint "private -- called by the MouseTracker as we allow it to drag our window around. Move the window by the indicated amount" | oldPos newPos | newPoint = oldPoint ifTrue: [^ newPoint]. oldPos := self view position. newPos := oldPos + newPoint - oldPoint. self view position: newPos. ^ oldPoint. "because we've shifted the reference point" Of course, you'll have to ensure that the user has ways to close the window, etc, too. With that set up, you next need to make your window look "nice" (or slimy, dripping, and disgusting -- or whatever). To do that, the easiest thing is to design an image in a paint program, and use that as your main window. You can paint over that (using normal Windows graphics calls) to implement any flashing lights, or whatever, that your imagination has invented (and your natural good taste hasn't vetoed ;-). Lastly, you'll want some buttons (probably very strangely shaped), and perhaps other widgets, for the user to interact with. You can implement those directly, by interpreting mouse movements, etc, yourself, and drawing/updating your own graphics. Alternatively, and probably easier in the long run, you can use custom widgets, such as "owner draw" buttons and so on. Dolphin doesn't come with such things in the box, but it's not too difficult to add them (depending on how ambitious you want to be). There are several goodies that contain owner-draw widgets of one sort or another, which may be useful directly or may help you to work out how to create your own (as I'd guess you will want to in the long run). One example is the 'WalicXe - Widgets' package from: http://www.walicxe.com/pages/descargas.htm You'll probably want to place the buttons, etc, at fixed positions (so they are in the "right" place in the picture you're using as background). To do that use a nil #layoutManager. Or you may want to create a custom layout manager that -- say -- moves the buttons around at random... That should be enough to get started with creating some truly vile user interfaces. Good luck! ;-) Skinning is a whole different question. I can't cover that in any sort of detail because there are /far/ too may options. The essence of it is that an application is skinnable if, and only if, the application's author (or the creator of the underlying UI toolkit) has built the ability to be skinnable in from the start. It isn't something that you can just add afterwards. Being skinnable requires two things. One is that the GUI architecture has a clean separation between how the widgets /look/, and what they /mean/. Without that there is no hope of having any kind of pluggable widgetry. On that front, you are in luck -- Dolphin has precisely that separation. In fact Dolphin's Views are a very flexible and powerful variant on the "skin" idea. As an example, I think that the screenshots at: http://www.3dftp.com/skins/skins.htm look pretty lame. They have outrageously flamboyant decoration, but when you look at them, the actual lists of files, and so on, are just plain old-fashioned text. Nothing fancy at all. You should be able to say that the file lists are arranged in a circle, or that the text should seem to creep over the apparently 3-d surface as your scroll through lists. None of that is possible unless you can "plug in" your own special implementation of, say, a list without affecting the operation of the bits of the application that "know about" that list. In Dolphin, that means providing your own View that may look very different from the standard ListView, but is close enough in behaviour that the ListPresenter doesn't care which is actually in use. Of course, the fancier the plug-in widget has to look, the less chance there is that Windows, Dolphin, or the community will have implemented it. So you'll have to write your own (unless you are satisfied with the "lame" look). The other half of being skinnable requires that there is some way of specifying what an application looks like (and maybe some aspects of its behaviour too) that is /external/ to the application. According to taste (and according to how much effort you think it's worth) there is a large range of options here. At one extreme the "external specification" might be no more than a list of .GIF files, colours, fonts, button positions, and so on -- the application would read that file and replace any/all of its own bitmaps, colours, fonts, etc, with those specified. I haven't looked at 3dftp really, but I'd guess that that's about what it does. A "skin" is then that file plus any associated GIFs, etc, probably all packaged up together in a ZIP file or something like that. You could implement that as easily in Dolphin as in any other system, but it would be /you/ who did it. Notice that this isn't really making much use of the "deep" plugability of Dolphin Views -- all it is doing is allowing the user to change (some of) the configuration of the existing application. At the other extreme, the skin specification is so complex and powerful that it's really a whole new programming language, and it allows skin-writers to specify any aspect of the appearance of the application, and maybe even to re-write it's entire behaviour. (As I understand it, this is the approach underlying the Mozzilla toolkit -- which will undoubtedly create security problems for years to come). In Dolphin terms, this amounts to replacing the 'V' and most of the 'P' of MVP with the skinning stuff. What level of skinnability you want is up to you. The sky's the limit, but is also a lot of work to reach... One approach that /might/ work would be intermediate between the above. If the "skin" package (zipfile or whatever) was allowed to contain replacement View instances -- stored in STB format -- then your application could use those in preference to the configured ones. (You might need to modify the current View creation code a bit to make this work). You could go still further and allow the skin file to contain new View /classes/ (as binary package files) too. That would be some extra work, but I think it's probably feasible /if/ you want a powerful skinning ability in the first place, /and/ are willing to restrict it to people who can create them in Dolphin. -- chris ======== Some Region-related additional methods =========== !GDILibrary methodsFor! createEllipticRgnIndirect: aRECT "The CreateRectRgnIndirect function creates an elliptcal region. HRGN CreateEllipticRgnIndirect( CONST RECT *lprc // pointer to the rectangle );" <stdcall: handle CreateEllipticRgnIndirect RECT* > #CUadded. ^self invalidCall! ! !GDILibrary categoriesFor: #createEllipticRgnIndirect:!public!win32 functions-region! ! !Region class methodsFor! ellipse: aRectangle "Answer an elliptical region defined by aRectangle" #CUadded. ^self fromOwnedHandle: (GDILibrary default createEllipticRgnIndirect: aRectangle asParameter)! ! !Region class categoriesFor: #ellipse:!instance creation!public! ! !View methodsFor! setRegion: aRegion redraw: aBool "Attaches a copy of the given region to this window." | hRgn | #CUadded. aRegion isNil ifTrue: [^ UserLibrary default setWindowRgn: self asParameter hRgn: hRgn bRedraw: aBool]. "we have to pass a copy of the region 'cos Windows takes ownership of the handle" hRgn := GDILibrary default createRectRgnIndirect: RECT new. GDILibrary default combineRgn: hRgn hrgnSrc1: aRegion asParameter hrgnSrc2: nil fnCombineMode: RGN_COPY. [^ UserLibrary default setWindowRgn: self asParameter hRgn: hRgn bRedraw: aBool] ifCurtailed: [GDILibrary default deleteObject: hRgn].! ! !View categoriesFor: #setRegion:redraw:!clipping regions!public! ! !UserLibrary methodsFor! setWindowRgn: hdc hRgn: hRgn bRedraw: aBool "The SetWindowRgn function attaches a region to a window. NB: After ths has been called, Window's has taken ownership of the region handle and will delete it as necessary. int SetWindowRgn( HWND hWnd, // handle to window HRGN hRgn, // handle to region BOOL bRedraw // window redraw option );" <stdcall: sword SetWindowRgn handle handle bool> #CUadded. ^self invalidCall! ! !UserLibrary categoriesFor: #setWindowRgn:hRgn:bRedraw:!public!win32 functions-clipping!win32 functions-region! ! |
Chris,
thanks once again for your help. I already found out that the UI stuff is a huge beast to deal with. So far I haven't even been able to fully understand how "regular" views are implemented in Dolphin. The other day I got myself a Petzold so it'd teach me things from the start. Also quite difficult still as I don't speak C, yet. I'll try to learn it by constructing my own View using the External Interfacing documentation from OA. I'm doing ok with Smalltalk sofar, no bigger problems there, my main concern still remains about UIs. Once I'm beyound the above steps, I'll have another look at this book http://www.amazon.com/exec/obidos/tg/detail/-/1556222491/qid=1122905495/sr=8-1/ref=pd_bbs_1/104-2305678-7675140?v=glance&s=books&n=507846 and hope this gives me some more ideas. Günther |
In reply to this post by Chris Uppal-3
Chris Uppal wrote:
> Günther, > > [ .. snip lots of useful stuff .. ] Hi Chris, What an excellent reply. Answers many things I've always wanted to ask but never got round to. Cheers! Ted |
In reply to this post by Günther Schmidt
Günther,
> I already found out that the UI stuff is a huge beast to deal with. Probably because you are aiming for ambitious targets (/not/ a criticism!). > So > far I haven't even been able to fully understand how "regular" views are > implemented in Dolphin. It definitely helps a lot to understand how Window's GUI programming works. The design (more the internal design than the external API) of View and it's more Windows-centric subclasses very much reflects how Windows works. BTW, are you reasonably happy using vanilla Dolphin MVP ? I mean could you knock up a fairly simple UI using "normal" tabs, buttons, lists, etc, reasonably easily ? If not then you may be trying to run before you can walk (as they say). > The other day I got myself a Petzold so it'd teach me things from the > start. Also quite difficult still as I don't speak C, yet. Not speaking C will definitely make it hard work. Fortunately, I don't think you need to speak C very well in order to get value from Petzold. I have a copy of his book too, and find it very helpful, but I've never yet tried to read any of his complete code examples. The discussions leading up to the complete code are good enough on their own (IMO). What you really need (I think) is to be able to see, and work with, the correspondence between C function and structure definitions, and the corresponding code in Dolphin. -- chris |
Chris,
> Not speaking C will definitely make it hard work. Fortunately, I don't think > you need to speak C very well in order to get value from Petzold. I have a > copy of his book too, and find it very helpful, but I've never yet tried to > read any of his complete code examples. The discussions leading up to the > complete code are good enough on their own (IMO). What you really need (I > think) is to be able to see, and work with, the correspondence between C > function and structure definitions, and the corresponding code in Dolphin. > > -- chris > > books on C. Boy am I glad that I merely have to understand it to some extent and not to actually program in C. It must be hell. There is somebody, I think on Dolphinharbor.org, who seems to be playing with Windows in Dolphin quite a lot, translucent Windows and such. I'll try to find that again too, but I think my best bet is to study Petzold, and try to implement that in Dolphin from Scratch. Günther |
In reply to this post by Chris Uppal-3
Chris,
> It definitely helps a lot to understand how Window's GUI programming works. > The design (more the internal design than the external API) of View and it's > more Windows-centric subclasses very much reflects how Windows works. > > BTW, are you reasonably happy using vanilla Dolphin MVP ? I mean could you > knock up a fairly simple UI using "normal" tabs, buttons, lists, etc, > reasonably easily ? If not then you may be trying to run before you can walk > (as they say). Quite so, well I just don't know about the happy business. I mean creating an App with standard widgets in Dolphin poses no problem, but going beyond that does. I understand how to *use* MVP, but so far haven't been able to understand the inner workings of Dolphins Views yet. As I said it's quite a beast. Günther |
Free forum by Nabble | Edit this page |