Attribute query selection
MotifUtilities.cpp
// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 

 

// MotifUtilities.cpp

#include "MotifUtilities.h"

// Routine to display a modal prompt with 2 choices to a user.
int ModalPrompt (
  XtAppContext app,
  Widget parent,
  const char* question,
  const char* ans1,
  const char* ans2,
  int default_ans)
{
  static Widget dialog = (Widget) 0; 
  XmString text, yes, no;    
  static int answer;   
  
  if (!dialog) {
    XmString title = XmStringCreateLocalized(const_cast<char*>("Input"));
    dialog = XmCreateQuestionDialog (parent, const_cast<char*>("dialog"), NULL, 0);
    XtVaSetValues (dialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
    XtVaSetValues (dialog, XmNdialogTitle, title, NULL);
    XmStringFree(title);
    XtSetSensitive (XtNameToWidget (dialog, "Help"), False);
    XtAddCallback (dialog, XmNokCallback, ModalPromptCallback, (XtPointer) &answer);
    XtAddCallback (dialog, XmNcancelCallback, ModalPromptCallback, (XtPointer) &answer);
  }               
  
  // Initialize response and dialog
  answer = 0;    
  text = XmStringCreateLocalized (const_cast<char*>(question));    
  yes = XmStringCreateLocalized (const_cast<char*>(ans1));    
  no = XmStringCreateLocalized (const_cast<char*>(ans2));    
  XtVaSetValues (dialog, XmNmessageString, text,        
                 XmNokLabelString, yes,        
                 XmNcancelLabelString, no,        
                 XmNdefaultButtonType, 
                 (default_ans == BUTTON1? XmDIALOG_OK_BUTTON: XmDIALOG_CANCEL_BUTTON),        
                 NULL);    
  
  XmStringFree (text);    
  XmStringFree (yes);    
  XmStringFree (no);    
  
  // Show the prompt and wait for a response  
  XtManageChild (dialog);        
  while (answer == 0)        
    XtAppProcessEvent (app, XtIMAll);    
  
  // Make sure dialog disappears    
  XtUnmanageChild (dialog);   
  XSync (XtDisplay (dialog), 0);    
  XmUpdateDisplay (parent);    
  
  
  return answer;
}

// Callback for ModalPrompt, copies the user's choice into the static
// int answer.
void ModalPromptCallback (Widget widget, XtPointer client_data, XtPointer call_data)
{
  int *answer = (int *) client_data;    
  
  XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;    
  
  if (cbs->reason == XmCR_OK)        
    *answer = BUTTON1;    
  else if (cbs->reason == XmCR_CANCEL)        
    *answer = BUTTON2;
}

// Routine to display a modal text prompt to a user
char *ModalTextPrompt (XtAppContext app, Widget parent, const char* inPrompt, int *outClickedCancel)
{
  static Widget modaltextpromptdialog = (Widget) 0;
  static ModalTextPromptCallDataStruct resp;
  
  if (!modaltextpromptdialog) {
    XmString title = XmStringCreateLocalized(const_cast<char*>("Input"));
    modaltextpromptdialog = XmCreatePromptDialog(parent, const_cast<char*>("prompt"), NULL, 0);
    XtVaSetValues (modaltextpromptdialog,
                   XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
                   XmNdefaultButtonType, XmDIALOG_OK_BUTTON,
                   XmNdialogTitle, title,
                   NULL);
    XmStringFree (title);
    Widget remove1 = XmSelectionBoxGetChild(modaltextpromptdialog, XmDIALOG_HELP_BUTTON);
    XtUnmanageChild(remove1);
    XtAddCallback (modaltextpromptdialog, XmNokCallback, ModalTextPromptCallback, (XtPointer) &resp);
    XtAddCallback (modaltextpromptdialog, XmNcancelCallback, ModalTextPromptCallback, (XtPointer) &resp);
  }    
  
  // Initialize response
  resp.answer = 0;    
  strncpy(resp.strResp, "", 256);
  
  Widget txtwidget = XmSelectionBoxGetChild(modaltextpromptdialog, XmDIALOG_TEXT);
  XmTextSetString(txtwidget, const_cast<char*>(""));
  XmString prompt = XmStringCreateLocalized (const_cast<char*>(inPrompt));    
  XtVaSetValues (modaltextpromptdialog,
                 XmNmessageString, prompt,        
                 XmNselectionLabelString, prompt,
                 NULL);    
  XmStringFree (prompt);    
  
  // Show the prompt and wait for a response
  XtManageChild (modaltextpromptdialog);      
  while (resp.answer == 0)        
    XtAppProcessEvent (app, XtIMAll);    
  
  *outClickedCancel = resp.answer;
  XtUnmanageChild (modaltextpromptdialog);   
  
  // Make sure dialog disappears
  XSync (XtDisplay (modaltextpromptdialog), 0);    
  XmUpdateDisplay (parent);    
  
  return resp.strResp;
}

// Callback for ModalTextPrompt, copies the user's response into the
// static structure used to hold it.
void ModalTextPromptCallback (Widget widget, XtPointer client_data, XtPointer call_data)
{
  ModalTextPromptCallDataStruct *resp = (ModalTextPromptCallDataStruct *) client_data;
  XmSelectionBoxCallbackStruct *cbs = (XmSelectionBoxCallbackStruct *) call_data;
  char *fileName;
  
  if (cbs->reason == XmCR_OK)
  {
    // Get the layer name and check for errors
    if (!XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &fileName))
    {
      cerr << "Internal error in ModalTextPromptCallback\n";
      return;
    }
    strncpy(resp->strResp, fileName, 256);
    XtFree (fileName);
    resp->answer = OK;
  }
  else if (cbs->reason == XmCR_CANCEL)        
    resp->answer = CANCEL;
}

