Generate, update, and display diagrams within ArcGIS Server Schematics
ArcGIS_Schematics_ServingDiagrams_VBNet\App_Code\SchematicCommands.vb
' 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.
' 

Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports esriWebControls = ESRI.ArcGIS.ADF.Web.UI.WebControls
Imports ESRI.ArcGIS.ADF.Web.UI.WebControls
Imports ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools
Imports esriAgsServer = ESRI.ArcGIS.ADF.ArcGISServer
Imports ESRI.ArcGIS.ADF.Web.Geometry
Imports ESRI.ArcGIS.ADF.Web.DataSources
Imports ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Server
Imports ESRI.ArcGIS.Schematic
Imports ESRI.ArcGIS.Carto


Namespace SchematicCommands

  Public Class SelectViewType
    Implements IMapServerDropDownBoxAction
#Region "IServerAction Members"

    Public Sub ServerAction(ByVal info As ToolbarItemInfo) Implements IMapServerDropDownBoxAction.ServerAction

      Dim dropBox As DropDownBox = info.Toolbar.ToolbarItems.Find("ViewTypeList")
      Dim viewTypeName As String = dropBox.SelectedItem.Text

      dropBox = info.Toolbar.ToolbarItems.Find("DiagramList")
      dropBox.Items.Clear()

      Dim mapctrl As esriWebControls.Map = CType(info.BuddyControls(0), esriWebControls.Map)
      mapctrl.Page.Session("CurrentViewType") = viewTypeName
      mapctrl.Page.Session("DiagramFullExtent") = Nothing

      ' We have named the map resource managers like the view types
      Dim control As Control = info.Toolbar.Page.FindControl(viewTypeName)
      Dim mapResMgr As MapResourceManager = CType(control, MapResourceManager)

      mapctrl.MapResourceManagerInstance = mapResMgr

      If viewTypeName = "GeographicMap" Then
        dropBox.Disabled = True
        mapctrl.Extent = mapctrl.GetFullExtent()
      Else

        dropBox.Disabled = False

        Dim gisresource As MapResourceLocal = Nothing
        gisresource = CType(mapctrl.MapResourceManagerInstance.GetResource(0), MapResourceLocal)

        For Each layerDescription As esriAgsServer.LayerDescription In gisresource.MapDescription.LayerDescriptions
          layerDescription.DefinitionExpression = "DIAGRAMOBJECTID=-1"
        Next layerDescription

        Dim schDiagramClass As ISchematicDiagramClass = Utilities.GetCurrentDiagramClass(mapctrl)

        Dim schEnumDiagram As IEnumSchematicDiagram = schDiagramClass.SchematicDiagrams
        schEnumDiagram.Reset()

        dropBox.Items.Add(New ListItem)

        Dim schDiagram As ISchematicDiagram = schEnumDiagram.Next()
        While schDiagram IsNot Nothing
          dropBox.Items.Add(New ListItem(schDiagram.Name, schDiagram.OID.ToString()))
          schDiagram = schEnumDiagram.Next()
        End While

        dropBox.SelectedIndex = 0

      End If

      info.Toolbar.Refresh()

      control = info.Toolbar.Page.FindControl("Toc1")
      Dim toc1 As Toc = CType(control, Toc)
      toc1.Refresh()
      toc1.Nodes(0).Nodes(0).Text = ""

      mapctrl.CallbackResults.CopyFrom(toc1.CallbackResults)

      mapctrl.Refresh()

    End Sub  'ServerAction

#End Region
  End Class  'SelectViewType


  Public Class SelectDiagram
    Implements IMapServerDropDownBoxAction
