1 /* Copyright (c) 1994 FUJITSU LIMITED */
2 /* All Rights Reserved */
5 * $TOG: OutlineListViewMotif.C /main/15 1997/06/18 17:31:56 samborn $
7 * Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
8 * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
9 * States. Use of a copyright notice is precautionary only and does not
10 * imply publication or disclosure.
12 * This software contains confidential information and trade secrets of HaL
13 * Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
14 * withuot the prior express written permission of HaL Computer Systems, Inc.
16 * RESTRICTED RIGHTS LEGEND
17 * Use, duplication, or disclosure by the Government is subject to
18 * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
19 * Technical Data and Computer Software clause at DFARS 252.227-7013.
20 * HaL Computer Systems, Inc.
21 * 1315 Dell Avenue, Campbell, CA 95008
27 #define C_WindowSystem
31 #define C_OutlineElement
35 #define C_OutlineListView
36 #define C_LibraryAgent
43 #define USES_OLIAS_FONT
47 #include "Managers/CatMgr.hh"
48 #include "Registration.hh"
50 #include <WWL/WComposite.h>
51 #include <WWL/WXmScrollBar.h>
55 #include <sys/param.h>
58 #define DEBUGF(X) printf X
64 # define RCS_DEBUG(statement) cerr << statement << endl
66 # define RCS_DEBUG(statement)
69 extern "C" { void _Xm_dump_external(XmString); }
72 XmStringCreateComponent (XmStringComponentType tag, void *data, u_int length);
73 static void register_actions();
75 enum { XmSTRING_COMPONENT_POINTER = XmSTRING_COMPONENT_USER_BEGIN };
78 // /////////////////////////////////////////////////////////////////
80 // /////////////////////////////////////////////////////////////////
82 OutlineListView::OutlineListView (const WComposite &parent, const char *name,
85 : WXmList ((Widget) NULL), f_list (NULL), f_max_level (LEVEL_UNLIMITED),
86 f_current_selection (NULL), f_selected_item_count(0),
87 f_tracking_position (0),
88 f_tracking_element (NULL),
89 f_library_agent (NULL)
91 static serial_number = 1;
93 // Assign a unique serial number to this outline list.
94 f_serial_number = serial_number++;
96 // Non-scrolled list is useless so make it a scrolled list.
97 widget = XmCreateScrolledList (parent, (char *) name, NULL, 0);
100 // if dtinfo_font is defined then get the fontlist for the widget
101 // and append thte dtinfo_font
103 if (window_system().dtinfo_font()) {
104 XmFontList tempFontList, defaultList;
106 // get the current font list and make a copy
107 XtVaGetValues(widget, XmNfontList, &tempFontList, NULL);
108 defaultList = XmFontListCopy(tempFontList);
110 // append the dtinfo font. XmFontListAppendEntry deallocates the original font list after
111 // extracting the required information.
113 defaultList = XmFontListAppendEntry(defaultList, window_system().dtinfo_font());
115 // set the new new font list back
116 XtVaSetValues(widget, XmNfontList, defaultList, NULL);
120 // Save this pointer in user data of widget so that actions can
125 printf (">>> *** shadow %d, margin %d, highlight %d\n",
126 ShadowThickness(), ListMarginWidth(), HighlightThickness());
128 f_margin = ShadowThickness() + ListMarginWidth() + HighlightThickness();
129 f_selection_policy = SelectionPolicy();
133 SetSingleSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
134 SetBrowseSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
135 SetExtendedSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
136 SetMultipleSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
138 SetConvertCallback (this, (WWL_FUN) &OutlineListView::printConvertCallback);
142 SetDefaultActionCallback (this, (WWL_FUN) &OutlineListView::activate);
143 f_tracking_possible = 1;
147 f_tracking_possible = 0;
157 XmFontList defaultList;
158 XtVaGetValues(w, XmNfontList, &defaultList, NULL);
160 // Setup parameters for calculating click position.
162 if (window_system().nofonts())
165 string[0] = OLIAS_PLACEHOLDER_ICON;
167 XmString thing = XmStringCreate (string, OLIAS_FONT);
169 Dimension rval = XmStringWidth(defaultList, thing);
170 XmStringFree (thing);
175 // /////////////////////////////////////////////////////////////////
177 // /////////////////////////////////////////////////////////////////
179 OutlineListView::~OutlineListView()
183 f_data_handle = library_mgr().library().get_data_handle();
188 // /////////////////////////////////////////////////////////////////
189 // xmstring - return the xm string given an outline element
190 // /////////////////////////////////////////////////////////////////
193 OutlineListView::xmstring (OutlineElement *oe, unsigned force, char icon)
195 if (force || (oe->string_creator() != f_serial_number))
197 if (oe->xm_string() != NULL)
198 XmStringFree ((XmString) oe->xm_string());
199 oe->set_xm_string ((void *) create_xm_string (oe, f_base_level,
200 f_tracking_possible, icon));
201 oe->string_creator (f_serial_number);
203 return ((XmString) oe->xm_string());
207 // /////////////////////////////////////////////////////////////////
208 // set_list - set the list
209 // /////////////////////////////////////////////////////////////////
212 OutlineListView::set_list (OutlineList *list, BitHandle handle)
214 // NOTE: Eventually it should be possible to set the list to NULL.
215 if (f_list != NULL && f_list != list )
216 list->free_data_handle (f_data_handle);
220 f_data_handle = handle ;
222 f_data_handle = list->get_data_handle();
223 // Determine the base level.
225 if (list->length() > 0) {
226 // SWM -- need to change this so that when determining
227 // the base level, we check all of the roots...
228 f_base_level = ((OutlineElement *)(*list)[0])->level();
230 ON_DEBUG(printf (">> OutlineList base level = %d\n", f_base_level));
235 // /////////////////////////////////////////////////////////////////
236 // regen_list - regenerate list based on internal list
237 // /////////////////////////////////////////////////////////////////
239 static u_int g_table_index;
242 OutlineListView::regen_list()
244 Xassert (f_list != NULL);
245 // if list is null we should just empty the list.
247 u_int visible_count = f_list->count_expanded (f_data_handle);
249 XmStringTable table = new XmString[visible_count];
250 bool *selected_list = new bool[visible_count];
253 generate_table (f_list, table, selected_list, 0);
257 ItemCount (visible_count, args);
261 delete [] selected_list;
264 // reset tracking position to let dtinfo determine
265 // the new position in track_to()
266 f_tracking_element = NULL;
267 f_tracking_position = 0;
270 // /////////////////////////////////////////////////////////////////
271 // create_outline_string - create the XmString to display
272 // /////////////////////////////////////////////////////////////////
275 OutlineListView::create_xm_string (OutlineElement *oe, int base_level,
276 unsigned char track_on, char icon)
278 XmString string, tmp, next;
280 unsigned char track = track_on ? 1 : 0; // normalize track_on into 1 or 0
282 // First component is pointer to original element. Motif 1.2
283 // will ignore this component.
285 string = XmStringCreateComponent (XmSTRING_COMPONENT_POINTER,
288 // Next component is expand/contract icon, if any.
289 // 1 for tracker, 1 for arrow, 3 for icon and spacing, 1 for terminator
292 assert ((oe->level() - base_level + 6) * sizeof(char) < 64);
293 // Spaces before and including arrow, if any
294 if (window_system().nofonts())
296 memset (s, ' ', oe->level() - base_level + 1 + track);
308 s[0] = OLIAS_PLACEHOLDER_ICON ;
312 memset (p, OLIAS_PLACEHOLDER_ICON, oe->level() - base_level);
314 unsigned int pos = oe->level() - base_level + track;
316 // Only show the icon if this entry has children and
317 // the max level is unlimited or max level is higher than this level.
319 if (oe->has_children() &&
320 (f_max_level == LEVEL_UNLIMITED || f_max_level > oe->level())) {
321 if (oe->is_expanded (f_data_handle))
322 s[pos] = OLIAS_EXPANDED_ICON;
324 s[pos] = OLIAS_CONTRACTED_ICON;
327 s[pos] = OLIAS_NO_CHILDREN_ICON;
329 // Slot for icon -- plug in icon based on element type.
330 char entry_icon = '\0';
332 if (oe->type() == TOC_Element::TOC_ElementClass)
334 UAS_ObjectType type = ((TOC_Element *) oe)->toc()->type();
338 entry_icon = OLIAS_INFOLIB_ICON;
341 entry_icon = OLIAS_INFOBASE_ICON;
344 entry_icon = OLIAS_BOOK_ICON;
351 if (entry_icon != '\0' && !window_system().nofonts())
353 s[oe->level() - base_level + 1 + track] = OLIAS_SPACE04;
354 s[oe->level() - base_level + 2 + track] = entry_icon;
355 s[oe->level() - base_level + 3 + track] = OLIAS_SPACE04;
356 s[oe->level() - base_level + 4 + track] = '\0';
358 else if (window_system().nofonts())
360 s[oe->level() - base_level + 1 + track] = ' ';
361 s[oe->level() - base_level + 2 + track] = '\0';
364 s[oe->level() - base_level + 1 + track] = '\0';
366 next = XmStringCreate (s, OLIAS_FONT);
371 string = XmStringConcat (tmp, next);
378 // Final component is text of item
379 next = XmStringCreateLocalized ((String) oe->display_as());
381 string = XmStringConcat (tmp, next);
384 // _Xm_dump_external (string);
390 // /////////////////////////////////////////////////////////////////
391 // set_icon - set the icon in the xm string (the quick way)
392 // /////////////////////////////////////////////////////////////////
394 // Warning: This routine depends heavily upon the format of the XmString
395 // generated above. Any changes in that string WILL break this routine.
398 OutlineListView::set_icon (OutlineElement *oe)
400 xmstring (oe, 1); // force creation of string
404 // /////////////////////////////////////////////////////////////////
405 // generate_table - generate XmStringTable starting at list
406 // /////////////////////////////////////////////////////////////////
408 // NOTE: Can probably (and should) change g_element to f_element
409 static OutlineElement *g_element;
412 OutlineListView::generate_table (OutlineList *list, XmStringTable &table,
413 bool *selected_list, u_int level, unsigned force)
418 printf ("In generate_table, list = %p, level = %d\n", list, level);
420 for (i = 0; i < list->length(); i++)
422 g_element = ((OutlineElement *)(*list)[i]);
423 // NOTE: temporary for now - calc level in outline list code - DJB
424 // The level can be stored in the list, instead of the element.
425 // Store pointer to list in each element to back tracing.
427 // Level is initialized on first display.
428 // NOTE: This is a temporary hack. 15:59 01/13/93 DJB
429 if (g_element->string_creator() == 0)
430 g_element->level (level);
432 xmstring (g_element, force); // create the string
434 selected_list[g_table_index] = g_element->is_selected (f_data_handle);
435 table[g_table_index++] = (XmString) g_element->xm_string();
437 // g_element->print();
438 if ((g_element->has_children()) &&
439 g_element->is_expanded (f_data_handle))
440 generate_table (g_element->children(), table, selected_list, level+1, force);
445 // /////////////////////////////////////////////////////////////////
446 // XmStringCreateComponent
447 // /////////////////////////////////////////////////////////////////
450 XmStringCreateComponent (XmStringComponentType tag,
451 void *data, u_int length)
453 // NOTE: Possible improvement is to handle greater lengths, but this
454 // is easiest for now. DJB 8-8-92
455 assert (length <= 124);
457 // Length = ASN header + Component header + data
458 unsigned char total_length = 2 + length;
460 XmString string = (XmString) XtMalloc (total_length + 4);
461 unsigned char *p = (unsigned char*) string;
463 // Write the ASN.1 header (values from XmString.c)
469 // Write the component header
473 memcpy (p, data, length);
475 printf ("data = %p\n", data);
478 printf ("XmStringComponent = ");
479 for (i = 0; i < total_length + 4; i++)
480 printf ("%02x ", string[i]);
487 // /////////////////////////////////////////////////////////////////
488 // y_to_outline_element
489 // /////////////////////////////////////////////////////////////////
492 OutlineListView::y_to_outline_element (Position y)
495 // NOTE: if having problems with list expansion items, check here
497 // NOTE: Motif 1.2 bug alert: YToPos returns zero based, instead of 1 based
500 // NOTE: seems to be fixed returning 1 based
502 f_item_pos = YToPos (y) - 1;
505 printf ("Click in item %d, item count = %d\n", f_item_pos, ItemCount());
507 // Another Motif 1.2 bug. YToPos should return 0 for bogus position,
508 // but it doesn't check the range.
509 if (f_item_pos < 0 || f_item_pos >= ItemCount())
512 oe = item_at (f_item_pos);
515 ON_DEBUG(printf ("Found element %p (%s) at pos %d, level %d\n",
516 oe, oe->display_as(), f_item_pos, oe->level()));
519 f_item_pos++; // Adjust for Motif bug here.
524 // /////////////////////////////////////////////////////////////////
526 // /////////////////////////////////////////////////////////////////
529 OutlineListView::icon_extent(OutlineElement *oe) const
531 ON_DEBUG (printf ("horiz sbar value = %d\n",
532 WXmScrollBar(HorizontalScrollBar()).Value()));
533 ON_DEBUG (printf (" extent = %d\n",
534 f_margin - WXmScrollBar(HorizontalScrollBar()).Value() +
535 icon_width(*this) * (oe->level() - f_base_level + 1 + f_tracking_possible)));
537 return (f_margin - WXmScrollBar(HorizontalScrollBar()).Value() +
538 icon_width(*this) * (oe->level() - f_base_level + 1 + f_tracking_possible));
542 // /////////////////////////////////////////////////////////////////
543 // select_start - mouse button pressed (action proc)
544 // /////////////////////////////////////////////////////////////////
547 OutlineListView::_select_start (Widget w, XEvent *event,
548 String *params, Cardinal *num_params)
551 OutlineListView *lv = (OutlineListView *) W.UserData();
554 lv->select_start (w, event, params, num_params);
558 OutlineListView::select_start (Widget w, XEvent *event,
559 String *params, Cardinal *num_params)
561 if (event->type != ButtonPress)
564 ON_DEBUG(printf ("Select start at (%d, %d)\n",
565 event->xbutton.x, event->xbutton.y));
567 f_outline_element = y_to_outline_element (event->xbutton.y);
570 if (f_outline_element)
572 printf (">>> *** shadow %d, margin %d, highlight %d\n",
573 ShadowThickness(), ListMarginWidth(), HighlightThickness());
575 printf ("margin = %d, icon width = %d, level = %d\n",
576 f_margin, icon_width(*this), f_outline_element->level());
579 printf ("No element found at this location\n");
581 // See if item valid and icon was clicked in.
582 ON_DEBUG (printf ("X pos = %d\n", event->xbutton.x));
583 if (f_outline_element && event->xbutton.x < icon_extent (f_outline_element)
584 && f_outline_element->has_children())
586 ON_DEBUG (puts ("Clicked in an icon #1"));
590 // Set variable to signal that icon was not clicked on. This is
591 // checked in the select_end method.
592 f_outline_element = NULL;
594 ON_DEBUG (puts ("Passing through start"));
595 XtCallActionProc (w, "ListBeginSelect", event, params, *num_params);
599 // /////////////////////////////////////////////////////////////////
600 // select_end - mouse button released (action_proc)
601 // /////////////////////////////////////////////////////////////////
604 OutlineListView::_select_end (Widget w, XEvent *event, String *params,
605 Cardinal *num_params)
608 OutlineListView *lv = (OutlineListView *) W.UserData();
611 lv->select_end (w, event, params, num_params);
615 OutlineListView::select_end (Widget w, XEvent *event,
616 String *params, Cardinal *num_params)
618 if (event->type != ButtonRelease)
621 ON_DEBUG (printf ("Select end at (%d, %d)\n",
622 event->xbutton.x, event->xbutton.y));
624 // See if selection ended on the same item and in range.
625 if (f_outline_element != NULL &&
626 (y_to_outline_element (event->xbutton.y) == f_outline_element) &&
627 f_outline_element && event->xbutton.x < icon_extent (f_outline_element)
628 && f_outline_element->has_children() &&
629 (f_max_level == LEVEL_UNLIMITED ||
630 f_max_level > f_outline_element->level()))
632 ON_DEBUG (puts ("Clicked in an icon #2"));
633 unsigned char current_policy = f_selection_policy;
636 // Remove previous tracking, if any.
637 // Must happen before any expand/contract takes place
638 // or either the position will be wrong, or item hidden.
639 if (f_tracking_position > 0)
641 if (window_system().nofonts())
642 set_track_icon (f_tracking_element, f_tracking_position, ' ');
644 set_track_icon (f_tracking_element, f_tracking_position,
645 OLIAS_PLACEHOLDER_ICON);
646 f_tracking_position = 0;
649 if (f_outline_element->is_expanded (f_data_handle))
651 /* -------- Toggle current state to contracted -------- */
652 f_outline_element->set_contracted (f_data_handle);
654 f_outline_element->children()->count_expanded (f_data_handle);
655 DeleteItemsPos (subcount, f_item_pos + 1);
659 /* -------- Toggle current state to expanded -------- */
660 // Turn on the wait cursor if database access to occur.
661 bool wait_state = FALSE;
662 if (!f_outline_element->children_cached())
664 window_system().set_wait_state (WS_ON);
668 f_outline_element->set_expanded (f_data_handle);
670 f_outline_element->children()->count_expanded (f_data_handle);
671 XmStringTable table = new XmString[subcount];
672 bool *selected_list = new bool[subcount];
674 generate_table (f_outline_element->children(),
675 table, selected_list,
676 f_outline_element->level() + 1);
677 AddItemsUnselected (table, subcount, f_item_pos + 1);
678 // Must be in multiple select mode to add selected items
679 if (f_selection_policy != XmMULTIPLE_SELECT)
681 SelectionPolicy (XmMULTIPLE_SELECT);
682 current_policy = XmMULTIPLE_SELECT;
684 // Bogus Motif should have a routine to select multiple items.
686 if (selected_list[--subcount])
687 SelectPos (f_item_pos + subcount + 1, False);
689 delete selected_list;
691 // Turn the wait cursor off if it was on.
693 window_system().set_wait_state (WS_OFF);
696 // Update the icon for new mode
697 set_icon (f_outline_element);
699 // Tell the list about the change
700 XmString item = (XmString) f_outline_element->xm_string();
701 bool selected = PosSelected (f_item_pos);
702 ReplaceItemsPosUnselected (&item, 1, f_item_pos);
704 // YAMB (Yet Another Motif Bug): Cannot call ReplaceItemsPos
705 // because if the item matches another item in the list that
706 // happens to be selected, the item replaced will be selected.
707 // So, do selection here, if needed.
710 // Bugs Galore!! Motif will automatically (gee thanks)
711 // deselect all other selections on a select call, even
712 // if this list is in extended select mode. Work around
713 // by switching to multiple select mode which allows it.
714 if (current_policy != XmMULTIPLE_SELECT)
716 SelectionPolicy (XmMULTIPLE_SELECT);
717 current_policy = XmMULTIPLE_SELECT;
720 // Select it, do not call the select callback.
721 SelectPos (f_item_pos, False);
724 // Update the tracking if activated.
725 // Must happen after the expand/contract so that the track
726 // location is correctly computed.
727 bool scroll = (f_tracking_element == f_outline_element);
728 if (f_tracking_possible && f_library_agent)
729 f_library_agent->track (scroll);
731 // Switch the policy back, if it had been changed.
732 if (f_selection_policy != current_policy)
733 SelectionPolicy (f_selection_policy);
735 // f_outline_element can only be NULL if the click down wasn't in the icon.
736 else if (f_outline_element == NULL)
738 ON_DEBUG (("Passing through end"));
739 XtCallActionProc (w, "ListEndSelect", event, params, *num_params);
743 ON_DEBUG(puts ("Click down in icon, but click up wasn't"));
748 OutlineListView::update_list(OutlineList *list, BitHandle handle)
750 u_int visible_count = list->count_expanded (handle);
752 XmStringTable table = new XmString[visible_count];
753 bool *selected_list = new bool[visible_count];
755 generate_table (list, table, selected_list, 0, 1);
759 ItemCount (visible_count, args);
763 delete selected_list;
766 // /////////////////////////////////////////////////////////////////
768 // /////////////////////////////////////////////////////////////////
771 OutlineListView::register_actions()
773 static bool registered = FALSE;
777 static XtActionsRec actions_list[] =
779 {"OutlineListBeginSelect", OutlineListView::_select_start},
780 {"OutlineListEndSelect", OutlineListView::_select_end},
784 XtAppAddActions (AppContext(), actions_list, XtNumber (actions_list));
787 /**********************************************************************
788 OutputAnAtomName: Translates a target from its internal atom format into
789 a human readable character string.
790 **********************************************************************/
792 OutputAnAtomName(Widget w, Atom target)
794 char *AtomName = (char *)malloc(sizeof(char *) * 34);
796 AtomName = XGetAtomName(XtDisplay(w), target);
797 printf("\t%s\n", AtomName);
800 // /////////////////////////////////////////////////////////////////
801 // /////////////////////////////////////////////////////////////////
804 OutlineListView::printConvertCallback(WCallback *wcb)
806 XmConvertCallbackStruct *ccs = (XmConvertCallbackStruct *)wcb->CallData();
807 Widget w = wcb->GetWidget();
808 unsigned int * selectedPositions;
809 int selectedItemCount;
810 char filepath[MAXPATHLEN];
811 OutlineElement *oe = NULL;
815 Atom FILE_NAME = XInternAtom(XtDisplay(w), XmSFILE_NAME, False);
816 Atom TARGETS = XInternAtom(XtDisplay(w), XmSTARGETS, False);
817 Atom MOTIF_EXPORT_TARGETS = XInternAtom(XtDisplay(w), XmS_MOTIF_EXPORT_TARGETS, False);
819 RCS_DEBUG("printConvertCallback: called.\n");
825 RCS_DEBUG("\nNow in ConvertCallback.\n");
826 RCS_DEBUG("\tSelection: ");
827 OutputAnAtomName((Widget)w, ccs->selection);
828 RCS_DEBUG("\tTarget: ");
829 OutputAnAtomName((Widget)w, ccs->target);
832 * XmeDragSource is going to call ConvertCallback and ask
833 * it to convert MOTIF_EXPORT_TARGETS.
835 if ( (ccs->target == MOTIF_EXPORT_TARGETS) ||
836 (ccs->target == TARGETS))
840 * this callback must support the FILE_NAME transfer
841 * as this is the mechanism the Printer Icon on the
842 * front panel uses to transfer data.
844 Atom *targs = (Atom *) XtMalloc(sizeof(Atom) * 1);
846 ccs->status = XmCONVERT_REFUSE;
851 targs[n] = FILE_NAME; n++;
853 ccs->value = (XtPointer) targs;
857 ccs->status = XmCONVERT_DONE; /* Yes, we converted the target. */
861 * As the drop site supports FILE_NAME as an import target, then
862 * the drop site will ask ConvertCallback to convert the
863 * value to FILE_NAME format.
865 else if (ccs->target == FILE_NAME) {
868 * Get the text from the container
871 XmNselectedPositions, &selectedPositions,
872 XmNselectedItemCount, &selectedItemCount,
875 f_selected_item_count = selectedItemCount;
877 // This is commented out for now until i go and make this function private
879 tmpfile = _DtActGenerateTmpFile(NULL,
881 ( S_IRUSR|S_IRGRP|S_IWUSR|S_IWGRP),
884 strcpy(filepath, getenv("HOME"));
885 strcat(filepath, "/.dt/tmp/file.itp");
889 fprintf(stderr, "printConvertCallback: temp file = %s.\n", filepath);
891 // open the temporary file for writing
893 if ((fp = fopen(filepath, "w")) == NULL) {
894 fprintf(stderr, "Cannot open file %s.\n", filepath);
897 // write out each element in the list
899 for (int i = 0; i < f_selected_item_count; i++) {
900 oe = item_at(selectedPositions[i] - 1) ;
901 TOC_Element *te = (TOC_Element *)oe;
903 // write out the locator
904 if (fputs(((TOC_Element *)te)->toc()->locator(), fp) == EOF) {
905 fprintf(stderr, "Cannot write file %s in current directory.\n", filepath);
910 if (fputs("\n", fp) == EOF) {
911 fprintf(stderr, "Cannot write file %s in current directory.\n", filepath);
920 AppPrintData* p = window_system().GetAppPrintData();
921 p->f_pshell_parent = w;
923 // Assign file name to XmConvertCallbackStruct.
925 ccs->value = (XtPointer)filepath;
926 ccs->type = XA_STRING;
927 ccs->length = strlen(filepath);
929 ccs->status = XmCONVERT_DONE;
933 /* Unexpected target. */
934 ccs->status = XmCONVERT_REFUSE;
938 // /////////////////////////////////////////////////////////////////
939 // select - selection callback
940 // /////////////////////////////////////////////////////////////////
943 OutlineListView::select (WCallback *wcb)
945 XmListCallbackStruct *lcs = (XmListCallbackStruct *) wcb->CallData();
946 XmStringTable items = Items();
947 OutlineElement *oe = NULL;
949 DEBUGF (("**** select: item count = %d, pos = %d, selected = %s\n",
950 lcs->selected_item_count, lcs->item_position,
951 (PosSelected (lcs->item_position) ? "true" : "false")));
953 // DEBUGF ((">>>> SELECTION TYPE <<< %d\n", lcs->selection_type));
955 /* Fix for DTS #6303 -- Removed "if" statement. Always deselect all. */
956 deselect (f_list, DESELECT_ALL);
958 if (f_selection_policy == XmMULTIPLE_SELECT ||
959 f_selection_policy == XmEXTENDED_SELECT)
961 f_selected_item_count = lcs->selected_item_count;
963 printf ("selected # = %d\n", f_selected_item_count);
964 printf (" # = %d\n", SelectedItemCount());
966 for (int i = 0; i < f_selected_item_count; i++)
968 DEBUGF (("M-> extracting at %d\n", lcs->selected_item_positions[i]));
969 oe = item_at(lcs->selected_item_positions[i] - 1) ;
970 oe->set_selected (f_data_handle);
972 // Make the current selection the last item selected. This is
973 // (unfortunately) used by the LibraryAgent for the detach feature.
974 // The reason is that the Document List didn't support these selection
975 // modes until printing was added and could only have one selection.
976 // If there's more than one selection it won't matter because the
977 // Detach button will be insensitive.
978 f_current_selection = oe;
982 if (PosSelected (lcs->item_position))
984 DEBUGF (("--> extracting pointer @ %d\n", lcs->item_position));
985 oe = item_at(lcs->item_position - 1) ;
986 oe->set_selected (f_data_handle);
987 // Save the selection:
988 f_current_selection = oe;
989 f_selected_item_count = 1;
992 if (f_selected_item_count != 1) // 94/10/28 haya
993 f_item_pos = 0; // modify to change sensitive of detach
994 else // button by cursol key.
995 f_item_pos = *lcs->selected_item_positions; //
997 notify (ENTRY_SELECTED);
999 // DISCOURSE: If the list is in extended selection mode it is possible
1000 // for the user to toggle in and out of add mode (cf. Motif Style Guide
1001 // 1.2 pg. 4-6). Unfortunately there's no way for us to know if he is
1002 // in add mode, but that's ok for now, since there's a bug in Motif 1.2
1003 // which deselects the previous selection, even when add mode is on and
1004 // the selection policy is extended select.
1008 // /////////////////////////////////////////////////////////////////
1009 // deselect - turn off select bit in in-memory elements in list
1010 // /////////////////////////////////////////////////////////////////
1012 #define OUTLINE_ELEMENT(I) ((OutlineElement *)(*list)[I])
1015 OutlineListView::deselect (OutlineList *list, deselect_mode_t mode)
1019 for (i = 0; i < list->length(); i++)
1021 OUTLINE_ELEMENT(i)->unset_selected (f_data_handle);
1022 if (OUTLINE_ELEMENT(i)->children_cached() &&
1023 OUTLINE_ELEMENT(i)->has_children() &&
1024 (mode == DESELECT_ALL ||
1025 OUTLINE_ELEMENT(i)->is_expanded (f_data_handle)))
1026 deselect (OUTLINE_ELEMENT(i)->children(), mode);
1031 // /////////////////////////////////////////////////////////////////
1032 // activate - activate callback
1034 // Here's the deal: to get a consistent result for "activate" on any
1035 // entry in the booklist, such expert activation will always** do at
1036 // least an open of the object in the/a reading window. If the item
1037 // also is the parent of a sub-hierarchy of more nodes, the first
1038 // level beneath this object will be expanded [or contracted] in the
1039 // booklist. No expansion will occur, of course, if it is the lowest
1040 // leaf in the tree. A TOC (== a "Book" level) will display its TOC
1041 // page per its OutlineElement type; all other entries will display
1042 // the document or the top-most document in the sub-hierarchy. -jcb
1044 // ** Only if an entry has children and is initially expanded,
1045 // double-click contracts it, but does Not [re-]display its topmost
1046 // document. The assumption is being made that user Contract of a
1047 // hierarchical level is more often than not an expression of lesser
1048 // interest in its content. In many cases, the topmost doc will have
1049 // been previously displayed by a double-click on the entry while
1050 // contracted, anyway.
1052 // Also, the double-click action "selects" only the activated entry.
1053 // /////////////////////////////////////////////////////////////////
1056 OutlineListView::activate (WCallback *wcb)
1058 XmListCallbackStruct *lcs = (XmListCallbackStruct *) wcb->CallData();
1059 XmStringTable items = Items();
1061 int expanded = False;
1063 oe = item_at(lcs->item_position - 1) ;
1066 if( oe == NULL ) printf( "OLV::activate: NULL outline element pointer\n" ) ;
1069 if ( oe->has_children() )
1073 // Remove previous tracking, if any.
1074 // Must happen before any expand/contract takes place
1075 // or either the position will be wrong, or item hidden.
1076 if (f_tracking_position > 0)
1078 if (window_system().nofonts())
1079 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1081 set_track_icon (f_tracking_element, f_tracking_position,
1082 OLIAS_PLACEHOLDER_ICON);
1083 f_tracking_position = 0;
1086 if (oe->is_expanded (f_data_handle))
1090 printf( "OLV::activate: entry is Expanded\n" ) ;
1092 /* -------- Toggle current state to contracted -------- */
1093 oe->set_contracted (f_data_handle);
1095 oe->children()->count_expanded (f_data_handle);
1096 DeleteItemsPos (subcount, lcs->item_position + 1);
1101 printf( "OLV::activate: entry is Not expanded\n" ) ;
1103 /* -------- Toggle current state to expanded -------- */
1104 // Turn on the wait cursor if database access to occur.
1105 bool wait_state = FALSE;
1106 if (!oe->children_cached())
1108 window_system().set_wait_state (WS_ON);
1112 oe->set_expanded (f_data_handle);
1114 oe->children()->count_expanded (f_data_handle);
1115 XmStringTable table = new XmString[subcount];
1116 bool *sel_list = new bool[subcount];
1118 generate_table (oe->children(),
1121 AddItemsUnselected (table, subcount, lcs->item_position + 1);
1125 // Turn the wait cursor off if it was on.
1127 window_system().set_wait_state (WS_OFF);
1130 // Update the icon for new mode
1132 // Tell the list about the change
1133 XmString item = (XmString) oe->xm_string();
1134 ReplaceItemsPosUnselected (&item, 1, lcs->item_position);
1136 // Update the tracking if activated.
1137 // Must happen after the expand/contract so that the track
1138 // location is correctly computed.
1139 bool scroll = (f_tracking_element == oe);
1140 if (f_tracking_possible && f_library_agent)
1141 f_library_agent->track (scroll);
1145 // seems to occur ok for has_children case, above...
1146 deselect (f_list, DESELECT_ALL);
1149 // Select it as the only selection; do not call the select callback.
1150 // Need to reset all class pointers to elements or item pos, regardless
1151 // of traversal method paths in which used by class.
1152 SelectPos (lcs->item_position, True);
1153 oe->set_selected (f_data_handle);
1154 f_current_selection = oe;
1155 f_selected_item_count = 1;
1156 f_item_pos = lcs->item_position;
1158 f_outline_element = NULL; // because it should be with this path
1161 ON_DEBUG(cout << ">>>>>> CALLING DISPLAY ON ELEMENT <<<<<<" << endl);
1163 if ((oe->type() == TOC_Element::TOC_ElementClass) && !expanded)
1166 UAS_ObjectType type = ((TOC_Element *) oe)->toc()->type();
1171 UAS_List<UAS_Common> kids =
1172 ((TOC_Element *)oe)->toc()->children();
1173 if ( (kids != (const int)NULL)
1174 && (kids[0] != (const int)NULL)
1175 && (kids[0]->type() == UAS_BOOKCASE))
1177 UAS_List<UAS_Common> bckids = kids[0]->children();
1178 if (! (bckids[0] == (const int)NULL))
1180 bckids[0]->retrieve();
1188 UAS_List<UAS_Common> kids =
1189 ((TOC_Element *)oe)->toc()->children();
1190 if (! (kids[0] == (const int)NULL))
1192 kids[0]->retrieve();
1199 // let the OutlineElement "display" method handle it.
1206 message_mgr().error_dialog( (char*)UAS_String(CATGETS(
1207 Set_UrlAgent, 5, "Document not found." )) ) ;
1211 else if (oe->type() != TOC_Element::TOC_ElementClass) oe->display();
1215 // /////////////////////////////////////////////////////////////////
1216 // data_handle - return a new data handle
1217 // /////////////////////////////////////////////////////////////////
1221 OutlineListView::data_handle (BitHandle new_handle)
1223 f_data_handle = new_handle;
1224 // Need a variable since routine modifies it.
1226 update_highlighting (f_list, item_pos);
1231 // NOTE: is the calling objects responsibility to make sure that expanded
1232 // flag is correct with the current visual representation
1234 // /////////////////////////////////////////////////////////////////
1235 // update_highlighting
1236 // /////////////////////////////////////////////////////////////////
1240 OutlineListView::update_highlighting_recursive (OutlineList *list,
1243 for (int i = 0; i < list->length(); i++)
1245 // Select it, do not call the select callback.
1246 if (OUTLINE_ELEMENT(i)->is_selected (f_data_handle))
1248 if (!PosSelected(item_pos))
1250 SelectPos (item_pos, False);
1253 DeselectPos(item_pos);
1257 if (OUTLINE_ELEMENT(i)->is_expanded (f_data_handle) &&
1258 OUTLINE_ELEMENT(i)->has_children())
1259 update_highlighting (OUTLINE_ELEMENT(i)->children(), item_pos);
1265 OutlineListView::update_highlighting (OutlineList *list, u_int &item_pos)
1274 // Motif bug - see above.
1275 unsigned char current_policy = f_selection_policy;
1277 if (f_selection_policy != XmMULTIPLE_SELECT)
1279 current_policy = f_selection_policy;
1280 f_selection_policy = XmMULTIPLE_SELECT;
1281 SelectionPolicy (f_selection_policy);
1284 update_highlighting_recursive (list, item_pos);
1286 // Switch the policy back, if it was changed.
1287 if (f_selection_policy != current_policy)
1289 f_selection_policy = current_policy;
1290 SelectionPolicy (f_selection_policy);
1295 // /////////////////////////////////////////////////////////////////
1296 // selected_item_list
1297 // /////////////////////////////////////////////////////////////////
1300 OutlineListView::selected_item_list()
1302 return (f_list->selected_items (f_data_handle));
1306 // /////////////////////////////////////////////////////////////////
1308 // /////////////////////////////////////////////////////////////////
1311 OutlineListView::clear()
1314 deselect(f_list, DESELECT_ALL);
1315 f_selected_item_count = 0;
1318 // /////////////////////////////////////////////////////////////////
1319 // track_to - display tracking icon at specified position
1320 // /////////////////////////////////////////////////////////////////
1323 OutlineListView::track_to (OutlineElement *oe, u_int position, char icon)
1325 // Remove the old tracking icon, if any set.
1326 if (f_tracking_position > 0)
1327 if (window_system().nofonts())
1328 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1330 set_track_icon (f_tracking_element, f_tracking_position,
1331 OLIAS_PLACEHOLDER_ICON);
1333 // Set the new tracking icon.
1334 set_track_icon (oe, position, icon);
1335 f_tracking_position = position;
1336 f_tracking_element = oe;
1341 OutlineListView::untrack()
1343 if (f_tracking_position > 0)
1344 if (window_system().nofonts())
1345 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1347 set_track_icon (f_tracking_element, f_tracking_position,
1348 OLIAS_PLACEHOLDER_ICON);
1350 f_tracking_position = 0;
1354 // Warning: This routine depends heavily upon the format of the XmString
1355 // generated earlier. Any changes in that string WILL break this routine.
1358 OutlineListView::set_track_icon (OutlineElement *oe, u_int position, char icon)
1360 xmstring (oe, 1, icon);
1362 XmStringTable items = Items();
1364 // Tell the list about the change
1365 XmString item = (XmString) oe->xm_string();
1366 bool selected = PosSelected (position);
1367 ReplaceItemsPosUnselected (&item, 1, position);
1370 unsigned char current_policy = f_selection_policy;
1371 if (current_policy != XmMULTIPLE_SELECT)
1373 SelectionPolicy (XmMULTIPLE_SELECT);
1374 current_policy = XmMULTIPLE_SELECT;
1377 // Select it, do not call the select callback.
1378 SelectPos (position, False);
1379 // Switch the policy back, if it had been changed.
1380 if (f_selection_policy != current_policy)
1381 SelectionPolicy (f_selection_policy);
1385 // OutlineListView::item_at(position)
1387 // return the OutlineElement that is visible at 'position' in
1392 OutlineListView::item_at(unsigned int position)
1394 OutlineList *lptr = f_list ;
1395 unsigned int count = 0 ;
1396 unsigned int offset = 0 ;
1398 ON_DEBUG(cerr << "item_at: " << position << endl);
1400 // start at the beginning and descend the nested lists until we
1401 // reach the desired position, and return the element there
1403 OutlineElement *element = (OutlineElement *) (*lptr)[offset] ;
1404 while (count < position)
1406 if (element->is_expanded(f_data_handle) && element->has_children())
1408 if (count + element->children()->count_expanded(f_data_handle) >= position)
1410 ON_DEBUG(cerr << "descend: " << element->display_as() << endl);
1411 lptr = element->children();
1416 count += element->children()->count_expanded(f_data_handle) ;
1422 offset++ ; // go to the next one
1424 element = (OutlineElement*) (*lptr)[offset] ;
1427 ON_DEBUG(cerr << "item_at ==> " << element->display_as() << endl);