# Delphi

Source: https://docs.interop.io/desktop/capabilities/data-sharing/shared-contexts/delphi/index.html

## Using Shared Contexts

> ℹ️ *See the [Delphi 10](https://github.com/InteropIO/native-examples/tree/main/glue-com/GlueDelphi) and [Delphi 7](https://github.com/InteropIO/native-examples/tree/main/glue-com/GlueDelphi7) examples on GitHub.*

In order to use shared contexts, you must implement the [`IGlueContextHandler`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-igluecontexthandler) interface:

```delphi
TMainForm = class(TForm, IGlueContextHandler)
...
private
  G42: IGlue42;
  // The shared context handle.
  myContext: IGlueContext;
protected
  function HandleContext(const context: IGlueContext): HResult; stdcall;
  function HandleContextUpdate(const contextUpdate: IGlueContextUpdate): HResult; stdcall;
  ...
```

## Subscribing for Context Updates

To subscribe for context updates, use the [`SubscribeGlueContext`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-iglue42-subscribegluecontext) method. If the context doesn't exist, a new empty context will be created:

```delphi
TMainForm = class(TForm, IGlueContextHandler)
  ...
  procedure TMainForm.InitializeGlue;
    ...
    G42.Start(inst);
    // Subscribe for context updates.
    G42.SubscribeGlueContext('myContextName', Self);
    ...
```

## Handling Context Updates

To handle a newly activated shared context subscription, use the [`HandleContext`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-igluecontexthandler-handlecontext) method:

```delphi
function TMainForm.HandleContext(const context: IGlueContext): HResult; stdcall;
begin
  // Store the context handle.
  if context.GetContextInfo.Name = 'myContextName' then
    myContext := context;

  Result := S_OK;
end;
```

To handle updates of the shared context data, use the [`HandleContextUpdate`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-igluecontexthandler-handlecontextupdate) method:

```delphi
function TMainForm.HandleContextUpdate(const contextUpdate: IGlueContextUpdate): HResult; stdcall;
var
  context: IGlueContext;
  contextName: WideString;
  data: TGlueContextValueArray;
begin
  context := contextUpdate.GetContext();
  contextName := context.GetContextInfo.Name;
  // Get the context data in a native data structure.
  rawData := context.GetData();
  data := SA_AsTranslatedContextValues(rawData);
  ...
  SafeArrayDestroy(rawData);
  Result := S_OK;
end;
```

## Updating Contexts

To update the data of a shared context, use the [`SetContextData`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-igluecontext-setcontextdata) method of the [`IGlueContext`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-igluecontext) interface. The data must be provided as a `PSafeArray` containing [`GlueContextValue`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#types-gluecontextvalue) values:

```delphi
var
  psaData: PSafeArray;
  nativeData: array[0..0] of TGlueContextValue;
  emails: array of TGlueValue;
begin
  // Initiate an array with data.
  SetLength(emails,2);
  emails[0] := CreateValue('vernon.mullen@acme.com');
  emails[1] := CreateValue('vernon.d.mullen@acme.com');

  // Create the data with native types.
  nativeData[0] := CreateContextValue('contact', CreateComposite([
    CreateContextValue('name', CreateComposite([
      CreateContextValue('firstName', CreateValue('Vernon')),
      CreateContextValue('lastName', CreateValue('Mullen'))
    ], false)),
    CreateContextValue('displayName', CreateValue('Vernon Mullen')),
    CreateContextValue('emails', CreateTuple(emails))
  ], false));

  // Pack the native data into a `PSafeArray`.
  psaData := CreateContextValues_SA(AsGlueContextValueArray(nativeData));

  // Replace the context data.
  context01.SetContextData(psaData);

  // Clean up.
  SafeArrayDestroy(psaData);
end;
```

The resulting context data from the previous example, represented as JSON:

```json
{
    "contact": {
        "name": {
            "firstName": "Vernon",
            "lastName": "Mullen"
        },
        "displayName": "Vernon Mullen",
        "emails": [
            "vernon.mullen@acme.com",
            "vernon.d.mullen@acme.com"
        ]
    }
}
```

If you don't want to overwrite the contents of the entire context, you can set a specific elementary or composite value by using the [`SetContextDataOnFieldPath`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-igluecontext-setcontextdataonfieldpath) method:

```delphi
var
  psaData: PSafeArray;
begin
  // Pack the data into a `PSafeArray`.
  psaData := CreateContextValues_SA(AsGlueContextValueArray([
    CreateContextValue('name', CreateComposite([
      CreateContextValue('firstName', CreateValue('Vernon')),
      CreateContextValue('lastName', CreateValue('Mullen'))
    ], false)),
    CreateContextValue('displayName', CreateValue('Vernon Mullen')),
    CreateContextValue('emails', CreateTuple([
      CreateValue('vernon.mullen@acme.com'),
      CreateValue('vernon.d.mullen@acme.com')
    ]))
  ]));

  // Replace the context value for 'data.contact'.
  context01.SetContextDataOnFieldPath('data.contact', psaData);

  // Clean up.
  SafeArrayDestroy(psaData);
end;
```

You can also set a specific elementary or composite value by directly providing a JSON string to the [`UpdateContextDataJson`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-igluecontext-updatecontextdatajson) method:

```delphi
  ...
  // Replace the context value for 'data.contact'.
  context01.SetContextDataOnFieldPath('data.contact','{"name":{"firstName":"Vernon","lastName":"Mullen"}}');
  ...
```

## Listing All Available Contexts

To obtain a list of all available contexts, use the [`GetKnownContexts`](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/delphi/index.md#interfaces-iglue42-getknowncontexts) method:

```delphi
var
  saContexts: PSafeArray;
  contexts: array of GlueContext;
begin
  saContexts := G42.GetKnownContexts();
  contexts := SA_AsGlueContextArray(saContexts);
  ...
  SafeArrayDestroy(saContexts);
end;
```
