Proceedings of the August Be Developer Conference



August 1997 BeDC

replicants (Extending Track)




PETER POTREBIC: My name is Peter Potrebic still, and I'm going to talk about replicants, which is a new technology in the Preview Release. And I'm one of the engineers at Be. So at the end I hopefully can answer some technical questions.



So replicants is a new technology for sharing objects between applications, and consider it a light-weight component architecture. We didn't try to duplicate open dock. Kind of our goal in replicant and a lot of what we do is to try to make things really simple.

You might only have some fraction of the functionality you would have with open dock, but hopefully you have a couple orders of magnitude easier time implementing that functionality. And that's our goal in a lot of areas in the BeOS, to make things very simple but yet powerful and something that can grow over time so that the developers grow along with us.

So what it is is it's basically taking our archiving abilities that are also new in DR9, where you can take an object in our system, like a window, with a bunch of views in it, you can archive that window, write that out to some permanent store, read that back in, and then rehydrate it back into its full glory. You get back the whole window.

So we took -- or you can take just a part of that window and do the same thing. So we took that along with our DLL capabilities, where you can dynamically load code and dynamically call entry points in that code, and we combined the two of those and came up with this replicant technology. There are really two parts of it. There is the objects that are replicants, and then there are container views.

And one of the things that we did is, we made our desktop a container view, and I'll give you a quick demo of that. So here's our desktop, and it's actually a container view, and I'm going to open up our apps folder, and we took a couple -- I initially took a couple little applications and turned them into replicants, the clock app as well as Pulse, and there is a little API in the BMenu, Showreplicants, which will show all the replicants that we have in our system. Has anyone here not seen replicants yet? (Show of hands) Just a couple people. I'll show it again because it's so much fun.



So what you can do now is you can grab any of these replicants and drag them and drop them onto a container view. So I can drag, and now these objects are living inside the tracker. You will notice that when I -- I'm going to quit those two applications, and they're going to disappear from the desk bar, but yet this clock is still functioning. I can reposition it, say, underneath the buttons. I can turn off one of the CPUs. If I go back to Pulse and launch it, you will see that one of the CPUs is turned off. If I turn it back on in the application, you will see that it turns on again in the desktop.

So this is one example of a container view. We actually have -- let me get rid of these guys, or at least the two buttons, because they're not as interesting. I'll leave the clock up here. Actually, this little area in the desk bar is also a container view, but it's not a container view that you can programmatically drop something in. It's just meant for programs to add things to it, and we have one program that does that, which isn't currently running, the mail server, so let me launch the mail server and hopefully it will work.

What the mail server does it sends the desk bar a little message which is a replicant, and that gets put inside the little status view, and now this is a piece of functionality that the mail daemon added, and something happens when I double click on it.

I guess this machine wasn't set up for mail. This would open my mail folder if I had properly installed mail. And it also, when you get new mail, the icon changes. And our intention is to extend that, make that functionality a little richer for -- I don't know if the status view has to grow to accommodate a few more things, things like that. But that is actually a little container view.

And the most interesting application that's a replicant is our web browser, NetPositive. I can grab its little hand, drag it out and drop it on the desktop. I can close NetPositive, it disappears from the desk bar, and now I have a web browser right here on my desktop, a web page. I can go to our home page, and I can go to the developer page. It's going out over the network. Maybe the network connection isn't working very well.

Anyway, I can go -- suppose I had a little stock quote page. I could bring up my stock quotes and have them on my desktop. Every time I booted up my machine, this window or this view, this web page, would appear on my desk top, and I would see my current portfolio.

I don't know why it's not finding it. It will time-out eventually.



So, now to get into the techie stuff, replicants. There are several classes in our APIs that are used to create this replicant facility. For the objects themselves that are replicants, the two interesting classes are BArchivable, which is a class that allows you to make your classes archivable, and all of the kit classes like in the interface kit, windows, views, controls, things like that, they descend from archivable, and they override the appropriate methods and I'll show you some sample code shortly. Whoops. Can't open. So it timed out that web download.

