Building an ArcGIS Controls map viewer application
MapViewer.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.
// 

  
#include "MapViewer.h"

// Control Interfaces
IToolbarControlPtr g_ipToolbarControl;
IMapControl3Ptr g_ipMapControl;
ITOCControlPtr g_ipTOCControl;
IPageLayoutControlPtr g_ipPageLayoutControl;

// Events
PageLayoutControlEvents* g_pageLayoutEvents;
IEventListenerHelperPtr g_ipPageLayoutControlEventHelper;
TOCControlEvents* g_tocEvents;
IEventListenerHelperPtr g_ipTOCControlEventHelper;
TransformEvents* g_transEvents;
IEventListenerHelperPtr g_ipTransEventHelper;
MapControlEvents* g_mapEvents;
IEventListenerHelperPtr g_ipMapControlEvent2Helper;
CustomizeDialogEvents* g_customizeEvents;
IEventListenerHelperPtr g_ipCustomizeEventHelper;

IToolbarMenuPtr g_ipPopupMenu; 
IFillSymbolPtr g_ipFillSymbol;
IEnvelopePtr g_ipCurrentExtent;
ICustomizeDialogPtr g_ipCustomizeDialog;

AddDateTool* g_dateTool;
GtkWidget *customize_select;

int main (int argc, char* argv[])
{
  // Initialize the engine
  ::AoInitialize(NULL);
  {
    IAoInitializePtr ipInit(CLSID_AoInitialize);
    esriLicenseStatus status;
    ipInit->Initialize(esriLicenseProductCodeEngine, &status);
    if (status != esriLicenseCheckedOut)
      AoExit(0);  
  }

  form_setup(argc, argv);

  create_overview_symbol();

  g_ipTOCControl->put_LabelEdit(esriTOCControlManual);

  // Buddy the toolbar and TOC with the PageLayoutControl
  g_ipToolbarControl->SetBuddyControl(g_ipPageLayoutControl);
  g_ipTOCControl->SetBuddyControl(g_ipPageLayoutControl);

  // Associate the popup menu with the PageLayoutControl
  g_ipPopupMenu.CreateInstance(CLSID_ToolbarMenu);
  g_ipPopupMenu->SetHook(g_ipPageLayoutControl);

  add_popup_items();
  add_toolbar_items();
  create_customize_dialog();

  // Event listening
  g_pageLayoutEvents = new PageLayoutControlEvents();
  g_ipPageLayoutControlEventHelper.CreateInstance(CLSID_PageLayoutControlEventsListener);
  g_ipPageLayoutControlEventHelper->Startup(static_cast<IPageLayoutControlEventsHelper*> (g_pageLayoutEvents));
  g_ipPageLayoutControlEventHelper->AdviseEvents(g_ipPageLayoutControl, NULL);

  g_tocEvents = new TOCControlEvents();
  g_ipTOCControlEventHelper.CreateInstance(CLSID_TOCControlEventsListener);
  g_ipTOCControlEventHelper->Startup(static_cast<ITOCControlEventsHelper*> (g_tocEvents));
  g_ipTOCControlEventHelper->AdviseEvents(g_ipTOCControl, NULL);

  g_transEvents = new TransformEvents();
  g_ipTransEventHelper.CreateInstance(CLSID_TransformEventsListener);
  g_ipTransEventHelper->Startup(static_cast<TransformEvents*> (g_transEvents));

  g_mapEvents = new MapControlEvents();
  g_ipMapControlEvent2Helper.CreateInstance(CLSID_MapControlEvents2Listener);
  g_ipMapControlEvent2Helper->Startup(static_cast<IMapControlEvents2Helper*> (g_mapEvents));
  g_ipMapControlEvent2Helper->AdviseEvents(g_ipMapControl, NULL);
  
  g_customizeEvents = new CustomizeDialogEvents();
  g_ipCustomizeEventHelper.CreateInstance(CLSID_CustomizeDialogEventsListener);
  g_ipCustomizeEventHelper->Startup(static_cast<CustomizeDialogEvents*> (g_customizeEvents));
  LPOLESTR lpszGUID;
  ::StringFromIID(IID_ICustomizeDialogEvents, &lpszGUID);
  IUIDPtr ipUID(CLSID_UID);
  ipUID->put_Value(CComVariant(lpszGUID));
  g_ipCustomizeEventHelper->AdviseEvents(g_ipCustomizeDialog, ipUID);

  load_data();

  // Start the application running
  gtk_main();
}