// Routine to display a modal selection dialog to a user and get a response
char *ModalSelectionDialog (
  XtAppContext app,
  Widget parent,
  const char* inPrompt,
  XmString *inItems,
  int inItemCount,
  int *outClickedCancel)
{
  static Widget modalselectiondialog = (Widget) 0;
  static ModalTextPromptCallDataStruct resp;
  
  if (!modalselectiondialog) {
    XmString title = XmStringCreateLocalized(const_cast<char*>("Select"));
    XmString t = XmStringCreateLocalized(const_cast<char*>("Items"));;
    modalselectiondialog = XmCreateSelectionDialog(parent, const_cast<char*>("select"), NULL, 0);
    XtVaSetValues(modalselectiondialog,
                  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
                  XmNdefaultButtonType, XmDIALOG_OK_BUTTON,
                  XmNlistLabelString, t,
                  XmNdialogTitle, title,
                  NULL);
    XmStringFree (title);
    XmStringFree (t);
    Widget remove1 = XmSelectionBoxGetChild(modalselectiondialog, XmDIALOG_HELP_BUTTON);
    XtUnmanageChild(remove1);
    remove1 = XmSelectionBoxGetChild(modalselectiondialog, XmDIALOG_APPLY_BUTTON);
    XtUnmanageChild(remove1);
    XtAddCallback (modalselectiondialog, XmNokCallback, ModalSelectionDialogCallback, (XtPointer) &resp);
    XtAddCallback (modalselectiondialog, XmNcancelCallback, ModalSelectionDialogCallback, (XtPointer) &resp);
    XtAddCallback (modalselectiondialog, XmNnoMatchCallback, ModalSelectionDialogCallback, (XtPointer) &resp);
  }    
  
  // Initialize response
  resp.answer = 0;    
  strncpy(resp.strResp, "", 256);
  
  XmString prompt = XmStringCreateLocalized (const_cast<char*>(inPrompt));    
  XtVaSetValues (modalselectiondialog, XmNmessageString, prompt,        
                 XmNselectionLabelString, prompt,
                 XmNlistItems, inItems,
                 XmNlistItemCount, inItemCount,
                 NULL);    
  XmStringFree (prompt);    
  
  // Show the prompt and wait for a response
  XtManageChild (modalselectiondialog);      
  while (resp.answer == 0)        
    XtAppProcessEvent (app, XtIMAll);    
  
  *outClickedCancel = resp.answer;
  XtUnmanageChild (modalselectiondialog);   
  
  // Make sure dialog disappears
  XSync (XtDisplay (modalselectiondialog), 0);    
  XmUpdateDisplay (parent);    
  
  return resp.strResp;
}

// Callback for ModalTextPrompt, copies the user's response into the
// static structure used to hold it.
void ModalSelectionDialogCallback (Widget widget, XtPointer client_data, XtPointer call_data)
{
  ModalTextPromptCallDataStruct *resp = (ModalTextPromptCallDataStruct *) client_data;
  XmSelectionBoxCallbackStruct *cbs = (XmSelectionBoxCallbackStruct *) call_data;
  char *fileName;
  
  if (cbs->reason == XmCR_OK)
  {
    // Get the layer name and check for errors
    if (!XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &fileName))
    {
      cerr << "Internal error in ModalSelectionDialogCallback\n";
      return;
    }
    strncpy(resp->strResp, fileName, 256);
    XtFree (fileName);
    resp->answer = BUTTON1;
  }
  // Treat cancel and no match the same
  else if (cbs->reason == XmCR_CANCEL || cbs->reason == XmCR_NO_MATCH)        
    resp->answer = BUTTON2;
}