And then BDragger is the class that gives you that API, that little hand API that allows you to pick up a replicant out of the application and drop it onto a container view.

Container views are created by using the class called BShelf, and I'll show you some sample code there as well. And this architecture isn't really constrained to UI type functionally; you can use the same archivability and our DLLs to do things like send around some math engine or something like that. It doesn't necessarily have to be UI related, although that's where the initial work was focused. I kind of kept in mind, you know, non-UI related components.



So how do you make a replicant? Well, you use this BArchivable class. Oftentimes we use it just as a mix-in, unless it happens to be at the top of whatever class structure it is that you're working on, and if you're subclassing an existing class like a view or control that's already in our kits, well, it already descends from archivable.

And there is basically three main things you need to do in this archivable to do with this archivable class. There is an archive method that you need to override to define how you archive your object, and we use the BMessage class as a data container. If you were at the talk at one o'clock about messaging and scripting, it was mentioned that the BMessage class is often used as just a data container. So that's what we're using here for archiving.

You might be familiar in other systems where you would archive or flat an object. It is typical you just write it out into the stream of bytes, and on unarchive you have to read the stream of bytes in the same order in order to recreate your class, your object. Then you call Inherited and you have to make sure that you do things in the right order so that you don't get out of synch in this byte stream.

What we did is we decided to use BMessage as our data container, because it was a lot more expressive. You could add data under names that were descriptive. So when a view is archived, it adds the frame of itself into the BMessage under a descriptive name, and that name also has a type. So you have a lot more richer information, in terms of rather than just having a stream of bytes where you could look at that stream and you have no idea what that stream of bytes was.

And it also allows you to create an editor for an archived object that doesn't really know about the object, but it just lets you see this underlying BMessage and lets you maybe manipulate it, and you can change the frame of a view without even really creating the view. And this is what is going to be used in -- kind of the genesis of this archivability was with App Sketcher, where it did its own thing like this. So what we did was created it in the kits, and then App Sketcher uses archiving facilities.

Another thing you need to do is, there is a method called Instantiate, which is actually a static member function, and I'll show you that in a moment in more detail. And then there is a special constructor you define for whatever class you're dealing with that takes this data container as a argument, and that's how you recreate the object. You're given a data container, and you read data out of the message, and you set your object up.

Another step in creating a replicant is defining a MIME signature for the application or library that defines this class. And just like every application has a MIME signature, in the case of the clock application, you just take its MIME signature, and you need to put that piece of information in the right place in order to create a replicant, and then you associate one of these BDragger objects which gives you the user interface for a replicant.



So now I'll show you the sample code for this. So here's a class -- imagine we're dealing with this clock over here. So the view is called T clock, the subclass is view. So I want to -- here are those three functions that I just mentioned, the special constructor, the virtual archive method, and the static function Instantiate.

So I define those three methods, as well as my normal constructor for the view, where I give it the frame where I want the view to show up, and I have an integer because the clock can have several faces, and whether I want the second hand to be showing. You can turn on and off the second hand, and I forgot -- okay. You can turn on and off the second hand, so that's what this Boolean corresponds to.

So that's the header file basically for this view. One thing you need to do is you need to export these symbols so when you build the library, those symbols get exported, the key component of which is this Instantiate static member function. So you need to include these pragmas, export on and export reset.

Now, your actual code, here is the normal constructor for the view, where you're given these three parameters, you just initialize that object. Here is where you associate that dragger with the view in order to get this UI here. And so all you do to do that is you create the dragger, and you specify where you want the dragger to appear, and you give it a pointer to the replicant view. And then you add that dragger, it's a view, and you add it where -- in this case, I'm adding it as a child of the replicant view. You can see that here the little hand is living inside this clock, so it's a child of the clock.

Other relationships are allowed. If I go back -- let me open up Pulse. In the Pulse case, you can see that the hands are outside the button. In this case, the dragger and the button are sibling views. So you can have that relationship, and you can also have the dragger be the parent of the replicant views, so any of those relationships are allowed. It sounds a little complicated, but it's really not. You just do whatever is natural. You just have a view and you add it.

