Add feature layer
AddFeatureLayer.cpp
// Copyright 2011 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.
// 

  

// AddFeatureLayer.cpp
//
// This sample shows how to programmatically add and delete layers
// from a MapControl

#include "AddFeatureLayer.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_toolbarWidget;           // toolbar control
Widget g_addLayerWidget;
Widget g_removeLayerWidget;
Widget g_fileSelectionDialog;  
Widget g_selectionDialog;
XtAppContext g_appContext;
Atom g_wmDeleteWindow;

int main(int argc, char* argv[])
{
  // Interfaces for the controls
  IMapControl3Ptr ipMapControl;
  IToolbarControlPtr ipToolbarControl;
  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);
    }      
  }

  // Initialize the Motif toolkit and create the parent widget
  XtSetLanguageProc(NULL, NULL, NULL);
  g_topLevel = XtVaAppInitialize(
    &g_appContext,
    "XApplication",
    NULL,
    0,
    &argc,
    argv,
    NULL,
    NULL);
  XtVaSetValues(
    g_topLevel,
    XmNtitle,
    "Add Feature Layer Motif Example",
    NULL);
  XtResizeWidget(g_topLevel, 999, 800, 1);

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

  // Create g_mainForm - it will fill 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 add button
  XmString label;
  label = XmStringCreateLocalized(const_cast<char*>("Add Feature Layer"));
  g_addLayerWidget = XtVaCreateWidget(
    "g_addLayerWidget",
    xmPushButtonWidgetClass,   g_mainForm,
    XmNlabelString,      label,
    XmNtopAttachment,          XmATTACH_FORM,
    XmNleftAttachment,         XmATTACH_FORM,
    XmNheight,                 40,
    XmNwidth,                  200,
    NULL);
  XmStringFree(label);
    
  //Create remove button
  label = XmStringCreateLocalized(const_cast<char*>("Remove Feature Layer"));
  g_removeLayerWidget = XtVaCreateWidget(
    "g_removeLayerWidget",
    xmPushButtonWidgetClass,   g_mainForm,
    XmNlabelString,            label,
    XmNtopAttachment,          XmATTACH_FORM,
    XmNleftAttachment,         XmATTACH_WIDGET,
    XmNleftWidget,             g_addLayerWidget,
    XmNheight,                 40,
    XmNwidth,                  200,
    NULL);
  XmStringFree(label);

  // 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);

  // Create a selection dialog (used when removing layers)
  label = XmStringCreateLocalized(const_cast<char*>("Layers"));
  title = XmStringCreateLocalized(const_cast<char*>("Select Layer"));
  g_selectionDialog = XmCreateSelectionDialog(g_mainForm, const_cast<char*>("selection"), NULL, 0);
  XtVaSetValues(
    g_selectionDialog,
    XmNlistLabelString, label,
    XmNdialogTitle, title,
    XmNmustMatch, True,
    NULL);
  XmStringFree(label);
  XmStringFree(title);    
  // Remove the Help and Apply buttons
  remove1 = XmSelectionBoxGetChild(g_selectionDialog, XmDIALOG_HELP_BUTTON);
  XtUnmanageChild(remove1);
  remove1 = XmSelectionBoxGetChild(g_selectionDialog, XmDIALOG_APPLY_BUTTON);
  XtUnmanageChild(remove1);

  // Set up callbacks which don't need widgets created
  XtAddCallback(g_addLayerWidget, XmNactivateCallback, processClickAdd, NULL);

  // Toolbar Control setup 
  g_toolbarWidget = XtVaCreateWidget(
    "g_toolbarWidget",
    mwCtlWidgetClass,     g_mainForm,
    XmNtopAttachment,     XmATTACH_WIDGET,
    XmNtopWidget,     g_addLayerWidget,
    XmNrightAttachment,   XmATTACH_FORM,
    XmNleftAttachment,    XmATTACH_FORM,
    MwNprogID,          AoPROGID_ToolbarControl,
    NULL);
  XtVaSetValues(g_toolbarWidget, XmNheight, 25, NULL);
  MwCtlGetInterface(g_toolbarWidget, (IUnknown**)&ipToolbarControl);
  
  // TOC Control setup
  g_tocWidget = XtVaCreateWidget(
    "g_tocWidget",
    mwCtlWidgetClass,        g_mainForm,
    XmNtopAttachment,        XmATTACH_WIDGET,
    XmNtopWidget,            g_toolbarWidget,
    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_toolbarWidget,
    XmNleftAttachment,       XmATTACH_WIDGET,
    XmNleftWidget,           g_tocWidget,
    XmNrightAttachment,      XmATTACH_FORM,
    XmNbottomAttachment,     XmATTACH_FORM,
    MwNprogID,               AoPROGID_MapControl,
    NULL);
  MwCtlGetInterface(g_mapWidget, (IUnknown**)&ipMapControl);

  // Set up callbacks that need the widget to have been created
  XtAddCallback(g_removeLayerWidget, XmNactivateCallback, processClickRemove, (XtPointer) g_mapWidget);
  XtAddCallback(g_fileSelectionDialog, XmNokCallback, processFileSelect, (XtPointer) g_mapWidget);
  XtAddCallback(g_fileSelectionDialog, XmNcancelCallback, processFileSelect, (XtPointer) g_mapWidget);
  XtAddCallback(g_selectionDialog, XmNokCallback, processSelect, (XtPointer) g_mapWidget);
  XtAddCallback(g_selectionDialog, XmNcancelCallback, processSelect, (XtPointer ) g_mapWidget);


  // Manage the non-parent widgets
  XtManageChild(g_mainWindow);
  XtManageChild(g_mainForm);
  XtManageChild(g_addLayerWidget);
  XtManageChild(g_removeLayerWidget);
  XtManageChild(g_toolbarWidget);
  XtManageChild(g_tocWidget);
  XtManageChild(g_mapWidget);

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

  // Add tools to toolbar
  ::AddStandardToolbarItems(ipToolbarControl);

  // Structure used to pass data to callback routines
  CloseFormClientDataStruct cfcds;
  cfcds.pMapControl = ipMapControl;
  cfcds.pToolbarControl = ipToolbarControl;
  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;
  IToolbarControlPtr ipToolbarControl (cfcds->pToolbarControl);
  ipToolbarControl = 0;
  ITOCControlPtr ipTOCControl (cfcds->pTOCControl);
  ipTOCControl = 0;

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

  AoExit(0);
}

