From: paulj@gdwest.gd.com (Paul D Johnston)
Newsgroups: comp.windows.x.motif
Subject: Re: Help using TAB to move to next field in ScrolledWindow
Date: 18 Dec 92 17:26:09 GMT
Organization: General Dynamics Corp.

In article <2402@sdrc.COM> jeff.blanchet@sdrc.com writes:
>
>I tried to solve this by changing the TranslationTable on the XmText fields to capture the TAB key press. Great! Now I have control and know which XmText I need to go to next. What I can't figure out when doing this is first how to transfer focus to the next XmText field, and second if the next XmText is out of the viewing area what to do?
>
>Has anyone come across this? How did you solve it? How would you suggest I solve this? Am I going in the right direction?
>

   In order to process keyboard traversals yourself, you will probably need to
create a table (array) containing widget IDs in the order that you want them 
traversed.  Override the translations of the text widgets with a translation
table as follows:

#define TRANSLATION_TABLE       "Shift<Key>Tab: Do_traversal_back()\n\
                                <Key>Tab: Do_traversal_fwd()"

int Num_fields = 0, Current_field = 0;
Widget Text_fields[MAX_NUM_TEXT_WIDGETS];


Add this after the creation of each text widget:

   XtAddCallback(w, XmNactivateCallback, Do_traversal_fwd, NULL);
   XtOverrideTranslations(w, XtParseTranslationTable(TRANSLATION_TABLE));
   XtAddEventHandler(w, ButtonPressMask, True, Set_current_field, Num_fields);
   Text_fields[Num_fields++] = w;

The event handler is used so that when the user selects a text widget in the
traversal list that widget becomes the current one in the list for subsequent
traversals.  The XmNactivateCallback is used to traverse forward in the list
when the activate key (Return) is pressed in the widget.

To actually process the traversals, create functions like:

void Set_current_field(w, field_index, event)
Widget w;
int field_index;                        /* INPUT: index into Text_fields */
XEvent *event;                          /* NOT USED */
{

/* Make sure this event is a ButtonPress. */
   if (event->type != ButtonPress)
      return;

/* Set the current field to be the text widget that received the ButtonPress. */
   Current_field = field_index;

} /* end of Set_current_field */


void Do_traversal_back(w, event, parms, num_parms)
Widget w;
XEvent *event;
String *parms;
Cardinal *num_parms;
{
/*
 * Traverse to the previous widget in the list. If already at the beginning
 * of the list, traverse to the last widget in the list.
 */
   Current_field--;
   if (Current_field < 0)
      Current_field = Num_fields-1;

   XmProcessTraversal(Text_fields[Current_field], XmTRAVERSE_CURRENT);

} /* end of Do_traversal_back */


void Do_traversal_fwd(w, event, parms, num_parms)
Widget w;
XEvent *event;
String *parms;
Cardinal *num_parms;
{
/*
 * Traverse to the next widget in the list. If already at the end of the
 * list, traverse to the first widget in the list.
 */
   Current_field++;
   if (Current_field == Num_fields)
      Current_field = 0;
   XmProcessTraversal(Text_fields[Current_field], XmTRAVERSE_CURRENT);

} /* end of Do_traversal_fwd */


  The XmProcessTraversal function with an argument of XmTRAVERSE_CURRENT is
used to actually force traversal to the specified widget.  This code works,
I'm using it in a piece of software for our customer.

			- Hope this helps,
			  Paul D. Johnston

-- 
==============================================================================
| Paul D. Johnston  paulj@gdwest.gd.com	|  My opinions are not	| 	     |
| GDE Systems, Inc., San Diego, CA.	|  shared by anyone.	| God Rules! |
==============================================================================