Trying Something New

| | Comments (36)

Since my brain hurts lately from the massive amount of UI work I’ve been doing, I’ve not had much time to post anything terribly interesting to REALbasic users. Usually, by the time I get the chance to blog, I’m coded-out and have no real interest in talking about RB more. Also, I feel like I’ve covered “everything.” I hate running out of things to say about as much as Thomas hates hearing about my day-to-day life. ;-)

So I’m going to try something new and see how it goes.

I’m wondering what you want to know. Any nagging questions about how something works? What it’s like to work for RS? Things like that. Keep in mind that I won’t be answering anything like “when will we see feature X or bug fix Y”, or “Since you’re the spawn of Satan, how do babies taste?” So I reserve the right to not answer questions. :-P But you’re welcome to ask me what my personal opinion is on things (gods know I’m fine with spewing my opinion all over the internet), or technical questions you have.

I’ll start with an opinion just so this post doesn’t totally suck.

My thoughts on the behavior of the resize widget on the Mac. Wow it's a weird beasts! You see, on Windows, the only time you ever have a resize widget on the window is when you also have a status bar on the window. Since the status bar is a client control that stretches the entire width of the window, you never have a problem with overlap (unless your UI is already broken). However, on the Mac, that widget is in the non-client area and shows up whenever the window can be resized. So if you have a control that goes all the way to the edge of the window (which is common on floating windows), then you have dueling UI.

One example of this is a ListBox (though an EditField would have the same issue). If the bottom-right corner of the listbox is in the area of the resize widget and it has a vertical or horizontal scrollbar, then you have a problem. The tacks for the scrollbar interfere with the thumb tack for the window.

The way the Mac solves this is by bumping up the scrollbar on the listbox by the resize widget size. But I find this to be an unsatisfying solution to the problem — it requires a client-area control (the listbox) to know about the non-client area control (the resize widget) and modify its visual behavior accordingly. That just doesn’t sit right with my idea of design because it’s not something that’s uniform. Yes, it solves the issue for the scrollbar interfering with the widget, but it doesn’t solve the problem in a general way. What if I have a button in that corner (granted, that’s broken UI again)? How does the button modify itself to not interfere? It can’t. Technically, neither can an EditField with no scrollbar since that’s a valid area for text to go.

I rather like the way Windows handled the issue by making the widget a client-area control as part of the status bar. It neatly solves the issue since you won’t have two client-area controls overlapping. However, that poses a different problem — how do you tell the difference between a resizable and a non-resizable window. What’s more, how do people with disabilities resize the window? Let’s face it, 1-2 pixels is easy to miss when you have a physical handicap. I like the fact that the Mac has the resize widget for any window which can be resized — I think that’s a good visual cue and solves the handicap issue. However, there’s probably a better way to solve the issue altogether. Maybe, use a different frame border entirely to designate a resizable window. If the border is visually distinguishable, then it solves the issue of wondering whether you can resize it or not. As for the problem of clickable area, Microsoft solved this nicely — they have a contextual menu which can be gotten to via the keyboard which lets you interactively resize the window using only the keyboard. Hit Alt+Space to go to the app’s menu, go to size. Now press the arrow key corresponding to the edge you wish to resize. The cursor moves to that edge, and you can use the arrow keys to resize. Hit enter when you’re done. Is it the best solution? Nope! But it’s a solution. Another possible idea would be to have the resize widget be on the exterior part of the border instead of the interior. Then you can't have dueling UI since it's on not within the client's space. Or, reserve the space as non-client so that you can't put any client controls in that area (like what happens with toolbars on the Mac).

So yeah, to make a long story longer, I was a bit surprised when I learned of how the Mac behavior is supposed to be with regards to this issue. It wasn't the solution I was expecting, but hey, it's the proper solution for the platform and it works well enough in most cases. Just some food for thought, that's all.

36 Comments

Yeah, the Mac behavior is interesting. And it certainly is a pain to have to adjust client controls to compensate for the frame design.

However, the interesting thing is that with Cocoa (or at least Interface Builder) all of this is taken care of "for-free". A listbox automatically compensates for a resize widget in a seemingly magic way. Thus, it's not really an issue for most other Mac OS X programmers.

Try it for yourself: go to Interface Builder, create a new Window, drag a listbox on, disable horizontal scrollbar, drag the listbox to the bottom right. Then slowly resize the window taller and shorter. You'll notice that the listbox's vertical scroll bar compensates *exactly*, pixel-for-pixel, to where it needs to be to avoid conflicts with the resize widget. Not like REALbasic where it's a 16-pixel cut out or nothing.