// Routine to display a modal selection dialog to a user and get a response
char *ModalFileSelectionDialog (XtAppContext app, Widget parent, const char* inTitle, const char* inMask, int *outClickedCancel)
{
  static Widget modalfileselectiondialog = (Widget) 0;
  static ModalTextPromptCallDataStruct resp;
  
  if (!modalfileselectiondialog) {
    XmString title = XmStringCreateLocalized(const_cast<char*>(inTitle));
    XmString mask = XmStringCreateLocalized(const_cast<char*>(inMask));
    modalfileselectiondialog = XmCreateFileSelectionDialog(parent, const_cast<char*>("new"), NULL, 0);
    XtVaSetValues(modalfileselectiondialog,
                  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
                  XmNdefaultButtonType, XmDIALOG_OK_BUTTON,
                  XmNdirMask, mask,
                  XmNdialogTitle, title,
                  NULL);
    XmStringFree (title);
    XmStringFree (mask);
    Widget remove1 = XmFileSelectionBoxGetChild(modalfileselectiondialog, XmDIALOG_HELP_BUTTON);
    XtUnmanageChild(remove1);
    XtAddCallback (modalfileselectiondialog, XmNokCallback, ModalFileSelectionDialogCallback, (XtPointer) &resp);
    XtAddCallback (modalfileselectiondialog, XmNcancelCallback, ModalFileSelectionDialogCallback, (XtPointer) &resp);
    XtAddCallback (modalfileselectiondialog, XmNnoMatchCallback, ModalFileSelectionDialogCallback, (XtPointer) &resp);
  }    
  
  // Initialize response
  resp.answer = 0;    
  strncpy(resp.strResp, "", 256);
  
  // Show the prompt and wait for a response
  XtManageChild (modalfileselectiondialog);      
  while (resp.answer == 0)        
    XtAppProcessEvent (app, XtIMAll);    
  
  *outClickedCancel = resp.answer;
  XtUnmanageChild (modalfileselectiondialog);   
  
  // Make sure dialog disappears
  XSync (XtDisplay (modalfileselectiondialog), 0);    
  XmUpdateDisplay (parent);    
  
  return resp.strResp;
}

// Callback for ModalTextPrompt, copies the user's response into the
// static structure used to hold it.
void ModalFileSelectionDialogCallback (Widget widget, XtPointer client_data, XtPointer call_data)
{
  ModalTextPromptCallDataStruct *resp = (ModalTextPromptCallDataStruct *) client_data;
  XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data;
  char *fileName;
  
  if (cbs->reason == XmCR_OK)
  {
    // Get the layer name and check for errors
    if (!XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &fileName))
    {
      cerr << "Internal error in ModalFileSelectionDialogCallback\n";
      return;
    }
    strncpy(resp->strResp, fileName, 256);
    XtFree (fileName);
    resp->answer = BUTTON1;
  }
  // Treat cancel and no match the same
  else if (cbs->reason == XmCR_CANCEL || cbs->reason == XmCR_NO_MATCH)        
    resp->answer = BUTTON2;
}

// Utility function to dispay a MessageDialog
void ShowMessage (Widget parent, const char* dialogtitle, const char* text, bool asError)
{
  // Create a MessageDialog
  Widget err;
  Arg args[1];
  XmString str;
  int n = 0;
  str = XmStringCreateLocalized(const_cast<char*>(text));
  XtSetArg(args[n], XmNmessageString, str);
  n++;

  if (asError)
    err = XmCreateErrorDialog(parent, const_cast<char*>("error"), args, n);
  else 
    err = XmCreateInformationDialog(parent, const_cast<char*>("info"), args, n);

  // Remove the help and cancel buttons
  Widget remove; 
  remove = XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON);
  XtUnmanageChild(remove);
  remove = XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON);
  XtUnmanageChild(remove);
  
  // Set the title of the MessageDialog
  XmString title;
  title = XmStringCreateLocalized(const_cast<char*>(dialogtitle));
  XtVaSetValues(err, XmNdialogTitle, title, NULL);
  XmStringFree(title);
  
  XtManageChild(err);
  XmStringFree(str);
}

// Remove all items from a combobox widget
void ClearCombo(Widget w)
{
  // Delete items from the combobox if any exist
  int itemcount = 0;
  XtVaGetValues(w, XmNitemCount, &itemcount, NULL);
  
  for (int j=1; j<itemcount; j++) 
    XmComboBoxDeletePos(w, 0); 

  if (itemcount > 0) 
    XmComboBoxDeletePos(w, 0);

  XtVaSetValues(w, XmNselectedItem, NULL, NULL);
}