#Region "IServerAction Members"

    Public Sub ServerAction(ByVal info As ToolbarItemInfo) Implements IMapServerDropDownBoxAction.ServerAction

      Dim dropBox As DropDownBox = info.Toolbar.ToolbarItems.Find("DiagramList")
      Dim diagramName As String = dropBox.SelectedItem.Text
      Dim diagramID As String = dropBox.SelectedValue

      If diagramName = "" Then Exit Sub

      Dim mapctrl As esriWebControls.Map = CType(info.BuddyControls(0), esriWebControls.Map)
      Dim viewTypeName As String = mapctrl.Page.Session("CurrentViewType")

      If mapctrl.MapResourceManager <> viewTypeName Then
        Dim control As Control = info.Toolbar.Page.FindControl(viewTypeName)
        mapctrl.MapResourceManagerInstance = CType(control, MapResourceManager)
      End If

      Dim gisresource As MapResourceLocal = Nothing
      gisresource = CType(mapctrl.MapResourceManagerInstance.GetResource(0), MapResourceLocal)

      Dim schDiagramClass As ISchematicDiagramClass = Utilities.GetCurrentDiagramClass(mapctrl)

      Dim objectClass As IObjectClass = CType(schDiagramClass, IObjectClass)
      Dim diagramClassID As String = objectClass.ObjectClassID.ToString()

      ' Change the definition query of each layer in order to display the selected diagram
      Dim definitionExpression As String = "DIAGRAMCLASSID=" & diagramClassID & " AND DIAGRAMOBJECTID=" & diagramID & " AND ISDISPLAYED = -1"

      For Each layerDescription As esriAgsServer.LayerDescription In gisresource.MapDescription.LayerDescriptions
        If layerDescription.LayerID > 0 Then
          layerDescription.DefinitionExpression = definitionExpression
        End If
      Next layerDescription

      Utilities.CalculateExtent(mapctrl, schDiagramClass, diagramName)
      mapctrl.Refresh()

      mapctrl.Page.Session("DiagramFullExtent") = mapctrl.Extent

      Dim control1 As Control = info.Toolbar.Page.FindControl("Toc1")
      Dim toc1 As Toc = CType(control1, Toc)

      ' Change the diagram name in the toc
      toc1.Nodes(0).Nodes(0).Text = diagramName

      ' Redraw the toc : add a CallbackResult with the html content
      Dim sw As System.IO.StringWriter = New System.IO.StringWriter()
      Dim writer As HtmlTextWriter = New HtmlTextWriter(sw)

      toc1.RenderControl(writer)
      Dim htmlContent As String = sw.ToString()
      sw.Close()

      mapctrl.CallbackResults.Add(control1, "content", htmlContent)

      ' In case the previous diagram is being updated, hide progress bar
      mapctrl.CallbackResults.Add(Utilities.ShowAjaxIndicator(False))

    End Sub  'ServerAction

#End Region
  End Class  'SelectDiagram


  Public Class CustomFullExtent
    Implements IMapServerCommandAction
#Region "IServerAction Members"

    Public Sub ServerAction(ByVal info As ToolbarItemInfo) Implements IServerAction.ServerAction

      Dim mapctrl As esriWebControls.Map = CType(info.BuddyControls(0), esriWebControls.Map)

      Dim viewTypeName As String = mapctrl.Page.Session("CurrentViewType")

      Dim fullExtent As Envelope = Nothing

      If viewTypeName = "GeographicMap" Then
        mapctrl.Extent = mapctrl.GetFullExtent
      Else
        fullExtent = CType(mapctrl.Page.Session("DiagramFullExtent"), Envelope)
      End If

      If fullExtent Is Nothing Then Exit Sub

      If mapctrl.MapResourceManager <> viewTypeName Then
        Dim control As Control = info.Toolbar.Page.FindControl(viewTypeName)
        mapctrl.MapResourceManagerInstance = CType(control, MapResourceManager)
      End If

      mapctrl.Extent = fullExtent

      mapctrl.Refresh()

    End Sub  'ServerAction

#End Region
  End Class  'CustomFullExtent


  Public Class DiagramListUpdate
    Implements IMapServerCommandAction