So now we've created the clock view as it exists in this application here. Here is the view, and here is the dragger.

Now, when I did this to create an instance of it, at this point, Archive was called to archive this object, and so here is the archive method in clock, and I'm given the data container. So I call Inherited here to get everything that I'm inheriting from to properly archive.

And then there is a bunch of just adding data to that container, and I add whatever it is that's important for that particular object, like the bounds, okay; I want to remember where the view lives, so I archive the bounds. Remember, you can change the face of the clock, so I need to save this integer which tells me what face to display, and I need to save the Boolean, whether I'm showing seconds or not showing seconds.

By saving all this stuff, every time I restart my machine, the clock is going to come up in the same place with the same face with the seconds on or off as appropriate.

This first thing, this is where I talked about the signature of the application or library that defines that class. So I add the signature under the special name add-on, and I specify the signature. And this allows the system then to know where it is that the code lives that will be able to recreate the object the next time my machine gets turned on, for instance.

So now here's the constructor -- well, let me skip down to this last one and look at the Instantiate function. So when I take this and I drop this on -- I'm dropping this archived object onto another application, the tracker. So when I drop it, what happens is, the system gets this message, and it seems okay, it is an archived replicant.

It looks and figures out, using this piece of information we added before, as well as some other information that gets added into the system, it figures out that it needs to call -- it needs to load that library if it's not already loaded, and then it calls this static function Instantiate, passing it the message.

So these three lines of code are code that you would write for every replicant. They are basically identical. It's just checking to make sure that you have a valid message. So these three identical lines -- I mean, almost identical. Your class name would go here as well as a call to New would go here. So this is just basically cut and paste. So that's all you have to do in the instantiate function.

And then the constructor, here your constructor is called, T clock, passing it a BMessage. So all you do in this constructor is you get the data, you call your inherited constructor with the message, and then you just extract the data that you added up above. Here is the data that you added above, and you just extract it out of the message, and you call your initial -- and you do your initialization. And when that's completed, you end up with your replicant living in another application.

A question?

FROM THE AUDIENCE: In the archive method, you have the MIME string and the special add-on name. What if I want to subclass this replicant; do I have to make sure I blow away that one before I add the subclass?

POTREBIC: I didn't quite...

FROM THE AUDIENCE: Sorry. You added the MIME string in the archive method. If I subclass this object, that method, that objects is archived. If you just say add string, it will add another string, so you have one more MIME thing. So do you have to make sure you blow away the first one first?

POTREBIC: Well, it depends. If they all live in the same library, then it doesn't matter, it's all going to be the same MIME string. If they live in different libraries, I hadn't really thought about that. What the system is going to find is the first one that was added, so the first time add string add-on is called. So depending on where you place your call to Inherited, it will define which library it will look in. But that's a good point for me to think about and potentially look through a list of those.

So that's all there is to creating a replicant. Hopefully that's not that difficult. I'll take another question.

FROM THE AUDIENCE: You obviously created the new clock. What's the target of like deleting the memory and cleaning up after itself? Is that part of (inaudible), or will the system take care of it?

POTREBIC: Well, in the view world, when a window is closed, all of the views that live in that window are automatically -- the destructors are automatically called, and view destructors are virtual. So when the desktop, which is really a window, when you shut down the machine, that window will get deleted, and so your view's destructor will get called, so that just happens naturally.

If you're dealing with a replicant that isn't a view, that's some non-UI thing, which is allowed, then, you know, something else will be calling delete at the appropriate time.



So now I'm going to talk about making a container view, how do you make a thing that can hold replicants. And there is just one class here to talk about, and that's BShelf, and you actually don't have a subclass here.

Initially, we thought of, you know, your first idea would be you have a special type of view that's a container, and you would subclass that, but we felt that that was a little restrictive, because what if you already had, in the case of the tracker, well, the tracker already had all this mechanism for doing views that can hold icons, and trying to change the way they all descended from, you know, something just didn't make -- it just made it a little more complicated.

So actually we designed it so you don't have to subclass. All you really do is associate one of these objects with the view that you want to become the container view, and I'll show you how that's done, and poof, that view becomes a container view.