void form_setup(int argc, char* argv[])
{
  GtkWidget *window;
  GtkWidget *fullapp_vbox, *view_hpane, *tlb_hbox, *toc_vbox;
  GtkWidget *toolbarWidget, *tocWidget, *mapWidget, *pageLayoutWidget;
  HRESULT hr;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_default_size(GTK_WINDOW(window), 600, 500);

  toolbarWidget = gtk_axctl_new(AoPROGID_ToolbarControl);
  tocWidget = gtk_axctl_new(AoPROGID_TOCControl);
  mapWidget = gtk_axctl_new(AoPROGID_MapControl);
  pageLayoutWidget = gtk_axctl_new(AoPROGID_PageLayoutControl);

  customize_select = gtk_toggle_button_new_with_label("Customize");
 
  hr = gtk_axctl_get_interface(toolbarWidget, (IUnknown **)&g_ipToolbarControl); 
  hr = gtk_axctl_get_interface(tocWidget, (IUnknown **)&g_ipTOCControl); 
  hr = gtk_axctl_get_interface(mapWidget, (IUnknown **)&g_ipMapControl); 
  hr = gtk_axctl_get_interface(pageLayoutWidget, (IUnknown **)&g_ipPageLayoutControl);

  gtk_widget_set_size_request(mapWidget, 150, 150);
  gtk_widget_set_size_request(customize_select, 100, 25);
  gtk_widget_set_size_request(toolbarWidget, -1, 25);
  gtk_widget_set_size_request(tocWidget, 100, -1);

  toc_vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(toc_vbox), tocWidget, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(toc_vbox), mapWidget, FALSE, TRUE, 0);

  view_hpane = gtk_hpaned_new();
  gtk_paned_add1(GTK_PANED(view_hpane), toc_vbox);
  gtk_paned_add2(GTK_PANED(view_hpane), pageLayoutWidget);

  tlb_hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(tlb_hbox), toolbarWidget, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(tlb_hbox), customize_select, FALSE, TRUE, 0);

  g_signal_connect(G_OBJECT(customize_select), "clicked",
                   G_CALLBACK(toggle_button_callback), NULL);

  fullapp_vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(fullapp_vbox), tlb_hbox, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(fullapp_vbox), view_hpane, TRUE, TRUE, 0);

  gtk_container_add(GTK_CONTAINER(window), fullapp_vbox);

  g_signal_connect(G_OBJECT(window), "delete_event",
                   G_CALLBACK(delete_event), NULL);
  g_signal_connect(G_OBJECT(window), "destroy",
                   G_CALLBACK(destroy_event), NULL);

  gtk_widget_show_all(window);

  gtk_axctl_initialize_message_queue();
}

static void destroy_event(GtkWidget *widget, gpointer data)
{
  gtk_main_quit();
}

static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
  // Clean up events
  g_ipPageLayoutControlEventHelper->UnadviseEvents();
  g_ipPageLayoutControlEventHelper->Shutdown();
  g_ipPageLayoutControlEventHelper = 0;
  delete g_pageLayoutEvents;
  g_ipTOCControlEventHelper->UnadviseEvents();
  g_ipTOCControlEventHelper->Shutdown();  
  g_ipTOCControlEventHelper = 0;
  delete g_tocEvents;
  g_ipTransEventHelper->UnadviseEvents();
  g_ipTransEventHelper->Shutdown();
  g_ipTransEventHelper = 0;  
  delete g_transEvents;
  g_ipMapControlEvent2Helper->UnadviseEvents();
  g_ipMapControlEvent2Helper->Shutdown();
  g_ipMapControlEvent2Helper = 0;
  delete g_mapEvents;
  g_ipCustomizeEventHelper->UnadviseEvents();
  g_ipCustomizeEventHelper->Shutdown();
  g_ipCustomizeEventHelper = 0;
  delete g_customizeEvents;

  // delete the instance of the tool
  delete g_dateTool;
  
  g_ipPopupMenu = 0;
  g_ipFillSymbol = 0;
  g_ipCurrentExtent = 0;
  g_ipCustomizeDialog = 0;

  g_ipToolbarControl = 0;
  g_ipMapControl = 0;
  g_ipTOCControl = 0;
  g_ipPageLayoutControl = 0;

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

  return FALSE; // must return false to trigger destroy event for window
}

void load_data()
{
  char datapath[1024];
  sprintf(datapath, "%s/Samples/data/GulfOfStLawrence/Gulf_of_St._Lawrence.mxd", getenv("AGSDEVKITJAVA"));
  CComBSTR MX_DATAFILE(datapath);
  VARIANT_BOOL bValidDoc;
  g_ipPageLayoutControl->CheckMxFile(MX_DATAFILE, &bValidDoc);
  if (bValidDoc)
    g_ipPageLayoutControl->LoadMxFile(MX_DATAFILE);
}