#Region "IServerAction Members"

    Public Sub ServerAction(ByVal info As ToolbarItemInfo) Implements IServerAction.ServerAction

      Dim dropBox As DropDownBox = info.Toolbar.ToolbarItems.Find("ViewTypeList")
      Dim viewTypeName As String = dropBox.SelectedItem.Text

      If viewTypeName = "GeographicMap" Then Exit Sub

      dropBox = info.Toolbar.ToolbarItems.Find("DiagramList")
      dropBox.Items.Clear()

      Dim mapctrl As esriWebControls.Map = CType(info.BuddyControls(0), esriWebControls.Map)

      mapctrl.Page.Session("CurrentViewType") = viewTypeName
      mapctrl.Page.Session("DiagramFullExtent") = Nothing

      ' We have named the map resource managers like the view types
      Dim control As Control = info.Toolbar.Page.FindControl(viewTypeName)
      Dim mapResMgr As MapResourceManager = CType(control, MapResourceManager)

      mapctrl.MapResourceManagerInstance = mapResMgr

      Dim gisresource As MapResourceLocal = CType(mapctrl.MapResourceManagerInstance.GetResource(0), MapResourceLocal)

      For Each layerDescription As esriAgsServer.LayerDescription In gisresource.MapDescription.LayerDescriptions
        layerDescription.DefinitionExpression = "DIAGRAMOBJECTID=-1"
      Next layerDescription

      Dim schDiagramClass As ISchematicDiagramClass = Utilities.GetCurrentDiagramClass(mapctrl)
      Dim schEnumDiagram As IEnumSchematicDiagram = schDiagramClass.SchematicDiagrams

      schEnumDiagram.Reset()

      dropBox.Items.Add(New ListItem)

      Dim schDiagram As ISchematicDiagram = schEnumDiagram.Next()
      While schDiagram IsNot Nothing
        dropBox.Items.Add(New ListItem(schDiagram.Name, schDiagram.OID.ToString()))
        schDiagram = schEnumDiagram.Next()
      End While

      dropBox.SelectedIndex = -1

      info.Toolbar.Refresh()

      control = info.Toolbar.Page.FindControl("Toc1")
      Dim toc1 As Toc = CType(control, Toc)
      toc1.Refresh()
      toc1.Nodes(0).Nodes(0).Text = ""

      mapctrl.CallbackResults.CopyFrom(toc1.CallbackResults)

      mapctrl.Refresh()

    End Sub  'ServerAction

#End Region
  End Class  'DiagramListUpdate


  Public Class DiagramUpdate
    Implements IMapServerCommandAction
#Region "IServerAction Members"

    Public Sub ServerAction(ByVal info As ToolbarItemInfo) Implements IServerAction.ServerAction

      Dim mapctrl As esriWebControls.Map = CType(info.BuddyControls(0), esriWebControls.Map)

      Dim page As System.Web.UI.Page = info.Toolbar.Page

      If Not page.Session("UpdatingDiagram") Is Nothing Then
        Dim callbackResult As CallbackResult = New CallbackResult(Nothing, Nothing, "javascript", "alert('Previous update not yet finished')")
        mapctrl.CallbackResults.Add(callbackResult)
        Return
      End If

      Dim diagramName As String = Nothing
      Dim diagramID As String = Nothing

      Dim dropBox As DropDownBox = info.Toolbar.ToolbarItems.Find("DiagramList")
      If dropBox.SelectedIndex > 0 Then
        diagramName = dropBox.SelectedItem.Text
        diagramID = dropBox.SelectedValue
      End If

      If String.IsNullOrEmpty(diagramName) Then Exit Sub


      ' Initialize GP resource and functionality
      Dim control As Control = info.Toolbar.Page.FindControl("GeoprocessingResourceManager1")
      Dim gpResourceManager As GeoprocessingResourceManager = CType(control, GeoprocessingResourceManager)
      Dim gpResourceItem As GeoprocessingResourceItem = CType(gpResourceManager.ResourceItems(0), GeoprocessingResourceItem)

      If gpResourceItem.FailedToInitialize Then
        Dim errorMessage As String = gpResourceItem.InitializationFailure.Message
        Dim callbackResultError As CallbackResult = New CallbackResult(Nothing, Nothing, "javascript", "alert('Resource initialization exception: " & errorMessage & "')")
        mapctrl.CallbackResults.Add(callbackResultError)
        Return
      End If

      Dim gpResource As IGeoprocessingResource = CType(gpResourceItem.Resource, IGeoprocessingResource)
      Dim gpFunctionality As IGeoprocessingFunctionality = CType(gpResource.CreateFunctionality(GetType(IGeoprocessingFunctionality), Nothing), IGeoprocessingFunctionality)
      Dim agsGpFunctionality As GeoprocessingFunctionality = CType(gpFunctionality, GeoprocessingFunctionality)

      If (Not agsGpFunctionality.Initialized) Then
        agsGpFunctionality.Initialize()
      End If

      Dim taskname As String = "Update"
      Dim adfGPToolInfo As GPToolInfo = agsGpFunctionality.GetTask(taskname)
      Dim adfGPParamterInfoArray As GPParameterInfo() = adfGPToolInfo.ParameterInfo

      ' Set input parameter (diagram name) 
      Dim adfGPString As GPString = New GPString()
      adfGPString.Value = diagramName

      ' Submit Job
      Dim adfGPValueArray As GPValue() = New GPValue(0) {}
      adfGPValueArray(0) = adfGPString
      Dim jobID As String = agsGpFunctionality.SubmitJob(taskname, adfGPValueArray)

      mapctrl.CallbackResults.Add(Utilities.ShowAjaxIndicator(True))
      page.Session("UpdatingDiagram") = diagramName

      ' Trigger an initial callback to check job status
      Dim diagramTypeName As String = page.Session("CurrentViewType")
      Dim callbackFunctionString As String = page.ClientScript.GetCallbackEventReference(page, "message", "processCallbackResult", "context", "postBackError", True)
      Dim callbackReplaceString As String = callbackFunctionString.Replace("'", "\'")
      Dim timerFunctionString As String = String.Format("window.setTimeout('checkJob(""gpJobArgs={0},{1},{2},{3}"",""{4}"")',3000);", jobID, diagramName, diagramID, diagramTypeName, callbackReplaceString)
      Dim checkJobCallbackResult As CallbackResult = New CallbackResult(page, "javascript", timerFunctionString)

      mapctrl.CallbackResults.Add(checkJobCallbackResult)

    End Sub  'ServerAction

