6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
35 // PoseView scripting interface
41 #include <ByteOrder.h>
44 #include <PropertyInfo.h>
49 #define kPosesSuites "suite/vnd.Be-TrackerPoses"
51 #define kPropertyPath "Path"
53 // notes on PoseView scripting interface:
54 // Indices and entry_refs are used to specify poses; In the case of indices
55 // and previous/next specifiers the current PoseView sort order is used.
56 // If PoseView is not in list view mode, the order in which poses are indexed
58 // Both of these specifiers, but indices more so, are likely to be accurate
59 // only untill a next change to the PoseView (a change may be adding,
60 // removing a pose, changing an attribute or stat resulting in a sort ordering
61 // change, changing the sort ordering rule. When getting a selected item,
62 // there is no guarantee that the item will still be selected after the
63 // operation. The client must be able to deal with these inaccuracies.
64 // Specifying an index/entry_ref that no longer exists will be handled well.
67 doo Tracker get Suites of Poses of Window test
68 doo Tracker get Path of Poses of Window test
69 doo Tracker count Entry of Poses of Window test
70 doo Tracker get Entry of Poses of Window test
71 doo Tracker get Entry
2 of Poses of Window test
72 doo Tracker count Selection of Poses of Window test
73 doo Tracker get Selection of Poses of Window test
74 doo Tracker
delete Entry
'test/6L6' of Poses of Window test
75 doo Tracker execute Entry
'test/6L6' of Poses of Window test
76 doo Tracker execute Entry
2 of Poses of Window test
77 doo Tracker set Selection of Poses of Window test to
[0,2]
78 doo Tracker set Selection of Poses of Window test to
'test/KT55'
79 doo Tracker create Selection of Poses of Window test to
'test/EL34'
80 doo Tracker
delete Selection
'test/EL34' of Poses of Window test
84 // access list view column state
87 // - pose text widgets
90 const property_info kPosesPropertyList
[] = {
93 { B_DIRECT_SPECIFIER
},
94 "get Path of ... # returns the path of a Tracker window, "
95 "error if no path associated",
102 { B_COUNT_PROPERTIES
},
103 { B_DIRECT_SPECIFIER
},
104 "count Entry of ... # count entries in a PoseView",
111 { B_DELETE_PROPERTY
},
112 { B_ENTRY_SPECIFIER
, B_INDEX_SPECIFIER
},
113 "delete Entry {path|index} # deletes specified entries in a PoseView",
121 { B_DIRECT_SPECIFIER
, B_INDEX_SPECIFIER
, kPreviousSpecifier
,
123 "get Entry [next|previous|index] # returns specified entries",
130 { B_EXECUTE_PROPERTY
},
131 { B_ENTRY_SPECIFIER
, B_INDEX_SPECIFIER
},
132 "execute Entry {path|index} # opens specified entries",
138 { kPropertySelection
,
140 { B_DIRECT_SPECIFIER
, kPreviousSpecifier
, kNextSpecifier
},
141 "get Selection [next|previous] # returns the selected entries",
147 { kPropertySelection
,
149 { B_DIRECT_SPECIFIER
, kPreviousSpecifier
, kNextSpecifier
},
150 "set Selection of ... to {next|previous|entry} # selects specified "
157 { kPropertySelection
,
158 { B_COUNT_PROPERTIES
},
159 { B_DIRECT_SPECIFIER
},
160 "count Selection of ... # counts selected items",
166 { kPropertySelection
,
167 { B_CREATE_PROPERTY
},
168 { B_DIRECT_SPECIFIER
},
169 "create selection of ... to {entry|index} "
170 "# adds specified items to a selection in a PoseView",
176 { kPropertySelection
,
177 { B_DELETE_PROPERTY
},
178 { B_ENTRY_SPECIFIER
, B_INDEX_SPECIFIER
},
179 "delete selection {path|index} of ... "
180 "# removes specified items from a selection in a PoseView",
192 BPoseView::GetSupportedSuites(BMessage
* data
)
194 data
->AddString("suites", kPosesSuites
);
195 BPropertyInfo
propertyInfo(
196 const_cast<property_info
*>(kPosesPropertyList
));
197 data
->AddFlat("messages", &propertyInfo
);
199 return _inherited::GetSupportedSuites(data
);
204 BPoseView::HandleScriptingMessage(BMessage
* message
)
206 if (message
->what
!= B_GET_PROPERTY
207 && message
->what
!= B_SET_PROPERTY
208 && message
->what
!= B_CREATE_PROPERTY
209 && message
->what
!= B_COUNT_PROPERTIES
210 && message
->what
!= B_DELETE_PROPERTY
211 && message
->what
!= B_EXECUTE_PROPERTY
) {
215 // dispatch scripting messages
216 BMessage
reply(B_REPLY
);
217 const char* property
= 0;
218 bool handled
= false;
223 status_t result
= message
->GetCurrentSpecifier(&index
, &specifier
,
226 if (result
!= B_OK
|| index
== -1)
229 ASSERT(property
!= NULL
);
231 switch (message
->what
) {
232 case B_CREATE_PROPERTY
:
233 handled
= CreateProperty(message
, &specifier
, form
, property
,
238 handled
= GetProperty(&specifier
, form
, property
, &reply
);
242 handled
= SetProperty(message
, &specifier
, form
, property
,
246 case B_COUNT_PROPERTIES
:
247 handled
= CountProperty(&specifier
, form
, property
, &reply
);
250 case B_DELETE_PROPERTY
:
251 handled
= DeleteProperty(&specifier
, form
, property
, &reply
);
254 case B_EXECUTE_PROPERTY
:
255 handled
= ExecuteProperty(&specifier
, form
, property
, &reply
);
260 // done handling message, send a reply
261 message
->SendReply(&reply
);
269 BPoseView::ExecuteProperty(BMessage
* specifier
, int32 form
,
270 const char* property
, BMessage
* reply
)
272 status_t result
= B_OK
;
273 bool handled
= false;
274 if (strcmp(property
, kPropertyEntry
) == 0) {
275 BMessage
launchMessage(B_REFS_RECEIVED
);
277 if (form
== (int32
)B_ENTRY_SPECIFIER
) {
278 // move all poses specified by entry_ref to Trash
280 for (int32 index
= 0; specifier
->FindRef("refs", index
, &ref
)
282 launchMessage
.AddRef("refs", &ref
);
283 } else if (form
== (int32
)B_INDEX_SPECIFIER
) {
284 // move all poses specified by index to Trash
285 int32 specifyingIndex
;
286 for (int32 index
= 0; specifier
->FindInt32("index", index
,
287 &specifyingIndex
) == B_OK
; index
++) {
288 BPose
* pose
= PoseAtIndex(specifyingIndex
);
291 result
= B_ENTRY_NOT_FOUND
;
295 launchMessage
.AddRef("refs", pose
->TargetModel()->EntryRef());
300 if (result
== B_OK
) {
301 // add a messenger to the launch message that will be used to
302 // dispatch scripting calls from apps to the PoseView
303 launchMessage
.AddMessenger("TrackerViewToken",
304 BMessenger(this, 0, 0));
305 if (fSelectionHandler
)
306 fSelectionHandler
->PostMessage(&launchMessage
);
312 reply
->AddInt32("error", result
);
319 BPoseView::CreateProperty(BMessage
* specifier
, BMessage
*, int32 form
,
320 const char* property
, BMessage
* reply
)
322 status_t result
= B_OK
;
323 bool handled
= false;
324 if (strcmp(property
, kPropertySelection
) == 0) {
325 // creating on a selection expands the current selection
327 if (form
!= B_DIRECT_SPECIFIER
)
328 // only support direct specifier
331 // items to add to a selection may be passed as refs or as indices
332 if (specifier
->HasRef("data")) {
334 // select poses specified by entries
335 for (int32 index
= 0; specifier
->FindRef("data", index
, &ref
)
338 BPose
* pose
= FindPose(&ref
, form
, &poseIndex
);
341 result
= B_ENTRY_NOT_FOUND
;
346 AddPoseToSelection(pose
, poseIndex
);
350 // select poses specified by indices
351 int32 specifyingIndex
;
352 for (int32 index
= 0; specifier
->FindInt32("data", index
,
353 &specifyingIndex
) == B_OK
; index
++) {
354 BPose
* pose
= PoseAtIndex(specifyingIndex
);
356 result
= B_BAD_INDEX
;
361 AddPoseToSelection(pose
, specifyingIndex
);
368 reply
->AddInt32("error", result
);
375 BPoseView::DeleteProperty(BMessage
* specifier
, int32 form
,
376 const char* property
, BMessage
* reply
)
378 status_t result
= B_OK
;
379 bool handled
= false;
381 if (strcmp(property
, kPropertySelection
) == 0) {
382 // deleting on a selection is handled as removing a part of the
383 // selection not to be confused with deleting a selected item
385 if (form
== (int32
)B_ENTRY_SPECIFIER
) {
387 // select poses specified by entries
388 for (int32 index
= 0; specifier
->FindRef("refs", index
, &ref
)
391 BPose
* pose
= FindPose(&ref
, form
, &poseIndex
);
394 result
= B_ENTRY_NOT_FOUND
;
398 RemovePoseFromSelection(pose
);
402 } else if (form
== B_INDEX_SPECIFIER
) {
403 // move all poses specified by index to Trash
404 int32 specifyingIndex
;
405 for (int32 index
= 0; specifier
->FindInt32("index", index
,
406 &specifyingIndex
) == B_OK
; index
++) {
407 BPose
* pose
= PoseAtIndex(specifyingIndex
);
410 result
= B_BAD_INDEX
;
414 RemovePoseFromSelection(pose
);
420 } else if (strcmp(property
, kPropertyEntry
) == 0) {
421 // deleting entries is handled by moving entries to trash
423 // build a list of entries, specified by the specifier
424 BObjectList
<entry_ref
>* entryList
= new BObjectList
<entry_ref
>();
425 // list will be deleted for us by the trashing thread
427 if (form
== (int32
)B_ENTRY_SPECIFIER
) {
428 // move all poses specified by entry_ref to Trash
430 for (int32 index
= 0; specifier
->FindRef("refs", index
, &ref
)
432 entryList
->AddItem(new entry_ref(ref
));
434 } else if (form
== (int32
)B_INDEX_SPECIFIER
) {
435 // move all poses specified by index to Trash
436 int32 specifyingIndex
;
437 for (int32 index
= 0; specifier
->FindInt32("index", index
,
438 &specifyingIndex
) == B_OK
; index
++) {
439 BPose
* pose
= PoseAtIndex(specifyingIndex
);
442 result
= B_BAD_INDEX
;
447 new entry_ref(*pose
->TargetModel()->EntryRef()));
454 if (result
== B_OK
) {
455 TrackerSettings settings
;
456 if (!settings
.DontMoveFilesToTrash()) {
457 // move the list we build into trash, don't make the
458 // trashing task select the next item
459 MoveListToTrash(entryList
, false, false);
461 Delete(entryList
, false, settings
.AskBeforeDeleteFile());
463 for (int i
= entryList
->CountItems() - 1; i
>= 0; i
--)
464 delete entryList
->ItemAt(i
);
472 reply
->AddInt32("error", result
);
479 BPoseView::CountProperty(BMessage
*, int32
, const char* property
,
482 bool handled
= false;
483 //PRINT(("BPoseView::CountProperty, %s\n", property));
485 // just return the respecitve counts
486 if (strcmp(property
, kPropertySelection
) == 0) {
487 reply
->AddInt32("result", fSelectionList
->CountItems());
489 } else if (strcmp(property
, kPropertyEntry
) == 0) {
490 reply
->AddInt32("result", fPoseList
->CountItems());
499 BPoseView::GetProperty(BMessage
* specifier
, int32 form
,
500 const char* property
, BMessage
* reply
)
502 // PRINT(("GetProperty %s\n", property));
503 bool handled
= false;
504 status_t result
= B_OK
;
506 if (strcmp(property
, kPropertyPath
) == 0) {
507 if (form
== B_DIRECT_SPECIFIER
) {
509 if (TargetModel() == NULL
)
510 result
= B_NOT_A_DIRECTORY
;
512 reply
->AddRef("result", TargetModel()->EntryRef());
514 } else if (strcmp(property
, kPropertySelection
) == 0) {
515 int32 count
= fSelectionList
->CountItems();
517 case B_DIRECT_SPECIFIER
:
518 // return entries of all poses in selection
519 for (int32 index
= 0; index
< count
; index
++) {
520 reply
->AddRef("result", fSelectionList
->ItemAt(index
)->
521 TargetModel()->EntryRef());
527 case kPreviousSpecifier
:
530 // return entry and index of selected pose before or after
533 if (specifier
->FindRef("data", &ref
) != B_OK
)
537 BPose
* pose
= FindPose(&ref
, &poseIndex
);
540 if (form
== (int32
)kPreviousSpecifier
)
541 pose
= PoseAtIndex(--poseIndex
);
542 else if (form
== (int32
)kNextSpecifier
)
543 pose
= PoseAtIndex(++poseIndex
);
546 result
= B_ENTRY_NOT_FOUND
;
550 if (pose
->IsSelected()) {
551 reply
->AddRef("result",
552 pose
->TargetModel()->EntryRef());
553 reply
->AddInt32("index", IndexOfPose(pose
));
562 } else if (strcmp(property
, kPropertyEntry
) == 0) {
563 int32 count
= fPoseList
->CountItems();
565 case B_DIRECT_SPECIFIER
:
567 // return all entries of all poses in PoseView
568 for (int32 index
= 0; index
< count
; index
++) {
569 reply
->AddRef("result",
570 PoseAtIndex(index
)->TargetModel()->EntryRef());
577 case B_INDEX_SPECIFIER
:
579 // return entry at index
581 if (specifier
->FindInt32("index", &index
) != B_OK
)
584 if (!PoseAtIndex(index
)) {
585 result
= B_BAD_INDEX
;
589 reply
->AddRef("result",
590 PoseAtIndex(index
)->TargetModel()->EntryRef());
596 case kPreviousSpecifier
:
599 // return entry and index of pose before or after
602 if (specifier
->FindRef("data", &ref
) != B_OK
)
606 BPose
* pose
= FindPose(&ref
, form
, &tmp
);
609 result
= B_ENTRY_NOT_FOUND
;
614 reply
->AddRef("result", pose
->TargetModel()->EntryRef());
615 reply
->AddInt32("index", IndexOfPose(pose
));
624 reply
->AddInt32("error", result
);
631 BPoseView::SetProperty(BMessage
* message
, BMessage
*, int32 form
,
632 const char* property
, BMessage
* reply
)
634 status_t result
= B_OK
;
635 bool handled
= false;
637 if (strcmp(property
, kPropertySelection
) == 0) {
641 case B_DIRECT_SPECIFIER
:
645 if (message
->FindInt32("data", 0, &selStart
) == B_OK
646 && message
->FindInt32("data", 1, &selEnd
) == B_OK
) {
647 if (selStart
< 0 || selStart
>= fPoseList
->CountItems()
648 || selEnd
< 0 || selEnd
>= fPoseList
->CountItems()) {
649 result
= B_BAD_INDEX
;
654 SelectPoses(selStart
, selEnd
);
659 case kPreviousSpecifier
:
662 // PRINT(("SetProperty direct/previous/next %s\n", property));
663 // select/unselect poses specified by entries
664 bool clearSelection
= true;
665 for (int32 index
= 0; message
->FindRef("data", index
, &ref
)
668 BPose
* pose
= FindPose(&ref
, form
, &poseIndex
);
671 result
= B_ENTRY_NOT_FOUND
;
676 if (clearSelection
) {
677 // first selected item must call SelectPose so the
678 // selection gets cleared first
679 SelectPose(pose
, poseIndex
);
680 clearSelection
= false;
682 AddPoseToSelection(pose
, poseIndex
);
692 reply
->AddInt32("error", result
);
699 BPoseView::ResolveSpecifier(BMessage
* message
, int32 index
,
700 BMessage
* specifier
, int32 form
, const char* property
)
702 BPropertyInfo
propertyInfo(
703 const_cast<property_info
*>(kPosesPropertyList
));
705 int32 result
= propertyInfo
.FindMatch(message
, index
, specifier
, form
,
708 //PRINT(("FindMatch result %d \n"));
709 return _inherited::ResolveSpecifier(message
, index
, specifier
,
718 BPoseView::FindPose(const entry_ref
* ref
, int32 specifierForm
,
721 // flavor of FindPose, used by previous/next specifiers
723 BPose
* pose
= FindPose(ref
, index
);
725 if (specifierForm
== (int32
)kPreviousSpecifier
)
726 return PoseAtIndex(--*index
);
727 else if (specifierForm
== (int32
)kNextSpecifier
)
728 return PoseAtIndex(++*index
);