Interesting stuff, and it makes me wonder who's doing it--is Interface Builder setting a magic property, or does NSListView automatically compensate, or something else? Of course, the problem with all of Cocoa's "magic" behavior is that there's no way to understand exactly how it all works without being a NeXT programmer since version 1.0. It's built on Objective C, for heaven's sake--which I actually love as a language, except for all of the hackish stuff it has from 1985.

So anyway, I actually dislike the Windows method even more. Yes, borders are a good way to resize, and it makes it much easier on us programmers, but I think that unbordered windows (à la Mac OS X) look much, much better and take up less screen space. Besides, as you mentioned, unskilled users have a heck of a time grabbing a non-obvious 2px wide space.

Oh, and status bars are evil. :-) But seriously, I don't like them. At all. Including REALbasic's, although it's a necessary evil for now since it would take substantial effort to replace it.

I think the ListBox (and EditField) behavior comes for free on OS X. But someone had to do the work, and to me, it's a layering issue with the design. Client controls should never have to care about non-client controls. The two are in different layers of the UI and so they shouldn't have that tight of a coupling.

And I don't like the Win32 way of not know whether you have a resizable window or not, but the borders really don't bother me. The lack of borders on the Mac are visually difficult for me since there's no "stopping point" to them. You can butt two windows next to one another, and aside from a slight rounding, there's no way to know where one ends and the next begins. :-)

Oh, and my question. This is a *great* idea. I could ask questions until I'm blue in the face. :-)

Here's one: how does the ListBox work? I believe it's a custom control, so is it essentially graphics-based with custom drawing for *everything* (like, you handle the mousedowns on headers and redraw them, etc)? Is the fundamental codebase more or less shared cross platform or completely different? How is this magic "listbox code" stored--a compiled plugin, or part of the framework? And are there plans to use NSTableView for Cocoa instead of the custom control?

Since I'm not a compiler designer, I'm also wondering how exactly the "framework" is generated. For example, the listbox code. Is it just C++ code that is compiled into a library, which is then linked into by the main RB compiler?

And to what degree do you think REALbasic should provide for platform-specific capability? For example, the ability to create an Automator-compatible application on Mac OS X, or a tray item on Windows? Do you think that it's ultimately a desirable goal or a distraction from REALbasic's purpose?

Finally, I hear that NTLM implementation is a bumpy road, so if there's anything I can help with, drop me a line.

"You can butt two windows next to one another, and aside from a slight rounding, there’s no way to know where one ends and the next begins."

Well, to each his own of course; I personally love that appearance. And the shadows are excellent, in my opinion. (The last Vista screenshots I saw showed shadows, but I didn't like them nearly as much.)

@Adam -- #1: The listbox is a custom control written in C++. Historically, it was custom because the listbox for Classic wasn't nearly powerful enough and everyone wrote their own. However, now that modern platforms are all the rage, it'd make sense to use a native control. But we have so many custom features tied into the listbox that it's simply impossible to just get rid of it.

The functionality for it is 100% x-platform. We handle all of the drawing and all of the behaviors for it. It's compiled in the framework like most things in REALbasic (so it's not a plugin). As for future plans, I can't discuss those. ;-) But I can say that I'd personally love to see a platform native listbox. While x-platform consistency is nice, I think a native control is more important. So I'd love to see something that's reasonably consistent and native on all platforms.

@Adam -- #2: The framework is C++ code that's utilized by your applications. The easiest way to think about it is as a static library that your code calls into. That's not 100% accurate, but it's close enough. It's not truly linked into your application in the traditional sense, but it is linked into your application since it's part of the final executable (at least, for non-bundled link formats).

@Adam -- #3: I think REALbasic should allow the user to do anything on any supported platform. So if REALbasic doesn't provide the functionality directly, it should at least provide the tools to be able to do it yourself. For example, the TrayItem class was essentially impossible to do from pure RB code. So it got built-in. But some things don't need to be built-in because you can do them yourself (like the status bar). That's not to say things you can do yourself will never get built-in. It's just a prioritization thing.

So, for example, I would say COM support is more important than a tree-view control since you can use COM to implement a tree-view.

Ultimately, it'd be nice for RB to be everything to everyone. But until then, I think it's best for RB to be a solid tool that lets people accomplish what they need to accomplish, even if they have to do the leg-work to make it happen.