void add_toolbar_items()
{
  CComVariant varTool;
  long itemindex;

  if(g_ipToolbarControl == NULL) return;

  varTool = L"esriControlCommands.ControlsOpenDocCommand";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0, 
                              esriCommandStyleIconOnly, &itemindex);

  // Add PageLayout Navigation Commands
  varTool = L"esriControlCommands.ControlsPageZoomInTool";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_TRUE, 0,
                              esriCommandStyleIconOnly, &itemindex);
  varTool = L"esriControlCommands.ControlsPageZoomOutTool";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
                              esriCommandStyleIconOnly, &itemindex);
  varTool = L"esriControlCommands.ControlsPagePanTool";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
                              esriCommandStyleIconOnly, &itemindex);
  varTool = L"esriControlCommands.ControlsPageZoomWholePageCommand";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
                              esriCommandStyleIconOnly, &itemindex);
  varTool = L"esriControlCommands.ControlsPageZoomPageToLastExtentBackCommand";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
                              esriCommandStyleIconOnly, &itemindex);
  varTool = L"esriControlCommands.ControlsPageZoomPageToLastExtentForwardCommand";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
                              esriCommandStyleIconOnly, &itemindex);

  // Add Map Navigation Commands
  varTool = L"esriControlCommands.ControlsMapZoomInTool";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_TRUE, 0,
                              esriCommandStyleIconOnly, &itemindex);
  varTool = L"esriControlCommands.ControlsMapZoomOutTool";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
                              esriCommandStyleIconOnly, &itemindex);
  varTool = L"esriControlCommands.ControlsMapPanTool";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
                              esriCommandStyleIconOnly, &itemindex);
  varTool = L"esriControlCommands.ControlsMapFullExtentCommand";
  g_ipToolbarControl->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
                              esriCommandStyleIconOnly, &itemindex);

  // Add custom date placement command to the tools toolbar
  g_dateTool = new AddDateTool();
  AoToolbarAddTool(g_ipToolbarControl, g_dateTool, esriCommandStyleIconOnly);
}

void add_popup_items()
{
  CComVariant varTool;
  long popupItemIndex;
  
  varTool = L"esriControlCommands.ControlsPageZoomInFixedCommand";
  g_ipPopupMenu->AddItem(varTool, 0, -1, VARIANT_FALSE,
                         esriCommandStyleIconAndText, &popupItemIndex);
  varTool = L"esriControlCommands.ControlsPageZoomOutFixedCommand";
  g_ipPopupMenu->AddItem(varTool, 0, -1, VARIANT_FALSE,
                         esriCommandStyleIconAndText, &popupItemIndex);
  varTool = L"esriControlCommands.ControlsPageZoomWholePageCommand";
  g_ipPopupMenu->AddItem(varTool, 0, -1, VARIANT_FALSE,
                         esriCommandStyleIconAndText, &popupItemIndex);
  varTool = L"esriControlCommands.ControlsPageZoomPageToLastExtentBackCommand";
  g_ipPopupMenu->AddItem(varTool, 0, -1, VARIANT_TRUE,
                         esriCommandStyleIconAndText, &popupItemIndex);
  varTool = L"esriControlCommands.ControlsPageZoomPageToLastExtentForwardCommand";
  g_ipPopupMenu->AddItem(varTool, 0, -1, VARIANT_FALSE, 
                         esriCommandStyleIconAndText, &popupItemIndex);
}

HRESULT create_overview_symbol()
{
  // IRgbColor interface
  IRgbColorPtr ipColor(CLSID_RgbColor);
  ipColor->put_Red(255);
  ipColor->put_Green(0);
  ipColor->put_Blue(0);
  
  // ILine symbol interface
  ILineSymbolPtr ipOutline(CLSID_SimpleLineSymbol);
  ipOutline->put_Width(2);
  ipOutline->put_Color(ipColor);
  
  // IFillSymbol properties
  g_ipFillSymbol.CreateInstance(CLSID_SimpleFillSymbol);
  g_ipFillSymbol->put_Outline(ipOutline);
  ((ISimpleFillSymbolPtr) g_ipFillSymbol)->put_Style(esriSFSHollow);
  
  return S_OK;
}

HRESULT create_customize_dialog()
{
  g_ipCustomizeDialog.CreateInstance(CLSID_CustomizeDialog);
  // Set the title
  g_ipCustomizeDialog->put_DialogTitle(CComBSTR(L"Customize Toolbar Items"));
  // Don't show the "Add From File" Button
  // Adding from file is not an option for your custom C++ Commands. The 
  //   C++ API requires programmatic placement of custom commands onto the 
  //   toolbar control. With the built-in ArcGIS Engine Commands already 
  //   visible in the dialog, nothing needs to be added from file.
  g_ipCustomizeDialog->put_ShowAddFromFile(VARIANT_FALSE);
  // Set the ToolbarControl that the new items will be added to
  g_ipCustomizeDialog->SetDoubleClickDestination(g_ipToolbarControl);
  
  return S_OK;
}

void toggle_button_callback (GtkWidget *widget, gpointer data)
{
  glong hWnd;
  g_ipToolbarControl->get_hWnd(&hWnd);

  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
    g_ipCustomizeDialog->StartDialog(hWnd);
  else
    g_ipCustomizeDialog->CloseDialog();
}