#End Region
  End Class  'DiagramUpdate


  Public Class Utilities

    Public Shared Function GetCurrentDiagramClass(ByVal mapctrl As esriWebControls.Map) As ISchematicDiagramClass

      Dim gisresource As MapResourceLocal = Nothing
      gisresource = CType(mapctrl.MapResourceManagerInstance.GetResource(0), MapResourceLocal)

      Dim mso As IMapServerObjects = CType(gisresource.MapServer, IMapServerObjects)
      Dim map As IMap = mso.Map(gisresource.DataFrame)

      Dim schLayer As ISchematicLayer = CType(map.Layer(0), ISchematicLayer)
      Dim schDiagram As ISchematicDiagram = schLayer.SchematicDiagram

      Return schDiagram.SchematicDiagramClass

    End Function


    Public Shared Sub CalculateExtent(ByVal mapctrl As esriWebControls.Map, ByVal schDiagramClass As ISchematicDiagramClass, ByVal diagramName As String)

      Dim schDiagram As ISchematicDiagram
      schDiagram = schDiagramClass.SchematicDiagramByName(diagramName)

      Dim schEltContainer As ISchematicElementContainer
      schEltContainer = CType(schDiagram, ISchematicElementContainer)

      Dim schElements As IEnumSchematicElement
      schElements = schEltContainer.SchematicElements
      schElements.Reset()

      Dim feature As IFeature = Nothing
      Dim env As ESRI.ArcGIS.Geometry.IEnvelope = Nothing

      Dim schElement As ISchematicElement = schElements.Next()

      While schElement IsNot Nothing

        feature = CType(schElement, IFeature)

        If env Is Nothing Then
          env = feature.Extent
        Else
          env.Union(feature.Extent)
        End If

        schElement = schElements.Next()

      End While

      Dim resEnvelope As Envelope = mapctrl.Extent

      If env IsNot Nothing Then

        Dim dx As Double = (env.XMax - env.XMin) * 0.05
        Dim dy As Double = (env.YMax - env.YMin) * 0.05

        resEnvelope.XMin = env.XMin - dx
        resEnvelope.XMax = env.XMax + dx
        resEnvelope.YMin = env.YMin - dy
        resEnvelope.YMax = env.YMax + dy

      End If

      mapctrl.Extent = resEnvelope

    End Sub


    Public Shared Function ShowAjaxIndicator(ByVal visible As Boolean) As CallbackResult

      Dim showIndicatorString As String = "document.getElementById('ProgressBar').style.visibility = "
      If visible Then
        showIndicatorString &= "'visible'"
      Else
        showIndicatorString &= "'hidden'"
      End If
      Dim showIndicatorCallbackResult As CallbackResult = New CallbackResult("div", "ProgressBar", "javascript", showIndicatorString)
      Return showIndicatorCallbackResult

    End Function

  End Class  'Utilities

End Namespace  'SchematicCommands