xref: /haiku/src/tests/kits/interface/bshelf/ShelfInspector/readme.txt (revision 268f99dd7dc4bd7474a8bd2742d3f1ec1de6752a)
1*d5f7f405SAugustin CavalierInspector Detector: the Shelf Inspector
2*d5f7f405SAugustin Cavalier
3*d5f7f405SAugustin CavalierWriting replicants is cool, and as our system evolves we'll see them used more often. Replicant creation is fairly easily, but there are some trouble spots. To help you avoid them I've started writing an application to smooth out the process: the Shelf Inspector. This app will work as a test bed for writing both replicants and containers. It will also show off some of the new scriptability found in all Replicants and BShelf objects. This is Part 1 of a multipart article.
4*d5f7f405SAugustin Cavalier
5*d5f7f405SAugustin CavalierThe first step is to inspect (and manipulate) the contents of a container view. You can find the sample app associated with this text at <ftp://ftp.be.com/pub/samples/application_kit/ShelfInspector.zip>.
6*d5f7f405SAugustin Cavalier
7*d5f7f405SAugustin CavalierThis app lets you interrogate a BShelf object (aka "container view") to see what replicants it contains. One common difficulty with replicants is managing the add-on/library that defines the replicant. The Shelf Inspector helps with this by showing the images currently loaded in the target application. It also lets you unload libraries that are no longer in use (be careful not to unload libraries that still are in use). This a good time to build and run the Shelf Inspector. You'll notice when you launch it that it also launches the Container demo application; these two apps work together.
8*d5f7f405SAugustin Cavalier
9*d5f7f405SAugustin CavalierThe Target Shelf: popup in the Shelf Inspector window can target any one of three container views in the system. Try it! The top list shows currently loaded replicants; the lower list shows the libraries loaded by the target application. By selecting a replicant in the top list you can delete it (with the Delete button) or you can try copying (cloning) the replicant into the Container demo application.
10*d5f7f405SAugustin Cavalier
11*d5f7f405SAugustin CavalierA warning here: not all replicants want to be cloned this way, but I thought it was useful to show the possibility. Such cloning can screw up the Container demo. If you run into problems it might help to remove the backing store file for the Container demo
12*d5f7f405SAugustin Cavalier(delete  /boot/home/config/settings/Container_data).
13*d5f7f405SAugustin Cavalier
14*d5f7f405SAugustin CavalierThat's about all there is to the app at this point. There will be more in the future. Now let's switch gears and talk about the implementation. The interesting code -- which figures out what replicants are loaded in some other application -- is in the following functions:
15*d5f7f405SAugustin Cavalier
16*d5f7f405SAugustin CavalierBMessenger	TInfoWindow::MessengerForTarget(type_code w)
17*d5f7f405SAugustin Cavalierint32		TInfoWindow::GetReplicantAt(int32 index)
18*d5f7f405SAugustin Cavalierstatus_t	TInfoWindow::GetReplicantName(int32 uid, BMessage *result)
19*d5f7f405SAugustin Cavalierstatus_t	TInfoWindow::DeleteReplicant(int32 uid)
20*d5f7f405SAugustin Cavalierstatus_t	TInfoWindow::ImportReplicant(int32 uid)
21*d5f7f405SAugustin Cavalier
22*d5f7f405SAugustin CavalierThe MessengerForTarget function uses the BeOS scripting protocol to get a BMessenger for the target shelf in the target application. Taking the Deskbar as an example, the code looks like this:
23*d5f7f405SAugustin Cavalier
24*d5f7f405SAugustin Cavalier	request.AddSpecifier("Messenger");
25*d5f7f405SAugustin Cavalier	request.AddSpecifier("Shelf");
26*d5f7f405SAugustin Cavalier	request.AddSpecifier("View", "Status");
27*d5f7f405SAugustin Cavalier	request.AddSpecifier("Window", "Deskbar");
28*d5f7f405SAugustin Cavalier	to = BMessenger("application/x-vnd.Be-TSKB", -1);
29*d5f7f405SAugustin Cavalier
30*d5f7f405SAugustin CavalierWe're asking for the "Messenger" to the "Shelf" in the View "Status" in the Window "Deskbar" of the Deskbar application.
31*d5f7f405SAugustin Cavalier
32*d5f7f405SAugustin Cavalier
33*d5f7f405SAugustin CavalierEvery replicant living inside a BShelf object automatically inherits several "Properties":
34*d5f7f405SAugustin Cavalier
35*d5f7f405SAugustin Cavalier   * ID - each replicant gets a unique ID when added to a shelf.
36*d5f7f405SAugustin Cavalier   * Name - the Name of the top view of the replicant.
37*d5f7f405SAugustin Cavalier   * Signature - the signature of the add-on defining the replicant.
38*d5f7f405SAugustin Cavalier   * Suites - the computer-readable description of these properties.
39*d5f7f405SAugustin Cavalier   * View - the property "pointing" to the top view of the replicant.
40*d5f7f405SAugustin Cavalier
41*d5f7f405SAugustin CavalierThe GetReplicantName and GetReplicantAt functions use these properties to do their work. Looking more closely at GetReplicantAt, it asks the shelf for the ID of the replicant at a given index:
42*d5f7f405SAugustin Cavalier
43*d5f7f405SAugustin Cavalier	BMessage	request(B_GET_PROPERTY);
44*d5f7f405SAugustin Cavalier	request.AddSpecifier("ID");			// want the ID
45*d5f7f405SAugustin Cavalier	request.AddSpecifier("Replicant", index); 	// the index
46*d5f7f405SAugustin Cavalier	// fTarget as returned by MessengerForTarget()
47*d5f7f405SAugustin Cavalier	fTarget.SendMessage(request, &reply);
48*d5f7f405SAugustin Cavalier	reply.FindInt32("result", &uid);
49*d5f7f405SAugustin Cavalier
50*d5f7f405SAugustin CavalierAnd that's how we get the replicant's ID, which remains valid across "saves." Thus, in the Container demo, IDs remain valid across quit/launch cycles. For shelves that don't save their state (e.g., the Deskbar), the ID for a replicant, such as the mailbox widget, potentially changes each time it is added to the shelf.
51*d5f7f405SAugustin Cavalier
52*d5f7f405SAugustin CavalierJust as every replicant supports a set of properties, so does a shelf. Every shelf defines one property called "Replicant" that supports the following actions:
53*d5f7f405SAugustin Cavalier
54*d5f7f405SAugustin Cavalier    * counting the number of replicants
55*d5f7f405SAugustin Cavalier    * adding a new replicant
56*d5f7f405SAugustin Cavalier    * deleting an existing replicant
57*d5f7f405SAugustin Cavalier    * getting the "data archive" defining a replicant
58*d5f7f405SAugustin Cavalier
59*d5f7f405SAugustin CavalierImportReplicant() and DeleteReplicant() use these features. ImportReplicant() gets a copy of the data archive (the archived BMessage) for the replicant. Then it sends that archive to the Container demo and asks it to create a new replicant. Let's take a closer look:
60*d5f7f405SAugustin Cavalier
61*d5f7f405SAugustin Cavalier	BMessage	request(B_GET_PROPERTY); 		// Get the archive
62*d5f7f405SAugustin Cavalier	BMessage	uid_specifier(B_ID_SPECIFIER);
63*d5f7f405SAugustin Cavalier
64*d5f7f405SAugustin Cavalier	// IDs are specified using code like so:
65*d5f7f405SAugustin Cavalier	uid_specifier.AddInt32("id", uid);
66*d5f7f405SAugustin Cavalier	uid_specifier.AddString("property", "Replicant");
67*d5f7f405SAugustin Cavalier	request.AddSpecifier(&uid_specifier);
68*d5f7f405SAugustin Cavalier
69*d5f7f405SAugustin Cavalier	fTarget.SendMessage(&request, &reply);
70*d5f7f405SAugustin Cavalier	// various error checking omitted
71*d5f7f405SAugustin Cavalier
72*d5f7f405SAugustin Cavalier	// OK, let's get the archive message
73*d5f7f405SAugustin Cavalier	BMessage	data;
74*d5f7f405SAugustin Cavalier	reply.FindMessage("result", &data);
75*d5f7f405SAugustin Cavalier
76*d5f7f405SAugustin Cavalier	// get messenger to the shelf in the Container demo
77*d5f7f405SAugustin Cavalier	BMessenger	mess 	MessengerForTarget(CONTAINER_MESSENGER);
78*d5f7f405SAugustin Cavalier	BMessage	msg(B_CREATE_PROPERTY);
79*d5f7f405SAugustin Cavalier	request2.AddMessage("data", &data);
80*d5f7f405SAugustin Cavalier	return mess.SendMessage(&request2, &reply);
81*d5f7f405SAugustin Cavalier
82*d5f7f405SAugustin Cavalier
83*d5f7f405SAugustin CavalierFirst we send a GET command, asking the shelf to return a copy of the archive data message for the replicant whose unique ID is uid. Then we extract the archived data message and add it to a CREATE message. This is sent to the shelf in the Container demo app, and that's it. Note that not all replicants respond well to this manipulation; the Shelf Inspector warns you if this is the case when you select the Copy to Container button. The Clock replicant works fine, so it's a good one to play with.
84*d5f7f405SAugustin Cavalier
85*d5f7f405SAugustin CavalierThe Library list isn't all that useful right now, but it can let you see if you're properly using some of the advanced replicant features such as the be:load_each_time and be:unload_on_delete flags. If "unload on delete" is set in a replicant that is removed, the corresponding library should also be removed. If "load each time" is set and the same replicant is loaded multiple times you should also see the library loaded the same number of times. In a future version of the Shelf Inspector I'll include some configurable test replicants that show these features in action.
86*d5f7f405SAugustin Cavalier
87*d5f7f405SAugustin CavalierThat's it for this installment. Have fun programming the BeOS!
88