And I have some more sample code to show that. So imagine this is tracker code, and we're looking at the code for the desktop view that we don't see much of anymore, and all you have to do to make yourself -- make your view a container is, you're in your constructor when the view is getting constructed, and most of this stuff is just picking out where you want the data to be live.

When I quit the tracker, the data that defines these two clocks sitting in this particular location, that has to get saved someplace, so when you turn your machine on again, the tracker can read that back and everything gets rehydrated.

So most of this stuff here is just finding that location. In the Be environment you should save those settings. Using the FindDirectory command, you get a path to the settings directory, which lives inside your home directory. You say, okay, I'm going to keep everything in a file called MyStore. This here just makes sure that that file exists. Then you get a reference, one of our entry refs. If you went to the Be file system talk or talks, it makes a little more sense.

And so basically once you have -- all these lines are just getting a reference to that file. Then all you do is you create this BShelf object right here, and you pass it the file that you want the data to be saved in, and then you pass it the view that you want to become a container view. So that will make that view a container view, and it will now accept replicants.

And so that's the constructor. And in the destructor, all you do is, when that view is getting deleted, all you want to do is delete that shelf object, and that will force everything to get saved into the backing store, the file.

So that's all it takes to create a container view, and so that's -- you know, it took five minutes to make the tracker container view; making this little area of the status bar was that simple. There's also a demo app which I believe the source for this is already available, container. This is a container, and I can drag things off the desktop and plop them onto here. I quit it, relaunched it, and there it appears, if I move it and I close it and relaunch it in its old place. So that's all there is to making a container view in the basics of the container view.



Now I'm going to talk about some more of the advanced features. The idea is we always want to start simple and make it easy to use our stuff. So hopefully the container view and making a replicant can seem fairly straightforward. And we want to start there and then build power on top of that, so that our system stays simple.





So a couple of the customizations and advanced techniques you can do, you can allow or disallow program user initiated changes to a container view. I showed you an example of that, where I tried to drag the Pulse replicant to this, which is a container view, but it wouldn't let me drop it, and that's because the desk bar has disallowed user-initiated drags of replicants, and that's done in the BShelf, constructor; there is a Boolean that says whether you want to allow user manipulation or disallow it. So, by using that Boolean, you can customize what kind of container you want to use.



Another customization is, you can use this -- there's a notion of a kind of container, which is another parameter to the constructor, and that's basically naming it. And if you name a container, then that container will only accept replicants that also have that same name inside of them.

And that's a way to, again, if you want to create a tool pallet that is using replicants, and in your application then a user can configure what tools that they commonly use, you can do that using replicants, but you can do it in such a way that they wouldn't be able to drag clock into your tool pallet, because it doesn't make sense. You only want your tools to live in that tool pallet.

There is also API in the BShelf class. You can subclass that class and hook into a few different -- take advantage of a few different customizations. There is a method called CanAcceptReplicantMessage. That might be one of our longer functions. And this is the message.

So when a drop occurs, either user initiated or programmatically, a message is sent to the container view. This hook function is called. So you can override that, and you can take a look inside that data container and look for some special piece of information, and only if that special piece of information is there will you accept this replicant. So that's another way to ensure that only what you want lives inside of your container view.

Another very similar hook function is CanAcceptReplicantView. This gets called after that -- the raw data is hydrated into a BView. And then this hook function is called, we are giving the view, and you are given the rectangle where that view wants to live, and you can then look at the view, or you can look at the rectangle and reject for any reason by returning false that replicant.

So, for instance, this status view, this is never going to accept clock, because it's too big. So even if it was programmatically sent, it would reject it, because one of the things that the desk bar is going to do is it's only going to accept 16-by-16 or 16-by-32 sized views, because it just wants to have a little area there for widgets. So it will implement that functionality by overriding CanAcceptReplicantView.

And there is another hook function which is to order things or move things around on the screen. For instance, the status bar, it's already visible here, it's going to probably grid things that get sent to it, so this hook function is called just before -- again before the view is going to get added, and it allows you to adjust by returning the point. It allows you to shift where you want that view to live.

