Arrow key pan
ArrowKeyPan.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.
// 

  
#include "ArrowKeyPan.h"

// Motif Widgets
Widget g_topLevel;                // application
Widget g_mainWindow;              
Widget g_mainForm;   
Widget g_loadDocText;             
Widget g_mapWidget;               
char* g_docName;
char* g_oldTextEntry;

// Control Interfaces
IMapControl3Ptr g_ipMapControl;

MapControlEvents* g_mapEvents;
IEventListenerHelperPtr g_ipMapControlEventHelper;

int main(int argc, char* argv[])
{
  // Initialize the Engine
  ::AoInitialize(NULL);
  {
    IAoInitializePtr ipInit(CLSID_AoInitialize);
    esriLicenseStatus status;
    ipInit->Initialize(esriLicenseProductCodeEngine, &status);
    if (status != esriLicenseCheckedOut)
    {
      std::cerr << "Invalid Licensing." << std::endl;
      AoExit(0);  
    }
  }
  
  XtAppContext app_context;
  SetUpForm(argc, argv, &app_context);

  // Listen for MapControl events
  g_mapEvents = new MapControlEvents();
  g_ipMapControlEventHelper.CreateInstance(CLSID_MapControlEvents2Listener);
  g_ipMapControlEventHelper->Startup(
    static_cast<IMapControlEvents2Helper*> (g_mapEvents));
  g_ipMapControlEventHelper->AdviseEvents(g_ipMapControl, NULL);

  // Allow the MapControl to intercept arrowkeys when it has focus
  g_ipMapControl->put_KeyIntercept(esriKeyInterceptArrowKeys);

  MwCtlAppMainLoop(app_context);
}

// Set up the widgets on the application
void SetUpForm(int argc, char* argv[], XtAppContext* app_context)
{
  XtSetLanguageProc(NULL, NULL, NULL);
  
  // Initialize the Motif toolkit and create the parent widget
  g_topLevel = XtVaAppInitialize(app_context, "XApplication", 
                                 NULL, 0, &argc, argv, NULL, NULL);
  XtVaSetValues(g_topLevel, 
                XmNtitle, "ArrowKeyPan",
                NULL);
  
  // Set the application size by resizing the created widget
  XtResizeWidget(g_topLevel, 640, 480, 1);
  
  g_mainWindow = XtVaCreateWidget("g_mainWindow", 
                                  xmMainWindowWidgetClass, g_topLevel,
                                  NULL);
  
  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);
  
  // LoadDoc button setup
  XmString label = XmStringCreateLocalized("Load Map Document");
  Widget loadDocButton = XtVaCreateWidget("loadDocButton",
                                          xmPushButtonWidgetClass, g_mainForm,
                                          XmNleftAttachment,   XmATTACH_FORM,
                                          XmNtopAttachment,    XmATTACH_FORM,
                                          XmNheight,           35,
                                          XmNwidth,            125,
                                          XmNtopOffset,        5,
                                          XmNleftOffset,       5,
                                          XmNtopOffset,        5,
                                          XmNlabelString,      label,
                                          NULL);
  XmStringFree(label);
  XtAddCallback(loadDocButton, XmNactivateCallback, LoadClick, NULL);

  // loadDoc Text setup
  g_loadDocText = XtVaCreateWidget("loadDocText",
                                   xmTextFieldWidgetClass, g_mainForm,
                                   XmNleftAttachment,    XmATTACH_WIDGET,
                                   XmNleftWidget,          loadDocButton,
                                   XmNrightAttachment,     XmATTACH_FORM,
                                   XmNtopAttachment,       XmATTACH_FORM,
                                   XmNheight,              35,
                                   XmNtopOffset,           5,
                                   XmNrightOffset,         5,
                                   XmNleftOffset,          5,
                                   XmNlabelString,         label,
                                   NULL);
  char datapath[1024];
  sprintf(datapath, "%s/Samples/data/GulfOfStLawrence/Gulf_of_St._Lawrence.mxd", getenv("AGSDEVKITJAVA"));
  XmTextFieldSetString(g_loadDocText, datapath);
  g_docName = XmTextFieldGetString(g_loadDocText);
  g_oldTextEntry = g_docName;
  XtAddCallback(g_loadDocText, XmNfocusCallback, TextMod, NULL);
  XtAddCallback(g_loadDocText, XmNlosingFocusCallback, TextFocus, NULL);

  // directions box setup
  label = XmStringCreateLocalized("Load a map document and then when map has focus use the arrow keys to pan around the map");
  Widget howToUseText = XtVaCreateWidget("howToUseText",
                                         xmLabelWidgetClass,   g_mainForm,
                                         XmNleftAttachment,    XmATTACH_FORM,
                                         XmNrightAttachment,   XmATTACH_FORM,
                                         XmNtopAttachment,     XmATTACH_WIDGET,
                                         XmNtopWidget,         g_loadDocText,
                                         XmNheight,            20,
                                         XmNtopOffset,         5,
                                         XmNlabelString,       label,
                                         NULL);
  XmStringFree(label);

  // MapControl setup
  g_mapWidget = XtVaCreateWidget("g_mapWidget",
                                 mwCtlWidgetClass,        g_mainForm,
                                 XmNleftAttachment,       XmATTACH_FORM,
                                 XmNrightAttachment,      XmATTACH_FORM,
                                 XmNbottomAttachment,     XmATTACH_FORM,
                                 XmNtopAttachment,        XmATTACH_WIDGET,
                                 XmNtopWidget,            howToUseText,
                                 MwNprogID,               AoPROGID_MapControl,
                                 XmNtopOffset,            5,
                                 NULL);
  MwCtlGetInterface(g_mapWidget, (IUnknown**)&g_ipMapControl);
  
  // Manage the non-parent widgets
  XtManageChild(g_mainWindow);
  XtManageChild(g_mainForm);
  XtManageChild(howToUseText);
  XtManageChild(loadDocButton);
  XtManageChild(g_loadDocText);
  XtManageChild(g_mapWidget);

  // Handle the window manager message that the window is about to be closed 
  Atom wm_delete_window = XmInternAtom(XtDisplay(g_topLevel), 
                                       "WM_DELETE_WINDOW", 
                                       FALSE);
  XmAddWMProtocolCallback(g_topLevel, wm_delete_window, 
                          CloseAppCallback, NULL);
  
  // Start the application running 
  XtRealizeWidget(g_topLevel);
}

void LoadClick(Widget w, XtPointer client_data, XtPointer call_data)
{
  HRESULT hr = g_ipMapControl->LoadMxFile(CComBSTR(g_docName));
  if (FAILED(hr))
  {
    std::cerr << "That is not a legal map to load." << std::endl;
    XmTextFieldSetString(g_loadDocText, g_oldTextEntry);
  }

}

void TextMod(Widget w, XtPointer client_data, XtPointer call_data)
{
  g_oldTextEntry = XmTextFieldGetString(w);
}

void TextFocus(Widget w, XtPointer client_data, XtPointer call_data)
{
  g_docName = XmTextFieldGetString(w);
}

// Function called when WM_DELETE_WINDOW protocol is passed
void CloseAppCallback(Widget w, XtPointer client_data, XtPointer call_data)
{
  g_ipMapControl = 0;
  g_mapEvents = 0;
  g_ipMapControlEventHelper = 0;
  
  // Uninitialize the engine
  {
    IAoInitializePtr ipInit(CLSID_AoInitialize);
    ipInit->Shutdown();
  }
  ::AoUninitialize();
  
  AoExit(0);
}