Hi Aaron,
As you might expect, my question relates to something I need to do for Reality Check. When I build a symbol table for a REALbasic application, I'll need to include symbols which are in the REALbasic frameworks (i.e., all classes, interfaces, modules, methods, properties, etc.). At present, I'm building an XML document by hand containing all of the objects, modules, methods, etc., in the frameworks. Not only is this tedious, but subject to breaking every time the frameworks are updated. If I could directly access symbol information from the frameworks, my symbol table would always be correct. Is there any way to do this?

@Scott -- why do you need the symbol table from the framework? Would introspection solve the issue for you instead?

Can you recommend a good resource (book, web site etc..) for becoming familiar with VS C++ Express? Of course, RB is my favorite development tool but it never hurts to learn more.

I have a low-to-moderate understanding of C++ and worked (struggled) partially through one of the MFC books several years ago.

I've used VB6 a lot, but none(!) at all since about RB 5 ! :-)

@Russ -- I've never used a book to learn an IDE, so I'm not of much help with VS IDE. But for learning C++, the bible is by Bjarne Stroustrup, so reading that will teach you much of what you need to know about C++. If you're interested in learning the Win32 APIs (not MFC, but the true-blue OS APIs), then there's a good book by Charles Petzold for that.

Here's a question I just posted to the NUG; I figure there's no one better to ask than you.

In Windows, you can right-click a file and choose "Print". This instructs the responsible application to print the file. Apparently there is some shell parameter that is sent.

How can I simulate this within REALbasic? Basically, I have a file, and I want to instruct a certain program (in this case, I know the program) to print it.

@Adam -- not certain I understand the question. Are you wondering how you can set your app to be the one to print certain files from the shell menu? Or are you wondering how to instruct another app (not in your control) to print a file?

Sure, introspection would help, but this doesn't solve the problem because: (1) I'd have to instantiate every class in the framework to get the information about their methods, properties, etc., which would be very slow plus require my code to know about every class that's available in advance, (2) REALbasic itself has no built-in introspection, (3)Mars explicitly warned me not to use the available open-source introspection code because it will most likely break with future versions of REALbasic, and (4) even if introspection were available, I still would have no information about the modules and interfaces in the frameworks because introspection would most likely work only on classes.

I am wanting to create a tool that uses the RB3DSpace to simulate a plane that has various cubes resting on the plane.

I have reviewed Joe S. document on 3D but it is blank for how to create 3D Geometry on the fly...and there just seems to be a dearth of complete information on how to dynamically create 3D geometry that is not loaded in from a shape file. All of the examples that come with RB simply don't include some program that draws a collection of spheres, cubes and pyraminds in a 3D space.

Can you give me an succienct overview of how to do this. I have been through the documentation and seem to not "get" it in determining what class to start with to even draw a simple cube with one vertices at (0,0,0) in the 3D space.

Thank you...