So in the tool pallet case, you would use this -- a user could just drop it on a tool pallet, and you would have that widget snap into the open location of the tool pallet.

I mentioned kind already, where a shelf can have a name, and if a shelf has a name, then it will only accept replicants that have that name as well. So here is how, if you want to work with that API and use that functionality, when you're archiving your replicants, you need to make this call, AddString, and you put in the kind or the type of shelf, and then you give the name that you created.

By doing that, the system kind of automatically does the compares for you. You don't have to override. You can do the same thing by overriding CanAcceptReplicantMessage and doing the work yourself, but we provided this API just to make this simple thing of just doing some name matching. Again, you could use this to build something like a tool pallet architecture.



So that's kind of the state of the replicant world right now. And as I think the Terminator said in Terminator 2, "The future is not known," or it might have been Terminator 1. We're not sure where this is going to go. We just got this release done, and we're in the planning stages, but there are definitely a lot of different areas that I've been thinking about.

I would like to see more support for data containers, where you can drag -- you could have an object that encapsulates some rich form of text, and on your machine that means you automatically get that text displayed in Application X, but on someone else's machine, they might have their system set up so that they want to use Application Y to show rich text, and have that kind of automatically happen.

That would involve kind of work between this replicant stuff and a lot of the MIME work we've done in this release as well, where different file types can have preferred handlers, so you can set up your machine today to -- you might have an editor that you want to use whenever you're editing a text/plain file so whenever you double click on a text/plain file, it opens up your editor, on my machine it might open up some other editor, and I want to use that same model to deal with these data containers.

There is more user interface work that needs to get done. My intention was this little menu that you can get up by clicking on the hand, you can give developers, if they create interesting replicants, they of course want to still have an About Box, and you can currently hook in and create your own About Box, so this you can customize. My intent then is to also be able to add some API here, so if you have preferences or whatever, you can add menus here to give some more user interface to your replicant.

Someone in an earlier session said, "Well, what happens when I put 50 clocks on my desktop? How do you get rid of them all?" There is no UI for that right now. So you have to go into your settings folder and throw away that backing store file that I showed you how to create earlier, called MyStore, basically find the right file for the tracker and throw that away, and that will get rid of everything. But we need some better UI for that.

Then some more support for saving and undoing in the shelf world. There is some API in there today for that, but nothing that -- it was just put in there to get an API in place so that we could add it in the future a little more easily, and for dealing with things like save, so a container could know, am I dirty, has something been added to me since the last time I saved, for things like undo. So there are lots of different areas that we can go in, and you can give me feedback as to how you think this should evolve.

I think that's about it. So I'll take questions now.

FROM THE AUDIENCE: I have a couple of questions. If you had two or three replicants of an application on the desktop, and you wanted to have different references for each of those applications, how would you do that?

POTREBIC: That just works naturally. I'll show you. Let me quit out of these slides. Let me close up some of this stuff. So here are two clocks. They are both living in the desktop, they have different faces, and I'll turn off seconds, but they're sitting right next to each other. So now I'm going to -- I'd better launch a terminal first. Now I'm going to quit the tracker.

So now the tracker quit using a hidden menu shortcut. The tracker is no longer running, so the desktop is gone. There is nothing on the desktop anymore. So let me launch the tracker again. You can see here, you can see the -- there is the web browser sitting there, and here are my two clocks. They are still in their same faces, and they still have their seconds on.

So, remember -- if we go and look at the archive code, each of these clocks is a separate view, each of them gets archived, and each of those views on its own saves what its current face is, whether I have my second hand showing or not, and so it's two separate hunks of information that get saved into that backing store.

FROM THE AUDIENCE: So whatever its last state was.

POTREBIC: Yes, that gets --

FROM THE AUDIENCE: That's what gets saved.

POTREBIC: Yes. It's really whatever the archive method does, which in most views will be saving the interesting attributes.

FROM THE AUDIENCE: I have one other question, and I think I saw it happen when you took one of the clocks and put it in the container. Around the dragger graphic, there appeared to be a box.