// Open a FileSelectionDialog window to allow the user to select a
// .lyr file to add to the map control and TOC.  The
// FileSelectionDialog has already been created, so all we need to do
// here is show it.
void processClickAdd(Widget w, XtPointer client_data, XtPointer call_data)
{
  XtManageChild(g_fileSelectionDialog);
}

// Show a SelectionDialog with the names of all layers currently in
// the map.  The SelectionDialog has already been created, so all we
// need to do here is update the items in its internal list and show
// it.  This method also shows how to use the ::AoFreeBSTR() SDK call
// and to this end bsLayerName is declared as a BSTR.  Normally
// bsLayerName would be declared as a CComBSTR (so that it's memory
// managment would occur automatically).  See the function
// GetIndexOfLayerName for an example of using a CComBSTR.
void processClickRemove(Widget w, XtPointer client_data, XtPointer call_data)
{
  USES_CONVERSION;
  
  IMapControl3Ptr ipMapControl;
  MwCtlGetInterface((Widget)client_data, (IUnknown**)&ipMapControl);

  BSTR bsLayerName; // Ordinarily would be a CComBSTR
  ILayerPtr ipLayer;
  long numLayers;
  XmString *str;
    
  ipMapControl->get_LayerCount(&numLayers);
  str = (XmString *) XtMalloc(numLayers * sizeof(XmString));

  // Add the map's layer names to a list
  for (long i=0; i<numLayers; i++)
  {
    ipMapControl->get_Layer(i, &ipLayer);
    ipLayer->get_Name(&bsLayerName);
    ::AoFreeBSTR(bsLayerName); // remember to free the BSTR that was returned
    str[i] = XmStringCreateLocalized(OLE2A(bsLayerName));
  }

  // Set the list of the SelectionDialog
  XtVaSetValues(g_selectionDialog,
                XmNlistItems, str,
                XmNlistItemCount, static_cast<int>(numLayers),
                NULL);
    
  // Clean up
  for (long i=0; i<numLayers; i++)
    XmStringFree(str[i]);
  XtFree((char *)str);

  XtManageChild(g_selectionDialog);
}

// Removes the layer with the name selected in the selectiondialog
// from the map
void processSelect(Widget w, XtPointer client_data, XtPointer call_data)
{
  IMapControl3Ptr ipMapControl;
  MwCtlGetInterface((Widget)client_data, (IUnknown**)&ipMapControl);
  XmSelectionBoxCallbackStruct *cbs = (XmSelectionBoxCallbackStruct *)call_data;

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

  // Get the layer name and check for errors
  char *layerName = 0;
  if (!XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &layerName))
  {
    XtUnmanageChild(g_selectionDialog);
    return;
  }

  long index = ::GetIndexOfLayerName(ipMapControl, layerName);
  if (index != -1)
    ipMapControl->DeleteLayer(index);

  XtFree (layerName);    
  XtUnmanageChild(g_selectionDialog);
}

// 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;
  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);
  return;
}