Attribute query selection
AttributeQuery.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.
// 

  

// AttributeQuery.cpp
//
// This sample illustrates how to programatically select features on
// the Map Control using a QueryFilter.  It also illustrates using a
// Motif FileSelectionDialog and MessageDialog.

#include "AttributeQuery.h"

// Global variables
//
// Motif 
Widget g_topLevel;                // application
Widget g_mainWindow;              // main program window
Widget g_mainForm;                // main prog window's form
Widget g_mapWidget;               // map control
Widget g_tocWidget;               // TOC control
Widget g_addLayerWidget;
Widget g_fileSelectionDialog;
Widget g_whereClauseWidget;
Widget g_wcLabel;
Widget g_queryWidget;
XtAppContext g_appContext;
Atom g_wmDeleteWindow;

int main(int argc, char* argv[])
{
  // Interfaces for the Controls
  IMapControl3Ptr ipMapControl;
  ITOCControlPtr ipTOCControl;

  // Initialize the engine
  ::AoInitialize(NULL);
  {
    IAoInitializePtr ipAOinit(CLSID_AoInitialize);
    esriLicenseStatus status;
    ipAOinit->Initialize(esriLicenseProductCodeEngine, &status);
    if (status != esriLicenseCheckedOut)
    {
      std::cerr << "License not available for Engine\n";
      std::cerr << "status is " << status << std::endl;
      ipAOinit->Shutdown();
      ipAOinit = 0;
      ::AoUninitialize();      
      AoExit(0);
    }      
  }

  XtSetLanguageProc(NULL, NULL, NULL);

  // Initialize the Motif toolkit and create the parent widget
  g_topLevel = XtVaAppInitialize(&g_appContext, "XApplication", 
                                 NULL, 0, &argc, argv, NULL, NULL);
  XtVaSetValues(g_topLevel, 
                XmNtitle, "Motif Attribute Query Sample",
                NULL);
  XtResizeWidget(g_topLevel, 999, 800, 1);

  // Create g_mainWindow
  g_mainWindow = XtVaCreateWidget("g_mainWindow", 
                                  xmMainWindowWidgetClass, g_topLevel,
                                  NULL);

  // Create g_mainForm - it will fill the g_mainWindow
  g_mainForm = XtVaCreateWidget("g_mainForm",
                                xmFormWidgetClass,        g_mainWindow,
                                XmNtopAttachment,         XmATTACH_WIDGET,
                                XmNtopWidget,             g_mainWindow,
                                XmNbottomAttachment,      XmATTACH_WIDGET,
                                XmNbottomWidget,          g_mainWindow,
                                XmNleftAttachment,        XmATTACH_WIDGET,
                                XmNleftWidget,            g_mainWindow,
                                XmNrightAttachment,       XmATTACH_WIDGET,
                                XmNrightWidget,           g_mainWindow,
                                XmNfractionBase,          100,
                                NULL);

  //Create button to add a layer
  XmString label;
  label = XmStringCreateLocalized(const_cast<char*>("Add Layer"));
  g_addLayerWidget = XtVaCreateWidget("g_addLayerWidget",
                                      xmPushButtonWidgetClass,   g_mainForm,
                                      XmNlabelString, label,
                                      XmNtopAttachment,   XmATTACH_FORM,
                                      XmNleftAttachment,  XmATTACH_FORM,
                                      XmNheight,          35,
                                      XmNwidth,           200,
                                      NULL);
  XmStringFree(label);
  XtAddCallback(g_addLayerWidget, XmNactivateCallback, processClick, NULL);
  
  // Create a label for the whereclause TextField
  label = XmStringCreateLocalized(const_cast<char*>(" WHERE clause:"));
  g_wcLabel = XtVaCreateWidget("g_wcLabel",
                               xmLabelWidgetClass,   g_mainForm,
                               XmNlabelString, label,
                               XmNtopAttachment,   XmATTACH_FORM,
                               XmNleftAttachment,  XmATTACH_WIDGET,
                               XmNleftWidget,      g_addLayerWidget,
                               XmNheight,          35,
                               XmNwidth,           100,
                               NULL);
  XmStringFree(label);
  
  // Create a button to run the query
  label = XmStringCreateLocalized(const_cast<char*>("Select Features"));
  g_queryWidget = XtVaCreateWidget("g_queryWidget",
                                   xmPushButtonWidgetClass,   g_mainForm,
                                   XmNlabelString, label,
                                   XmNtopAttachment,   XmATTACH_FORM,
                                   XmNtopAttachment,   XmATTACH_FORM,
                                   XmNrightAttachment,   XmATTACH_FORM,
                                   XmNheight,          35,
                                   XmNwidth,           200,
                                   NULL);
  XmStringFree(label);
  
  // Create the TextField for the WHERE clause
  g_whereClauseWidget = XtVaCreateWidget("g_whereClauseWidget",
                                         xmTextFieldWidgetClass,   g_mainForm,
                                         XmNtopAttachment,   XmATTACH_FORM,
                                         XmNleftAttachment,  XmATTACH_WIDGET,
                                         XmNleftWidget,      g_wcLabel,
                                         XmNrightAttachment,  XmATTACH_WIDGET,
                                         XmNrightWidget,      g_queryWidget,
                                         XmNheight,          35,
                                         NULL);

  // Create a FileSelectionDialog with a *.lyr mask
  XmString mask, title;
  Arg args[2];
  mask  = XmStringCreateLocalized(const_cast<char*>("*.lyr"));
  title = XmStringCreateLocalized(const_cast<char*>("Select Layer"));
  XtSetArg(args[0], XmNdirMask, mask);
  XtSetArg(args[1], XmNdialogTitle, title);
  g_fileSelectionDialog = XmCreateFileSelectionDialog(g_mainForm, const_cast<char*>("Select"), args, 2);
  XmStringFree(mask);
  XmStringFree(title);
  
  // Remove the Help button
  Widget remove1 = XmFileSelectionBoxGetChild(g_fileSelectionDialog, XmDIALOG_HELP_BUTTON);
  XtUnmanageChild(remove1);
  
  // TOC Control setup
  g_tocWidget = XtVaCreateWidget("g_tocWidget",
                                 mwCtlWidgetClass,        g_mainForm,
                                 XmNtopAttachment,        XmATTACH_WIDGET,
                                 XmNtopWidget,            g_addLayerWidget,
                                 XmNleftAttachment,       XmATTACH_FORM,
                                 XmNbottomAttachment,     XmATTACH_FORM,
                                 MwNprogID,               AoPROGID_TOCControl,
                                 NULL);
  XtVaSetValues(g_tocWidget, XmNwidth, 200, NULL);
  MwCtlGetInterface(g_tocWidget, (IUnknown**)&ipTOCControl);

  // Map Control setup
  g_mapWidget = XtVaCreateWidget("g_mapWidget",
                                 mwCtlWidgetClass,        g_mainForm,
                                 XmNtopAttachment,        XmATTACH_WIDGET,
                                 XmNtopWidget,            g_whereClauseWidget,
                                 XmNleftAttachment,       XmATTACH_WIDGET,
                                 XmNleftWidget,           g_tocWidget,
                                 XmNrightAttachment,      XmATTACH_FORM,
                                 XmNbottomAttachment,     XmATTACH_FORM,
                                 MwNprogID,               AoPROGID_MapControl,
                                 NULL);
  MwCtlGetInterface(g_mapWidget, (IUnknown**)&ipMapControl);

  // Register callbacks for the file selection dialog and the query now 
  //   that the widgets have been created
  XtAddCallback(g_fileSelectionDialog, XmNokCallback, processFileSelect, (XtPointer) g_mapWidget);
  XtAddCallback(g_fileSelectionDialog, XmNcancelCallback, processFileSelect, (XtPointer) g_mapWidget);
  XtAddCallback(g_queryWidget, XmNactivateCallback, processQuery, (XtPointer) g_mapWidget);

  // Manage the non-parent widgets
  XtManageChild(g_mainWindow);
  XtManageChild(g_mainForm);
  XtManageChild(g_addLayerWidget);
  XtManageChild(g_queryWidget);
  XtManageChild(g_whereClauseWidget);
  XtManageChild(g_wcLabel);
  XtManageChild(g_tocWidget);
  XtManageChild(g_mapWidget);

  // Buddy the TOC with the map
  ipTOCControl->SetBuddyControl(ipMapControl);

  // Structure used to pass data to callback routines
  CloseFormClientDataStruct cfcds;
  cfcds.pMapControl = ipMapControl;
  cfcds.pTOCControl = ipTOCControl;

  // Handle the window manager message that the window is about to be closed 
  g_wmDeleteWindow = XmInternAtom(XtDisplay(g_topLevel), "WM_DELETE_WINDOW", FALSE);
  XmAddWMProtocolCallback(g_topLevel, g_wmDeleteWindow, processClickCloseForm, &cfcds);

  // Realize the container widget
  XtRealizeWidget(g_topLevel);

  XtResizeWidget(g_topLevel, 1000, 800, 1);

  // Turn application control over to the X Toolkit Intrinsics
  MwCtlAppMainLoop(g_appContext);
}