POTREBIC: Yes. The question was about the dragger graphic. The problem is that our current view system doesn't support transparent views, so this little hand icon is a view --

FROM THE AUDIENCE: So I didn't do it wrong.

POTREBIC: No, no. But it really has to be square, because you can't see the clock behind it. So sometimes it looks okay, but if you move things around, you get the screen turns --

FROM THE AUDIENCE: If you open a menu on top of the little dragger icon, and the menu goes away, then you see the white box behind it.

POTREBIC: Yes. So either -- we have talked about transparent views, which is one thing. The other alternative is, I might just change the default UI for it to be something that is square. You can make your own -- you can take BDragger which creates that and subclass it and override draw and implement your own UI, and that's what's going to get drawn instead, to indicate this is the thing to move me with.

So some of the other areas we want to go is, if you're going to use this, for instance, to build a tool pallet, you don't really want to have these little hands all over the place, so you can start Initiate dragging a replicant without using a BDragger object, and that's just a matter of a few lines of code as well, which I haven't shown. So there is work to be done in the BDragger world.

FROM THE AUDIENCE: I had a question about the way replicants were handled on the desktop. Do you have plans to make it so that they won't be universal to all the workspaces so that they will only show up in one?

POTREBIC: There are lots of workspace- related issues on what shows up where and when you fly between workspaces, you know, when you double click on something, and replicant issues, and just other things on the desktop, you know, an icon on the desktop showing up in every workspace. So it's something that we're going to work on. We definitely know about those problems.

FROM THE AUDIENCE: This is a variation on the add-on problem, the instance that you are archiving has multiple listings (inaudible), so you need something to prefix the names on a per instance basis. How do you deal with that?

POTREBIC: The question was, when you are archiving an object, and say that object that you are archiving has multiple instances of some other object, and those are all going to get archived into that data container BMessage, how does that all work, and that example works very well. I'll give you another example where something doesn't work that great.

Think of a view, when you archive a view, it might have eight other views, and the parent view, all it knows is that there are eight views; it doesn't know if there are a button, a check box, a text view. So the parent view just archives each of those eight views into a message and then puts that message inside of its own message under the same name. So you have this kind of tree of messages, and all those eight subviews get added into the same entry.

Let me go back to some sample codes. This one, I think. All right. So in effect you just have a whole bunch of AddMessage into the same exact -- you know, the second view, the third view, all under the same name.

Now, archiving of subviews is done for you by the system, just by making sure in your views you call Inherited. But if you had your own objects, you would just do the same thing. You would have a little loop, and you would archive each of those objects that you had and put them into the same message, and then on the other side, you would just read each of the objects back out of that same entry. Now -- is that clear?

FROM THE AUDIENCE: I almost believe you.

POTREBIC: Okay. What our current archiving method system doesn't work well on -- it works well on a tree of objects, but if you have an object that you want to archive, and say it has two subobjects and each of those subobjects refers to another object, the system doesn't handle that well. You will end up with that -- if you don't do anything, you will end up with that subobject, subsubobject, archived twice.

And again, I've thought about the mechanism for handling arbitrary graph of objects and being able to archive those, and then on the other end being able to recreate them and fix up all of the pointers. That's just in this first version that hasn't been implemented. So if you do have that type of object structure that you want to archive, you have to do your own mechanism to ensure that the object is archived once and the right things happen.

FROM THE AUDIENCE: Two things: What is the -- how do we make an About Box for a replicant, and how do we add something to the desk bar?

POTREBIC: The question -- the first question -- I'll take the second one first, how do you add something to the desk bar. In the Preview Release, that's not really a public API, we kind of did that really fast at the end. So you could probably figure it out and get something to happen. But the desk bar isn't overriding the right calls to make sure that the second thing that gets added shows up in this empty space, for example, and what is it going to do if a third thing gets added and there is no room. So that functionality doesn't exist yet in the desk bar, but we're definitely planning on adding that.

Then your first question was -- now I forget.

FROM THE AUDIENCE: The About Box.