// Removes the item w/ value inItem from the inCombobox and resets its
// textfield. 
void RemovePosition(Widget inCombobox, char* inItem)
{
  XmString searchItem = XmStringCreateLocalized(inItem);
  XmString selectedItem;
  int itemCount;
  XtVaGetValues(inCombobox, XmNitemCount, &itemCount, NULL);
  
  if (itemCount == 1)
  {
    XmComboBoxDeletePos (inCombobox, 0);
  }
  else
  {
    XmStringTable items;
    XtVaGetValues(inCombobox, XmNitems, &items, NULL);
    for (int i=0; i<itemCount; i++)
    {
      if (XmStringCompare(searchItem, items[i]) == True)
      {
        XmComboBoxDeletePos (inCombobox, i+1);
      }
    }
  }
  
  XtVaGetValues(inCombobox, XmNselectedItem, &selectedItem, NULL);
  if (XmStringCompare(searchItem, selectedItem))
    XtVaSetValues(inCombobox, XmNselectedItem, NULL, NULL);
  
  XmStringFree (searchItem);
}

// Method to set the contents of a combobox
void SetComboboxItems (Widget inCombobox, XmString *inItems, int inItemCount)
{
  ::ClearCombo(inCombobox);
  XtVaSetValues(
    inCombobox,
    XmNitems, inItems,
    XmNitemCount, inItemCount,
    NULL);
  
  XmComboBoxUpdate(inCombobox );
}

// Create a menu containing the items specified in items.  Uses the
// global variable mainmenu as the menubar.  mnem can be NULL,
// everything else cannot be (except for items when number == 0).
void CreateMenu (Widget menubar, Widget menu, const char* menuname, char mnem, 
                 MenuItem *items, int number, Widget widgetIDs [])
{
  Widget pushbutton, cascade;
  Arg args[4];
  XmString menulabel;
  int n = 0;
  
  menu = XmCreatePulldownMenu (menubar, const_cast<char*>(menuname), NULL, 0);
  menulabel = XmStringCreateLocalized(const_cast<char*>(menuname));
  XtSetArg (args[n], XmNlabelString, menulabel); n++;
  
  if (mnem)
  {
    XtSetArg (args[n], XmNmnemonic, mnem); n++;
  }
  
  XtSetArg (args[n], XmNsubMenuId, menu); n++;
  cascade = XmCreateCascadeButton (menubar, const_cast<char*>(menuname), args, n);
  XtManageChild (cascade);
  
  XmStringFree(menulabel);
  
  for (int i=0; i<number; i++)
  {
    n = 0;
    XmString accelText;
    if (items[i].accelText)
    {
      accelText = XmStringCreateLocalized(const_cast<char*>(items[i].accelText));
      XtSetArg (args[n], XmNacceleratorText, accelText); n++;
    }
    if (items[i].accel)
    {
      XtSetArg (args[n], XmNaccelerator, items[i].accel); n++;
    }
    
    pushbutton = XmCreatePushButtonGadget (menu, const_cast<char*>(items[i].text), args, n);
    widgetIDs[i] = pushbutton;
    
    if (items[i].accelText)
      XmStringFree(accelText);
    
    if (items[i].callback)
    {
      XtAddCallback(pushbutton, XmNactivateCallback, items[i].callback, items[i].callbackData);
    }
    
    XtManageChild (pushbutton);
  }
}

// Centers the shell of toCenter in centerOver based on the location
// and size of centerOver's top level shell and toCenter's top level
// shell
void CenterDialog (Widget centerOver, Widget toCenter)
{
  Widget topShell = XtParent(centerOver);
  while (topShell && !XtIsWMShell (topShell))
    topShell = XtParent (topShell);  

  Widget dialogShell = XtParent(toCenter);
  while (dialogShell && !XtIsWMShell (dialogShell))
    dialogShell = XtParent (dialogShell);  
  
  Dimension parentW, parentH, dialogW, dialogH;
  Position parentX, parentY, dialogX, dialogY; 
  XtVaGetValues(topShell,
                XmNx, &parentX,
                XmNy, &parentY,
                XmNwidth, &parentW,
                XmNheight, &parentH,      
                NULL);
  XtVaGetValues(dialogShell,
                XmNwidth, &dialogW,
                XmNheight, &dialogH,      
                NULL);
  dialogX = parentX + ((parentW - dialogW) / 2);
  dialogY = parentY + ((parentH - dialogH) / 2);
  XtVaSetValues(dialogShell,
                XmNx, dialogX,
                XmNy, dialogY,
                NULL);
}