@Scott -- so it sounds like you need to do this on the fly or something (otherwise speed wouldn't be an issue)? Otherwise you could use introspection to generate that XML for you for a particular release, and then add modules by hand. Not ideal, but better than doing it all by hand.

I guess I wouldn't hold out for that sort of thing to happen since it would bloat the framework out by a fair amount for very little gain (to the average customer).

I would suppose that there would be some sort of agreement you could come to as part of the developer support program for getting the symbol stubs or something, perhaps. But I'm not even certain of the viability of that option.

@Cordell -- Unfortunately, you've stepped into one of those areas of RB where I am woefully uneducated. I wish I could help you out, but I wouldn't even know where to begin.

That might be a good question to direct to the NUG or the forums as there are a lot of very bright experts there who are usually pretty good at helping people out with this sort of thing.

I wish I could be of more help, sorry!

@Aaron - how funny, you gave me a great answer even though I gave you a rather pathetic question. Garbage in, Gold out. Sweet.

I have one of Petzolds books, but I believe all the examples are in C. "Programming Windows", 5th edition. Probably a collector's item now. Unfortunately, I never made many inroads into it.

@Aaron, the latter; and Brian Rathbone answered my question on the NUG. Thanks anyways, and sorry for the ambiguous wording.

@Russ -- The Petzold book is golden; you may want to consider re-looking into it if you're curious about Win32 programming.

Have you messed with .NET much? I spent a few hours messing with it last night, and I like it for the most part. However, I can't find anything great on using asynchronous sockets in it... I'm guessing I might have to create a thread subclass that just polls continously then fires events when appropriate? Or is WinSock a better API for this? And what kinda mess is calling unmanaged code from managed code?

Here's the problem with this discussion of client and non-client areas, and it illustrates why programmers are (generally, I mean no personal insult here) terrible at UI design: The user doesn't know, or care, which part of the windows are which, nor should they have to care. Apple had this in mind when they designed their way of doing things, while Microsoft just did it the way that was easiest to code.

Anyway, that's one of the Golden Rules of interface design: the UI should never be constrained by the underlying data structures.

I don't know if it's something to post here (or maybe RBLibrary) but the Office Automation stuff needs some clarification. The standard response always seems to be "get a VBA book it's close enough." Done and done! Yet I'm still finding it a frustrating and time consuming venture.

In an ideal world the Word stuff would have the same framework as Asher's PDF classes. That way we could just use an interface between the two. Along with the fact that Asher's stuff is so nicely designed. (Which brings up the question 'Why hasn't Geoff hired him yet?').

~joe

@James -- that would be true if client vs non-client was only part of the underlying data structures and not a conceptual part of the UI itself. It's every bit as important to have non-client area as it is to have UI layering. Your golden rule is rather silly (no offense intended); of course the UI has to be constrained by the underlying data structures. Otherwise you'd have the ability to draw your own content into another window, as an example. I think what you are after is that the designers need to communicate with engineers to ensure that everyone's goals are being met. The engineers need to make a safe, stable system that's easy to maintain. The designers need to make things look pretty and be functional. Sometimes these goals are at odds, and other times they're not.

You are right that the *user* doesn't have to care. But the UI designer had better care (just like they had better care about layering of controls).

@Joe -- I've played with .NET plenty, but not done any hard core networking with it (RB is just too easy to do it in, so I have no reason to bother with other APIs).

But the typical way of working with synchronous sockets is to spawn of threads (or fork processes, in the olden days) so that the app remains responsive.

Take us on a tour of Pragmatic Programmer with an RB perspective. :-)

Do you have any advice for an intended CS major early on in college?

@DeanG -- oddly enough, I've never read that book, though I hear it's excellent. If you've got something specific in mind, I may be able to take you up on it. ;-)

@Jeff -- Sure! Have fun. :-) Don't get stressed over things like debugging apps, it's all a part of learning. You're *going* to spend countless hours, but they'll be worth it. Much of the time, the information you learn is rather dated in terms of application. However, the theory behind it rarely is dated, and it usually very good to learn. So soak up anything you can, don't be afraid to strike out on your own and learn things yourself, but above all, enjoy it.

Or were you looking for more practical advice? ;-)

Nothing particular in mind. It should mesh well with new IDE features tailored to team RB development.

Nope, that is good. :)

Here is a suggestion for a future article that I would find very useful: A CVS / SVN primer. I would be really interested in a quick overview on how to use a course control system.

Aaron, I'd rather parse symbol information straight from the frameworks on the fly. Introspection would go a long way for that even if it didn't solve all of the problems. My second choice would be get full information on framework symbols from RS in a format that I could automatically process to create a symbol table. The only down side would be that I'd never be fully up to date to the latest REALbasic release. The worst option would be having to enter all the data by hand from the REALbasic documentation; I've done some of that already, but it was too time-consuming and as the documentation changed, it was too difficult to find the new stuff to add in. Bottom line: This has to be automated and preferably on the fly so the symbol information is correct for all versions of REALbasic.

Would it be practical to parse the HTML documentation files for the language reference?

Hi Mars! That would be possible, I suppose, but the processing to determine the relevant symbol information on each page is far from trivial. In addition, one would have to thread through all of the hypertext links to find the data types of properties, method parameters, the inheritance hierarchy, etc.
Of course, there is also the issue of whether or not the documentation is up to date with the latest release.

Aaron...I subscribe to the beta "bug" list and at times I seem a variety of emails that are submitted detailing a bug.

As a person who works on RealBasic...what is your perspective on the validity and quality of the bug submissions.

What are the 2-3 things that would be at the top of the list when submitting a "bug" report that enable RB to really correct a bug...not a 'supposed' bug.

@Cordell -- The best practices for bug reporting list is something I posted in a few places before. Such as here:

http://support.realsoftware.com/listarchives/realbasic-nug/2004-02/msg02002.html

But I have an additional one for beta testers, which is to test *early* instead of late. When you send in a flood of bug reports or start a design discussion during the alpha cycle or early beta cycle, that's a great time. When you don't start getting serious about testing until the fc's, it's not such a great time.

Leave a comment

Disclaimer

I'm currently an employee of REAL Software. My blog is mine. The opinions represented in this blog are mine as well and may not represent my employer's opinions. All original material is copyrighted and property of the author.

REALbasic® is a registered trademark of REAL Software, Inc. REAL SQL Server™ and Lingua™ are pending trademarks of REAL Software, Inc. All rights reserved.