ManualGroupDraw.h
// 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 <stdio.h> #include <QtGui/QtGui> #include <ArcSDK.h> #include <Ao/AoControls.h> #include <AxCtl/qt4axctl.h> #include <olb/esridefensesolutions.h> #define ABORT { \ printf ("abort on line %d of %s\n", __LINE__, __FILE__); \ shutdown(); \ } // functions defined in local C++ source files void addTool (IToolbarControlPtr &ipToolbar, const char *name); double dRandom (double low, double high); CComBSTR dsDataPath (const char *relativeDatasetPath); const char *getSIC(); void shutdown(); // the application's main window class ManualGroupDraw : public QWidget { Q_OBJECT QPushButton *m_button; QComboBox *m_comboBox; IMapControl4Ptr m_ipMapControl; IMoleGroupElementPtr m_ipMoleGroup; public slots: void addGroupElement() { // tell the user that we are busy for a few seconds QCursor oldCursor = cursor(); setCursor (Qt::WaitCursor); // pressing this button allows decluttering selections, and we only do it once m_button->setEnabled (false); m_comboBox->setEnabled (true); // tell MOLE to leave it cluttered, for now m_ipMoleGroup.CreateInstance (CLSID_MoleGroupElement); m_ipMoleGroup->put_DeclutterOption (moleDeclutterNone); m_ipMoleGroup->put_EnableDeclutter (false); // generate some elements (vary the number of elements as much as desired) IPointPtr ipPoint (CLSID_Point); IGroupElementPtr ipGroupElement (m_ipMoleGroup); for ( unsigned int i = 0; i < 10; ++i ) { // create a MarkerElement with a MOLE symbol IMoleSymbolPtr ipMoleSymbol (CLSID_MoleMarkerSymbol); ipMoleSymbol->put_SymbolID (CComBSTR(getSIC())); IMarkerElementPtr ipMarkerElement (CLSID_MarkerElement); ipMarkerElement->put_Symbol (IMarkerSymbolPtr(ipMoleSymbol)); IElementPtr ipElement (ipMarkerElement); // add the element to the group at a random clustered location ipPoint->PutCoords (dRandom(-15, 15), dRandom(-15, 15)); ipElement->put_Geometry (IGeometryPtr(ipPoint)); ipGroupElement->AddElement (ipElement); } // add the group to the current map and refresh the display IActiveViewPtr ipActiveView; m_ipMapControl->get_ActiveView (&ipActiveView); if ( ! ipActiveView ) ABORT; IGraphicsContainerPtr ipGraphicsContainer; ipActiveView->get_GraphicsContainer (&ipGraphicsContainer); if ( ! ipGraphicsContainer ) ABORT; ipGraphicsContainer->AddElement (IElementPtr(m_ipMoleGroup), 0); ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); // tell the user that we are no longer busy setCursor (oldCursor); } void declutter (int index) { if ( ! m_comboBox->isEnabled() ) return; // a simple array map for the combo box static const int numDeclutterOptions = 4; static moleDeclutterOptionEnum declutterOptions[numDeclutterOptions] = { moleDeclutterNone, moleDeclutterLeader, moleDeclutterManual, moleDeclutterStack }; // get the selected option from the combo box moleDeclutterOptionEnum currentOption; m_ipMoleGroup->get_DeclutterOption (¤tOption); moleDeclutterOptionEnum newOption = currentOption; if ( index >= 0 && index < numDeclutterOptions ) newOption = declutterOptions[index]; if ( newOption != currentOption ) { // the option has changed - set the new option and recalculate if necessary m_ipMoleGroup->put_DeclutterOption (newOption); if ( newOption != moleDeclutterNone ) m_ipMoleGroup->put_EnableDeclutter (VARIANT_TRUE); else m_ipMoleGroup->put_EnableDeclutter (VARIANT_FALSE); IGroupElementPtr ipGroupElement (m_ipMoleGroup); long elementCount; ipGroupElement->get_ElementCount (&elementCount); if ( newOption == moleDeclutterManual && elementCount > 0 ) { // calculate the decluttered positions manually - in decimal degrees double xStep = 25; double xDeclutter = -0.5 * elementCount * xStep; if ( xDeclutter < -180 ) { // don't fall off the end of the world xStep = 360 / elementCount; xDeclutter = -180 - 0.5 * xStep; } else xDeclutter -= 0.5 * xStep; IPointPtr ipPoint (CLSID_Point); IMoleDeclutterElementPtr ipMoleDeclutterElement (m_ipMoleGroup); for ( long i = 0; i < elementCount; ++i ) { // set a declutter point for each element // these lines of code have no effect in stack or leader mode IElementPtr ipElement; ipGroupElement->get_Element (i, &ipElement); xDeclutter += xStep; ipPoint->PutCoords (xDeclutter, 45); ipMoleDeclutterElement->DeclutterElement (ipElement, IGeometryPtr(ipPoint)); } } // refresh the display IActiveViewPtr ipActiveView; m_ipMapControl->get_ActiveView (&ipActiveView); if ( ! ipActiveView ) ABORT; ipActiveView->PartialRefresh (esriViewGraphics, NULL, NULL); } } public: ManualGroupDraw() { printf ("creating widgets\n"); // create the child widgets of this window QWidget *toolbar = new QWidget (this); m_button = new QPushButton ("Add Group Element", toolbar); m_comboBox = new QComboBox (toolbar); QSplitter *split = new QSplitter (this); QAxCtl *tlbControl = new QAxCtl (AoPROGID_ToolbarControl, toolbar, "Toolbar Control"); QAxCtl *tocControl = new QAxCtl (AoPROGID_TOCControl, split, "TOC Control"); QAxCtl *mapControl = new QAxCtl (AoPROGID_MapControl, split, "Map Control"); // set properties on some of the widgets tlbControl->setMinimumHeight (28); tlbControl->setMaximumHeight (28); split->setOpaqueResize (false); QList<int> sizes (split->sizes()); sizes[0] = 250; sizes[1] = 550; split->setSizes (sizes); m_comboBox->addItem ("No Decluttering"); m_comboBox->addItem ("Leader Decluttering"); m_comboBox->addItem ("Manual Decluttering"); m_comboBox->addItem ("Stack Decluttering"); m_comboBox->setEditable (false); m_comboBox->setEnabled (false); // establish the toolbar layout QHBoxLayout *toolbarLayout = new QHBoxLayout (toolbar); toolbarLayout->setMargin (0); toolbarLayout->addWidget (tlbControl, 1); toolbarLayout->addWidget (m_button); toolbarLayout->addWidget (m_comboBox); // establish the main window layout QVBoxLayout *rootLayout = new QVBoxLayout (this); rootLayout->setSpacing (0); rootLayout->setMargin (0); rootLayout->addWidget (toolbar); rootLayout->addWidget (split, 1); // set properties on this widget and connect event handlers resize (800, 600); setWindowTitle ("MOLE Manual Group Draw"); connect (m_button, SIGNAL(clicked()), SLOT(addGroupElement())); connect (m_comboBox, SIGNAL(currentIndexChanged(int)), SLOT(declutter(int))); printf ("setting up the controls\n"); // extricate the COM interfaces of the ArcGIS controls IUnknownPtr ipUnknown; mapControl->getInterface (&ipUnknown); m_ipMapControl = ipUnknown; if ( ! m_ipMapControl ) ABORT; tlbControl->getInterface (&ipUnknown); IToolbarControlPtr ipToolbarControl (ipUnknown); if ( ! ipToolbarControl ) ABORT; tocControl->getInterface (&ipUnknown); ITOCControlPtr ipTocControl (ipUnknown); if ( ! ipTocControl ) ABORT; // buddy up and load the toolbar ipToolbarControl->SetBuddyControl (m_ipMapControl); ipTocControl->SetBuddyControl (m_ipMapControl); addTool (ipToolbarControl, "ControlsOpenDocCommand"); addTool (ipToolbarControl, "ControlsAddDataCommand"); addTool (ipToolbarControl, "ControlsSaveAsDocCommand"); addTool (ipToolbarControl, "ControlsMapZoomPanTool"); addTool (ipToolbarControl, "ControlsMapFullExtentCommand"); addTool (ipToolbarControl, "ControlsMapZoomToLastExtentBackCommand"); addTool (ipToolbarControl, "ControlsMapZoomToLastExtentForwardCommand"); addTool (ipToolbarControl, "ControlsMapZoomToolControl"); addTool (ipToolbarControl, "ControlsSelectTool"); addTool (ipToolbarControl, "ControlsMapGoToCommand"); addTool (ipToolbarControl, "ControlsMapIdentifyTool"); addTool (ipToolbarControl, "ControlsMapMeasureTool"); printf ("loading the map\n"); // load a default map file CComVariant vUndefined ((long)DISP_E_PARAMNOTFOUND, VT_ERROR); CComBSTR bstmp; m_ipMapControl->LoadMxFile ((bstmp = dsDataPath("Continents/Continents.mxd")), vUndefined, vUndefined); SysFreeString(bstmp); } ~ManualGroupDraw() { printf ("releasing MOLE resources\n"); IMoleCoreHelperPtr ipMoleCoreHelper (CLSID_MoleCoreHelper); ipMoleCoreHelper->ReleaseForceElementRenderer(); } };