// Function called when WM_DELETE_WINDOW is received (i.e. when the
// user closes the window)
void processClickCloseForm(Widget w, XtPointer client_data, XtPointer call_data)
{
  // To be on the safe side we will make sure the controls are
  // destroyed before uninitializing
  CloseFormClientDataStruct *cfcds = (CloseFormClientDataStruct *) client_data;
  IMapControl3Ptr ipMapControl = cfcds->pMapControl;
  ipMapControl = 0;
  ITOCControlPtr ipTOCControl = cfcds->pTOCControl;
  ipTOCControl = 0;

  // Uninitialize the engine
  {
    IAoInitializePtr ipAOinit(CLSID_AoInitialize);
    ipAOinit->Shutdown();
  }    
  ::AoUninitialize();

  AoExit(0);    
}

// Callback which opens a FileSelectionDialog window to allow the user
// to select a .lyr file to add to the map control and TOC
void processClick(Widget w, XtPointer client_data, XtPointer call_data)
{
  XtManageChild(g_fileSelectionDialog);
}

// Callback to add the .lyr file that the user selected to the map
// control and TOC
void processFileSelect(Widget w, XtPointer client_data, XtPointer call_data)
{
  IMapControl3Ptr ipMapControl;
  MwCtlGetInterface((Widget)client_data, (IUnknown**)&ipMapControl);

  XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data;

  // Kill the dialog if they canceled
  if (cbs->reason == XmCR_CANCEL)
  {
    XtUnmanageChild(g_fileSelectionDialog);
    return;
  }

  // Get the file name and check for errors
  char *fileName = 0;
  if (!XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &fileName))
  {
    XtUnmanageChild(g_fileSelectionDialog);
    return;
  }
  
  if (*fileName)
  {
    // Try to add the layer to the map
    ipMapControl->AddLayerFromFile(CComBSTR(fileName), 0);
      
    // Hide file selection dialog      
    XtUnmanageChild(g_fileSelectionDialog);
  }
  
  XtFree (fileName);
}