POTREBIC: The About Box. What happens is when you bring up the little pop-up menu, which is under the secondary mouse button, and you select this, what the system does is it sends a BAboutRequested message, which is standard BMessage that apps used to implement their About Box. When I select the About Box in the Be IDE, it's probably sending the BAboutRequested message.

That message gets sent to the replicant view. So all you have to do in this case, in T clock view, is override -- there's a hook function called AboutRequested, I think, either that or you override MessageReceived, and you look for this what field, and then you make your own dialogues and spinning chairs or whatever, and do your own thing.

The default case, if you never -- if you don't override it, the default is just it brings up a little About Box that has the name of the view in there. So it's all just a matter of hooking into the event mechanism and catching the event.

FROM THE AUDIENCE: In at least the Advanced Access documentation for the Archivable, it mentioned putting the classing of the object into the message. Is that not necessary for replicants?

POTREBIC: The question was about Archivable, and the documentation said that you -- one of the other things that you do when you archive something is you put the class name in there, and it's not necessary, because at the top level there is the archived implementation in the BArchivable class which is at the top of the whole thing, and that will get the class name using C++'s runtime type information, and it will stuff it in the message. So you don't have to.

FROM THE AUDIENCE: There is also something about putting it for each class all the way down the chain and which order you had to put it in.

POTREBIC: The question was, well, we said maybe put them in -- every class should put it in there, and that was when we were thinking, well, suppose I have a class that is fancy button, and it's a replicant, and I sent it over to another machine and that machine doesn't have fancy button, but it does have plain button; well, maybe it can just instantiate itself just as a plain button, so you lose the fancy part.

That works for simple things like buttons, but it really breaks down, I mean, if I have some real replicant that implements something, you know. It doesn't make -- you can't really say, "Well, I don't have that code, but I'll make do with this." So we kind of punted on that.

FROM THE AUDIENCE: (Inaudible)

POTREBIC: The question was user interface guidelines and how an app developer might think about having the tool pallet, is it a separate window, how do you get things in and out of it, and guidelines for that. And I know we will be thinking about that, and we will be working on user interface guidelines. So we'll probably have something to say about that.

But we're completely willing to let a developer explore different ways to move things around. You can use a drag and drop metaphor, you can think of other ways in which to -- you can have your tool pallet and have an edit mode where users can reorder things and package things up and make it a separate application, if you want, that just sends messages, where the real -- you know, the paint program and the tool pallet are separate.

So, I mean, right now, since all this stuff is new, I don't know if it sounds like a copout or not to say, but it's things we've thought about but we haven't actually implemented, although I know you could implement a neat tool pallet using this technology, but we haven't, so we haven't explored what would be the right ways to do it.

FROM THE AUDIENCE: I just have a comment, I guess, on the user interface guidelines. It seems to me that I've heard a number of times over the past couple of days people asking you about that, and it seems to me that that's premature. I think you shouldn't do anything with user interface guidelines for a period of time and let us explore every direction, and then you will have a lot more information available to you to make good decisions on what those guidelines should be.

POTREBIC: We've heard comments from people saying, "You need user interface guidelines," and a lot of people like you are saying, "No, let people explore, and let's let things settle." And I think part of the reason, honestly, why we don't have them is there has been that, "Well, should we or shouldn't we?" We have had efforts to make them, but they haven't had the momentum to -- we're a small company, so it's really through our motivation and marketing or the engineers that things happen, and when enough of us are motivated and know it's the right thing, things happen.

And since user interface guidelines haven't happened -- we definitely hear a lot of feedback like that, but we also understand that we need to get some guidelines out there, but still not restrict developers from exploring different types of interface.

FROM THE AUDIENCE: Is there any way to prevent your replicants from being dragged? You don't want your tools to end up on a desktop.

POTREBIC: One way to do it right now is -- the question was, could you prevent your replicants from being dragged, and one way right now is to not associate this BDragger object with your replicant.

FROM THE AUDIENCE: Restrict where they go to not prevent them.

