Table of Contents
Be Developer Classified are an opportunity for Be developers to tell each other about projects they're working on, are thinking about working on, or would like to work on. Here's your chance to request assistance on a project, or make your talents available for other projects.
BeOS Programmers Available BeOS developers for hire. We specialize in games and real time development. For more information, see our web page:
Be Programming Positions Available/Wanted Page If you're looking to be hired as a Be programmer *or* to hire a Be programmer, please contact me. I'm in the process of setting up a web page dedicated to such ads. The ad should be in the same format as the Be newsletter classifieds. The page will initially be attached to my own pages, but may move later to one of the news sites. Pat Gratton
Gobe releases new Gobe Productive beta Gobe Software has released a new beta of Gobe Productive, their document creation system. The beta is available for download through their web site:
Be Team at PC EXPO 1998
Be will be demonstrating the BeOS in our brand new exhibit booth. Come check it out! Where:
For more information see: http://www.pcexpo.com/
BE ENGINEERING INSIGHTS: The Tracker Is Your Friend By Scott Barta When I came aboard at Be in January to begin my headlong dive into the guts of NetPositive, I quickly learned that one of the features most often requested was a hierarchical bookmark menu, along with better bookmark management than what PR2 offered (which was essentially nothing). Based on experience with other browsers and platforms, my usual response was to stare at my shoes and mumble something about how I should someday implement a bookmark manager ˆ la Netscape or Internet Explorer. Most people's response was, "No, use the Tracker instead. It's the Be way of doing things." For the Release 3 release, at Pavel's prodding, I changed the bookmark data format to use the attribute defined by the x.vnd-Be.bookmark file type for storing the bookmark URL, and made sure that bookmarks were given this type when saved. This opened up NetPositive bookmarks for editing in Tracker windows by allowing users to display and edit the URL attribute of bookmarks in the Tracker list view of NetPositive's Bookmarks directory. In retrospect, I should probably have modified the code to use the Title bookmark attribute as well, instead of relying on the filename for the bookmark's title, as this would have prevented a few weird quirks in bookmark naming. In my post-Release 3 work (which you'll see in the R4 release of NetPositive, or very likely sooner in an interim release after Release 3.1), I've extended the relationship between NetPositive and the Tracker for handling bookmarks -- I use NodeMonitors to keep informed of changes to the Bookmarks directory so I can update my Bookmarks menu on the fly. I also allow the user to create hierarchies in the Bookmarks menu by creating subdirectories in the Bookmarks directory. Having done this work, I'm now a complete convert to using the Tracker to manage your data. I've found that combining file directories with custom attributes, Tracker management of those files, and NodeMonitors to keep you up to date on changes, is a powerful way to manage lists of information with minimal work on your part, while providing users with a lot of power over that data through an already familiar interface. I plan to extend NetPositive to manage site passwords, cookies, and other information in this way, without the need to come up with a new user interface and storage format for each type of information. So where should you use this sort of mechanism in your applications? Anywhere you need user-maintained lists of information; examples include bookmarks, recent or favorite documents (you could maintain a directory of symlinks to do this), shortcuts, macros, plug-ins, etc. It's probably best suited to applications where the list of information is relatively short (i.e., dozens of items); it's not be the best way to maintain a user spelling dictionary. How is it done? Follow these steps:
"So where's some code I can copy and paste?" you ask. I've written a handy FolderWatcher class that does most of these tasks for you. Due to its length (close to 1,000 lines of code), it's not included here, but you can get it from our sample code archives at ftp://ftp.be.com/pub/samples/storage_kit/FolderWatcher.zip The sample code includes the FolderWatcher class and a simple application that creates some folders in your home directory, adds a few bookmark files to them, and then spits out any messages it gets back from the FolderWatcher. It's a command line program and has no GUI, so the application itself isn't very useful, but it should show you how to use the FolderWatcher. To use this class, create a separate FolderWatcher instantiation for each folder that you wish to watch. In the constructor, pass in a BEntry to the directory to be observed, the file type of the file of interest, the signature of the preferred application for the files, and the BLooper to be notified when something interesting happens. If you want, the FolderWatcher can create the folder if it doesn't already exist. Once the FolderWatcher is created, call I've found that for simple cases like I'm assuming here, a BMessage is a good way to represent attribute data, since BMessages can contain the type/name/value triplets that attributes use. Therefore, I use BMessages for passing attributes back and forth in the FolderWatcher interface. Note, however, that FolderWatcher will become extremely inefficient if you store large amounts of attribute data in these files. To create new files in the folder, you can do it yourself
or call If you don't need to watch the folder anymore, delete the FolderWatcher instance; it will clean up silently (without sending further messages back to you). All other communication with the FolderWatcher occurs as
messages sent back to your
As it is written, the class doesn't recurse into
subdirectories, so that might be a good way to modify it
if you want to enhance its capabilities. (In case you're
wondering, this class was written after I implemented
hierarchical bookmarks in NetPositive; I'm going to go
back and shoehorn in a modified version of this class
later.) Another suggestion would be to modify As a final warning, the code hasn't been stringently tested, so caveat emptor. If you find problems, though, let me know and I'll fix them and update the sample code archive. Happy coding!
Be's success depends on the creation of a solid BeOS applications market and online commerce model. We strive to give our developers the best engineering resources and support, so they can develop the best applications for the BeOS. Now we will also provide them with the tools they need to successfully market their product. To this end, Be has recently acquired StarCode, Inc. of Redwood City, CA. StarCode's products, BeDepot, Software Valet 1.5 for Intel and PPC, and PackageBuilder will be integrated into the line of Be products and services. This integration will allow Be to provide developers and end-users with software management solutions and with an online commerce system for selling and buying BeOS applications over the web. Developers will have the tools to market their BeOS applications efficiently and conveniently, and users will have the means to easily and quickly access a wide range of BeOS products. StarCode and Be are working together to ensure a smooth transition and integration. Over time, Be will incorporate these products and services into our developer program. Software Valet is an installer/deinstaller technology for the Beos, and will provide developers and users with a consistent reliable means of installing applications, updates, drivers, and other good stuff. Package Builder provides tools for creating downloadable and installable/deinstallable applications and updates. BeDepot is an online commerce system for selling applications over the web. Tune in to our web site, as more information will progressively be available, or write to info@be.com.
DEVELOPERS' WORKSHOP: BeOS Programming Basics: Part 3 "Developers' Workshop" is a new weekly feature that provides answers to our developers' questions. Each week, a Be technical support or documentation professional will choose a question (or two) sent in by an actual developer and provide an answer. We've created a new section on our web site. Please send us your Newsletter topic suggestions by visiting the web site at: http://www.be.com/developers/suggestion_box.html.
Last time, we created a simple application with a menu bar that the user could play with. We also poked a toe into the waters of the BMessage class, but I skimmed over the details, leaving you high and dry until this week's exciting episode. If you haven't read parts 1 and 2 of this series, you really ought to do so: http://www.be.com/aboutbe/benewsletter/volume_II/Issue7.html#Workshop http://www.be.com/aboutbe/benewsletter/volume_II/Issue13.html#Workshop As promised, this week we're going to delve a little more deeply into messaging on the BeOS. In particular, we're going to add support for multiple windows to the MenuWorld application from last time, using messages to keep track of how many windows are open, and to ensure that no two untitled windows get the same name. To accomplish this magnificent feat of software engineering, we're going to extend the HelloApp class to serve as a registry for our windows. Whenever a new window is opened within the MessageWorld application, that window tells the HelloApp object that a new window has been opened. HelloApp, in return, lets the new window know what its name should be. As always, you might want to have your Web browser aimed at the Be Book so you can read the more detailed descriptions of the functions discussed here; we won't be covering anything in complete detail, but just taking a look at how things might be done, to give you a place to start. We begin with the MenuWorld application from last time. Before getting into messaging, let's take a look at a minor change to the HelloWindow constructor. It was pointed out on the BeDevTalk mailing list that MenuWorld was assuming that the menu bar was always going to be 20 pixels tall, which is not a safe assumption to make. Additionally, there are a couple of minor changes needed so the window can register itself with the application object. So the HelloWindow constructor now does the following: HelloWindow::HelloWindow(BRect frame) : BWindow(frame, "Untitled ", B_TITLED_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE) { BRect r; BMenu *menu; BMenuItem *item; // Add the menu bar r = Bounds(); menubar = new BMenuBar(r, "menu_bar"); AddChild(menubar); // Add File menu to menu bar /* same code as last time */ // Add Options menu to menu bar /* same code as last time */ // Add the drawing view r.top = menubar->Bounds().bottom+1; AddChild(helloview = new HelloView(r)); Register(true); Show(); } The menu bar is now added using the full bounds rectangle of
the window. This is safe to do because, as described on page
467 of the Be Developer's Guide, the We've also added a call to the new Note also that we've changed the title of the HelloWindow to "Untitled ". This isn't important, but it seemed like a good idea. There are three basic classes in the BeOS messaging system. These are:
When a message is sent, the application server delivers it
to a BHandler by calling that BHandler's The BView class is derived from BHandler; a view can receive and respond to messages. That's how user commands are received -- messages indicating mouse and keyboard activity are delivered to the view, which interprets and acts upon them. If you flip through the Be Book for a while, you'll notice
that BLooper is derived from BHandler. BLooper is a handy
class that establishes a thread that runs a message loop
repeatedly until the loop's A BApplication object is instantiated, then you call its
Likewise, a BWindow loops, handling incoming messages in its
So now we know that Let's add the registry code to the HelloApp class. We'll
need to add the class HelloApp : public BApplication { public: HelloApp(); virtual void MessageReceived(BMessage *message); private: int32 window_count; int32 next_untitled_number; }; The window_count variable keep tracks of how many windows our application has open (there's actually a BApplication function that does this, but we're going to keep track of it ourselves for educational purposes). next_untitled_number tracks the number to use when naming a new untitled window (such as "Untitled 42"). This number always increases, so we'll never see the same number twice. The HelloApp constructor needs to be updated to initialize these variables: HelloApp::HelloApp() : BApplication(APP_SIGNATURE) { BRect windowRect; windowRect.Set(50,50,349,399); window_count = 0; // No windows yet next_untitled_number = 1; // Next window is "Untitled 1" new HelloWindow(windowRect); } When the application is first run, there aren't any open windows, and the first window is called "Untitled 1". The window registry -- the mechanism by which the application counts and names windows -- is handled entirely by accepting and responding to two application-defined messages: const uint32 WINDOW_REGISTRY_ADD = 'WRad'; const uint32 WINDOW_REGISTRY_SUB = 'WRsb';
The HelloApp needs to be able to reply to
WINDOW_REGISTRY_ADD messages so that it can tell the window
what number to use when giving itself a new "Untitled" name.
So we need to define a command code for this reply message:
Now let's look at HelloApp's void HelloApp::MessageReceived(BMessage *message) { switch(message->what) { The function begins by looking at the BMessage's command
code. This 32-bit value is located in the public "what"
variable in the BMessage class, and specifies what type of
message has been received. If it's a case WINDOW_REGISTRY_ADD: { bool need_id = false; if (message->FindBool("need_id", &need_id) == B_OK) { if (need_id) { BMessage reply(WINDOW_REGISTRY_ADDED); reply.AddInt32("new_window_number", next_untitled_number); message->SendReply(&reply); next_untitled_number++; } window_count++; } break; } Before handing the If need_id is false, a new BMessage, called reply, is
created, with the command code We then add a new field to the reply message by calling
Then the reply is sent by calling the received BMessage's
Finally, the next_untitled_number variable is incremented, so that the next new window's number will be one greater than the previous window's. The window count is then incremented (whether a reply was sent or not), since there's a new window registered. We always want to count up every new window, even if it's not untitled. case WINDOW_REGISTRY_SUB: window_count--; if (!window_count) { Quit(); } break; If the message is a default: BApplication::MessageReceived(message); break; } } All other messages are routed back to the inherited BApplication MessageReceived() function. Now let's look at the changes needed to the HelloWindow class: class HelloWindow : public BWindow { public: HelloWindow(BRect frame); ~HelloWindow(); virtual bool QuitRequested(); virtual void MessageReceived(BMessage *message); private: void Register(void); void Unregister(void); BMenuBar *menubar; HelloView *helloview; }; The updated HelloWindow class needs a customized destructor,
so that the window can be automatically unregistered
whenever it's closed. Two private functions are added as
well: The destructor is really simple -- it just calls the Unregister() function: HelloWindow::~HelloWindow() { Unregister(); } The The
void HelloWindow::Register(bool need_id) { BMessenger messenger(APP_SIGNATURE); BMessage message(WINDOW_REGISTRY_ADD); message.AddBool("need_id", need_id); messenger.SendMessage(&message, this); } The void HelloWindow::Unregister(void) { BMessenger messenger(APP_SIGNATURE); messenger.SendMessage(new BMessage(WINDOW_REGISTRY_SUB)); } HelloWindow's Here are the constants for the message codes we're adding support for: const uint32 MENU_FILE_NEW = 'MFnw'; const uint32 MENU_FILE_CLOSE = 'MFcl'; const uint32 MENU_FILE_QUIT = 'MFqu'; The code is as follows: void HelloWindow::MessageReceived(BMessage *message) { switch(message->what) { case WINDOW_REGISTRY_ADDED: { char s[22]; int32 id = 0; if (message->FindInt32("new_window_number", &id) == B_OK) { sprintf(s, "Untitled %ld", id); SetTitle(s); } } break; When a case MENU_FILE_NEW: { BRect r; r = Frame(); r.OffsetBy(20,20); new HelloWindow(r); } break; The File menu's New option creates a new HelloWindow, whose frame rectangle is the same as the current window's, but offset by 20 pixels down and to the left. This staggering effect helps keep the windows orderly on the screen (although in real life you want to be sure the windows don't eventually creep off the bottom or right edge of the screen!). case MENU_FILE_CLOSE: Quit(); break; The Close option simply calls the HelloWindow::Quit() function to close the window. Because the HelloWindow destructor calls Unregister(), the window will be unregistered from the application (thereby reducing the window count). case MENU_FILE_QUIT: be_app->PostMessage(B_QUIT_REQUESTED); break; The Quit option posts a B_QUIT_REQUESTED message to the application object. This causes the application to close all the windows and terminate itself. case MENU_OPT_HELLO: /* this is the same as last time */ break; default: BWindow::MessageReceived(message); break; } } The rest of the code in HelloWindow::MessageReceived() is unchanged since last time. Finally, because we don't want closing the window to
automatically quit the application, we rewrite the
bool HelloWindow::QuitRequested() { return true; } This has been a very brief overview of messaging on the
BeOS. Because messaging is so pervasive throughout the
entire operating system, we'll learn more about it as we go
on. But this will give you the background needed to follow
along as we continue to explore. Try adding code to insert
more data into the registration messages, or make the
Although this sample project's messages are mostly transmitted within the application, there's no reason you can't write two applications and send messages back and forth between them (try this -- just remember to use the appropriate signature when creating a BMessenger object for sending messages to the other application). You can download the source code for this week's project >from the Be FTP site: ftp://ftp.be.com/pub/samples/intro/messageworld.zip In about six weeks, we'll try making the HelloWindow class do something more useful than simply display a string in a window. We'll look at the BTextView class and start down the road toward turning our sample application into a text editor.
StarCodeLast week, we executed the closing documents to finalize Be's acquisition of StarCode. It is a great pleasure to welcome Carlin Wiegner and his team into Be. Their pioneering spirit and their achievements have been an inspiration and, in more ways than one, that's precisely why the deal got done. It shouldn't come as news for those (few) who read the original Be business plan that we believe in electronic distribution of software. A section of that plan explains how we'd create a dedicated Be BBS, knitting together the community of Be developers, Be customers, and the company itself. This was written in 1991, when you could buy a few phone lines, an inexpensive PC, and software from Mustang or Galacticom. With a Mac you needed a really nice product aptly called FirstClass, and you were in business. You had your own little Compuserve, your petit MoiOnLine. There were over 10,000 BBS in the country. The reference magazine for the BBS trade was Boardwatch -- still one of the best reads, nicely converted to the Internet under its erudite and opinionated editor-in-chief Jack Rickard http://www.boardwatch.com/. These BBS systems were, ahem, scalable. The largest one linked over 100 PCs via a Novell network -- very messy, but very inexpensive. McAfee, then reigning king of anti-virus software, used such a contraption for electronic delivery of its software; as a result, its IPO prospectus listed as a major risk the fact only one individual knew how to run the thing. So, we were going to build such an electronic community, alert our customers every week to new and improved application, utility, game, or even system software available. Developers would advertise their wares on our BBS. The weekly Newsletter would ask politely if we could deposit demo software and updates on their disk. The word "push" hadn't been invented yet. If customers liked the sampleware, they could call the developer, order with a credit card, and receive the software electronically or via snail mail. Not very sophisticated but, at the time, it was judged a little futuristic and risky. Customers might balk at the idea of having software loaded on their machines without having full control over the process. Cookies hadn't been invented either. Jump to 1996. Carlin works at Be as a summer intern and starts a company called StarCode, a site called BeDepot, and a product called Software Valet. BeDepot sells and delivers software over the Web. The Web is a still-evolving contraption, but a ubiquitous and inexpensive one. Software Valet sits in your BeOS system, where it downloads, installs, and registers software; it also notifies you of updates. StarCode practiced what we preached. Two more factors made StarCode attractive to Be: the people and the e-commerce infrastructure. With this in mind, and wanting to make life easy for customers and profitable for developers, the make vs. buy analysis was fairly straightforward. Carlin, his team, and their technology provide us with a better and faster way to build a BeOS software community and, therefore, the Be platform. Mere implementation details remain...which is a way to say we have much to do to realize the potential this reunion represents, but at least we are started on the right path.
1997 Be Newsletters | 1995 & 1996 Be Newsletters Copyright ©1998 Be, Inc. Be is a registered trademark, and BeOS, BeBox, BeWare, GeekPort, the Be logo and the BeOS logo are trademarks of Be, Inc. All other trademarks mentioned are the property of their respective owners. Comments about this site? Please write us at webmaster@be.com. |