// Callback to perform an attribute query based on user input
void processQuery(Widget w, XtPointer client_data, XtPointer call_data)
{
  IMapControl3Ptr ipMapControl;
  MwCtlGetInterface((Widget)client_data, (IUnknown**)&ipMapControl);
    
  // Make sure that a layer has been added
  long layerCount = 0;
  ipMapControl->get_LayerCount(&layerCount);
  if (layerCount < 1)
  {
    ::ShowMessage(g_mainForm, "Error","Please add a feature layer first", true);
    return;
  }
  
  // Just use 1st layer, but make sure it's a featurelayer
  ILayerPtr ipLayer;
  ipMapControl->get_Layer(0, &ipLayer);
  IFeatureSelectionPtr ipFeatSel (ipLayer); // Implicit QI
  if (ipFeatSel == 0)
  {
    ::ShowMessage(g_mainForm, "Error","Please add a feature layer first", true);
    return;
  }

  // Get text
  char *text  = XmTextFieldGetString(g_whereClauseWidget);
  if (strcmp(text, "") != 0)
  {
    // Do a query   
    IQueryFilterPtr ipQF(CLSID_QueryFilter);
    ipQF->put_WhereClause(CComBSTR(text));
    ipFeatSel->SelectFeatures (ipQF, esriSelectionResultNew, VARIANT_FALSE);

    // Do a partial refresh of only ipLayer's selection
    IActiveViewPtr ipActiveView;
    ipMapControl->get_ActiveView(&ipActiveView);    
    ipActiveView->PartialRefresh(esriViewGeoSelection, ipLayer, 0);
    
    XtFree(text);
  }
  else
    ::ShowMessage(g_mainForm, "Error", "Please specify a WHERE clause", true);
}