RemoteDrawingEngine: Reduce RP_READ_BITMAP result timeout.
[haiku.git] / src / kits / tracker / PoseViewScripting.cpp
blob04b98fce029c659cde27567bb169d868faeee13d
1 /*
2 Open Tracker License
4 Terms and Conditions
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.
32 All rights reserved.
35 // PoseView scripting interface
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
41 #include <ByteOrder.h>
42 #include <Debug.h>
43 #include <Message.h>
44 #include <PropertyInfo.h>
46 #include "Tracker.h"
47 #include "PoseView.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
57 // is arbitrary.
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.
66 #if 0
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
81 #endif
83 // ToDo:
84 // access list view column state
85 // access poses
86 // - pose location
87 // - pose text widgets
90 const property_info kPosesPropertyList[] = {
91 { kPropertyPath,
92 { B_GET_PROPERTY },
93 { B_DIRECT_SPECIFIER },
94 "get Path of ... # returns the path of a Tracker window, "
95 "error if no path associated",
97 { B_REF_TYPE },
98 {},
101 { kPropertyEntry,
102 { B_COUNT_PROPERTIES },
103 { B_DIRECT_SPECIFIER },
104 "count Entry of ... # count entries in a PoseView",
106 { B_INT32_TYPE },
110 { kPropertyEntry,
111 { B_DELETE_PROPERTY },
112 { B_ENTRY_SPECIFIER, B_INDEX_SPECIFIER },
113 "delete Entry {path|index} # deletes specified entries in a PoseView",
119 { kPropertyEntry,
120 { B_GET_PROPERTY },
121 { B_DIRECT_SPECIFIER, B_INDEX_SPECIFIER, kPreviousSpecifier,
122 kNextSpecifier },
123 "get Entry [next|previous|index] # returns specified entries",
125 { B_REF_TYPE },
129 { kPropertyEntry,
130 { B_EXECUTE_PROPERTY },
131 { B_ENTRY_SPECIFIER, B_INDEX_SPECIFIER },
132 "execute Entry {path|index} # opens specified entries",
134 { B_REF_TYPE },
138 { kPropertySelection,
139 { B_GET_PROPERTY },
140 { B_DIRECT_SPECIFIER, kPreviousSpecifier, kNextSpecifier },
141 "get Selection [next|previous] # returns the selected entries",
143 { B_REF_TYPE },
147 { kPropertySelection,
148 { B_SET_PROPERTY },
149 { B_DIRECT_SPECIFIER, kPreviousSpecifier, kNextSpecifier },
150 "set Selection of ... to {next|previous|entry} # selects specified "
151 "entries",
157 { kPropertySelection,
158 { B_COUNT_PROPERTIES },
159 { B_DIRECT_SPECIFIER },
160 "count Selection of ... # counts selected items",
162 { B_INT32_TYPE },
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",
187 { 0 }
191 status_t
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);
203 bool
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) {
212 return false;
215 // dispatch scripting messages
216 BMessage reply(B_REPLY);
217 const char* property = 0;
218 bool handled = false;
220 int32 index = 0;
221 int32 form = 0;
222 BMessage specifier;
223 status_t result = message->GetCurrentSpecifier(&index, &specifier,
224 &form, &property);
226 if (result != B_OK || index == -1)
227 return false;
229 ASSERT(property != NULL);
231 switch (message->what) {
232 case B_CREATE_PROPERTY:
233 handled = CreateProperty(message, &specifier, form, property,
234 &reply);
235 break;
237 case B_GET_PROPERTY:
238 handled = GetProperty(&specifier, form, property, &reply);
239 break;
241 case B_SET_PROPERTY:
242 handled = SetProperty(message, &specifier, form, property,
243 &reply);
244 break;
246 case B_COUNT_PROPERTIES:
247 handled = CountProperty(&specifier, form, property, &reply);
248 break;
250 case B_DELETE_PROPERTY:
251 handled = DeleteProperty(&specifier, form, property, &reply);
252 break;
254 case B_EXECUTE_PROPERTY:
255 handled = ExecuteProperty(&specifier, form, property, &reply);
256 break;
259 if (handled) {
260 // done handling message, send a reply
261 message->SendReply(&reply);
264 return handled;
268 bool
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
279 entry_ref ref;
280 for (int32 index = 0; specifier->FindRef("refs", index, &ref)
281 == B_OK; index++)
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);
290 if (pose == NULL) {
291 result = B_ENTRY_NOT_FOUND;
292 break;
295 launchMessage.AddRef("refs", pose->TargetModel()->EntryRef());
297 } else
298 return false;
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);
308 handled = true;
311 if (result != B_OK)
312 reply->AddInt32("error", result);
314 return handled;
318 bool
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
329 return false;
331 // items to add to a selection may be passed as refs or as indices
332 if (specifier->HasRef("data")) {
333 entry_ref ref;
334 // select poses specified by entries
335 for (int32 index = 0; specifier->FindRef("data", index, &ref)
336 == B_OK; index++) {
337 int32 poseIndex;
338 BPose* pose = FindPose(&ref, form, &poseIndex);
340 if (pose == NULL) {
341 result = B_ENTRY_NOT_FOUND;
342 handled = true;
343 break;
346 AddPoseToSelection(pose, poseIndex);
348 handled = true;
349 } else {
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);
355 if (pose == NULL) {
356 result = B_BAD_INDEX;
357 handled = true;
358 break;
361 AddPoseToSelection(pose, specifyingIndex);
363 handled = true;
367 if (result != B_OK)
368 reply->AddInt32("error", result);
370 return handled;
374 bool
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) {
386 entry_ref ref;
387 // select poses specified by entries
388 for (int32 index = 0; specifier->FindRef("refs", index, &ref)
389 == B_OK; index++) {
390 int32 poseIndex;
391 BPose* pose = FindPose(&ref, form, &poseIndex);
393 if (pose == NULL) {
394 result = B_ENTRY_NOT_FOUND;
395 break;
398 RemovePoseFromSelection(pose);
400 handled = true;
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);
409 if (pose == NULL) {
410 result = B_BAD_INDEX;
411 break;
414 RemovePoseFromSelection(pose);
416 handled = true;
417 } else
418 return false;
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
429 entry_ref ref;
430 for (int32 index = 0; specifier->FindRef("refs", index, &ref)
431 == B_OK; index++) {
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);
441 if (pose == NULL) {
442 result = B_BAD_INDEX;
443 break;
446 entryList->AddItem(
447 new entry_ref(*pose->TargetModel()->EntryRef()));
449 } else {
450 delete entryList;
451 return false;
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);
460 } else
461 Delete(entryList, false, settings.AskBeforeDeleteFile());
462 } else {
463 for (int i = entryList->CountItems() - 1; i >= 0; i--)
464 delete entryList->ItemAt(i);
465 delete entryList;
468 handled = true;
471 if (result != B_OK)
472 reply->AddInt32("error", result);
474 return handled;
478 bool
479 BPoseView::CountProperty(BMessage*, int32, const char* property,
480 BMessage* reply)
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());
488 handled = true;
489 } else if (strcmp(property, kPropertyEntry) == 0) {
490 reply->AddInt32("result", fPoseList->CountItems());
491 handled = true;
494 return handled;
498 bool
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) {
508 handled = true;
509 if (TargetModel() == NULL)
510 result = B_NOT_A_DIRECTORY;
511 else
512 reply->AddRef("result", TargetModel()->EntryRef());
514 } else if (strcmp(property, kPropertySelection) == 0) {
515 int32 count = fSelectionList->CountItems();
516 switch (form) {
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());
524 handled = true;
525 break;
527 case kPreviousSpecifier:
528 case kNextSpecifier:
530 // return entry and index of selected pose before or after
531 // specified pose
532 entry_ref ref;
533 if (specifier->FindRef("data", &ref) != B_OK)
534 break;
536 int32 poseIndex;
537 BPose* pose = FindPose(&ref, &poseIndex);
539 for (;;) {
540 if (form == (int32)kPreviousSpecifier)
541 pose = PoseAtIndex(--poseIndex);
542 else if (form == (int32)kNextSpecifier)
543 pose = PoseAtIndex(++poseIndex);
545 if (pose == NULL) {
546 result = B_ENTRY_NOT_FOUND;
547 break;
550 if (pose->IsSelected()) {
551 reply->AddRef("result",
552 pose->TargetModel()->EntryRef());
553 reply->AddInt32("index", IndexOfPose(pose));
554 break;
558 handled = true;
559 break;
562 } else if (strcmp(property, kPropertyEntry) == 0) {
563 int32 count = fPoseList->CountItems();
564 switch (form) {
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());
573 handled = true;
574 break;
577 case B_INDEX_SPECIFIER:
579 // return entry at index
580 int32 index;
581 if (specifier->FindInt32("index", &index) != B_OK)
582 break;
584 if (!PoseAtIndex(index)) {
585 result = B_BAD_INDEX;
586 handled = true;
587 break;
589 reply->AddRef("result",
590 PoseAtIndex(index)->TargetModel()->EntryRef());
592 handled = true;
593 break;
596 case kPreviousSpecifier:
597 case kNextSpecifier:
599 // return entry and index of pose before or after
600 // specified pose
601 entry_ref ref;
602 if (specifier->FindRef("data", &ref) != B_OK)
603 break;
605 int32 tmp;
606 BPose* pose = FindPose(&ref, form, &tmp);
608 if (pose == NULL) {
609 result = B_ENTRY_NOT_FOUND;
610 handled = true;
611 break;
614 reply->AddRef("result", pose->TargetModel()->EntryRef());
615 reply->AddInt32("index", IndexOfPose(pose));
617 handled = true;
618 break;
623 if (result != B_OK)
624 reply->AddInt32("error", result);
626 return handled;
630 bool
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) {
638 entry_ref ref;
640 switch (form) {
641 case B_DIRECT_SPECIFIER:
643 int32 selStart;
644 int32 selEnd;
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;
650 handled = true;
651 break;
654 SelectPoses(selStart, selEnd);
655 handled = true;
656 break;
658 } // fall thru
659 case kPreviousSpecifier:
660 case kNextSpecifier:
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)
666 == B_OK; index++) {
667 int32 poseIndex;
668 BPose* pose = FindPose(&ref, form, &poseIndex);
670 if (pose == NULL) {
671 result = B_ENTRY_NOT_FOUND;
672 handled = true;
673 break;
676 if (clearSelection) {
677 // first selected item must call SelectPose so the
678 // selection gets cleared first
679 SelectPose(pose, poseIndex);
680 clearSelection = false;
681 } else
682 AddPoseToSelection(pose, poseIndex);
684 handled = true;
686 break;
691 if (result != B_OK)
692 reply->AddInt32("error", result);
694 return handled;
698 BHandler*
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,
706 property);
707 if (result < 0) {
708 //PRINT(("FindMatch result %d \n"));
709 return _inherited::ResolveSpecifier(message, index, specifier,
710 form, property);
713 return this;
717 BPose*
718 BPoseView::FindPose(const entry_ref* ref, int32 specifierForm,
719 int32* index) const
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);
729 else
730 return pose;