POTREBIC: Well, restricting where they go to, you can do through that naming mechanism, which actually doesn't work in the direction you're asking today. I don't know why I didn't. It's just like ten lines of code, and I realized it like two weeks ago. So in one of the subsequent releases, you will be able to -- if a replicant has a name in it in a special place, and the associated container doesn't, then the replicant will say, hey, I'm not going there. Right now it only works in the other direction.

So you will have multiple ways for managing who you want to become friends with.

FROM THE AUDIENCE: I see a problem, for example, when you replicant a clock from a desktop, obviously then you still have the clock application running and the replicant on the desktop. Is there a way to know, for example, when you have been replicated so you could close the clock program?

POTREBIC: The code could. I mean, this code here -- where is the constructor? When this constructor is being called, this view knows I am being instantiated in the replicant way, and you could write some code in here that sees, is the clock running as an app, and if it is, send it a quit message. And there are other issues in terms of when you drag the replicant within the container, it just moves; when you drag it between one container to another, it's a duplicate. So there are those UI issues which we have to kind of think about as well.

FROM THE AUDIENCE: Except that's an awfully nice way to do plain old storing your data, so perhaps adding something to the BMessage that's coming into the constructor saying, I am being created from a drag, versus just using Archivable to store something which I've done and bring it back in.

POTREBIC: Yes, you're right.

FROM THE AUDIENCE: (Inaudible)

POTREBIC: Was your question about little-endian, big-endian? The question was little-endian, big-endian, and archiving. Even at a lower level, it is just BMessage, how is BMessage going to work across endian machines, because so much of our system uses BMessages, and all of this stuff just uses BMessages. So once we have BMessages right, archiving will be right, replicants on top of that will be right, and so forth.

So that's obviously one of the things we're working on right now getting ourselves up and running on Intel. That's something that we are working on.

FROM THE AUDIENCE: (Inaudible)

POTREBIC: I personally haven't. The question was, have you tried replicants on Intel? I'm sure on Intel they work fine. What I'm not sure about is if you took the file and you put it on Be Machine, what would happen, the backing store file.

A couple of minutes if there are any more questions.

FROM THE AUDIENCE: A simple one: Would you drop a digital clock on your pass file and delete?

POTREBIC: There is no more digital clock app in the Preview Release. The question was about the little digital clock app which we originally -- that's what we originally did, made it so you could drag it to the desk bar, but then we realized that dragging to the desk bar just isn't right. It should be a programmatic thing where an app sends a replicant to the desk bar like the mail server.

FROM THE AUDIENCE: Are you going to bring back functionality for the clock like showing seconds, 24-hour time, et cetera?

POTREBIC: The question?

FROM THE AUDIENCE: Bringing back the functionality of the digital clock in the desk bar; you used to be able to do 24-hour time and seconds.

POTREBIC: The question was about the functionality in the digital clock where it used to show seconds or turn the 24-hour clock on and off. I don't know. Sure. It's nothing -- I want major architectural questions, the hard ones. That is just a couple of features. I don't know why it disappeared.

FROM THE AUDIENCE: When are 3d Kit objects going to be container views?

POTREBIC: Pierre and I were talking about that; that would have been neat to do. I thought we could have a replicant contest at our next Developer Conference where you could try to come up with a neat replicant. I thought that might be fun.

I think I just have time for one more question.

FROM THE AUDIENCE: (Inaudible)

POTREBIC: The question was about the NetPositive resizing functionality. I mean, that was probably the hardest part about doing this, and, yes, I did have to write a little view to handle this resizing, and I made it look like a resize thing on a window.

I picked up -- I looked at the replicant source like two days before our last Developer Conference in May, never looked at it before, and I think in three hours I had it as a replicant. And then after that, it was mostly trying to get so you could resize it and make it look right and things like that. So it wasn't my own view. Pretty simple.

All right. I think that's all I have time for, but I think we have now our general Q&A session in the main room where all of us will be up there, if you have more questions about this or anything else.

(Applause)

(End of session)


Home | About Be | Be Products | BeWare | Purchase | Events | Developers | Be User Groups | Support


Copyright ©1997 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.
Icons used herein are the property of Be Inc. All rights reserved.