This article describes how you can configure the handle factory of the feature handles provider to deactivate the translate handle.

Other customizations

For more information about customizing an existing handles provider, see this article.

Step 1 - Create a custom HandleFactory

We must implement the FeatureHandlesProvider::IHandleFactory. In the createTranslateHandle method, we must make sure that the TranslateEditHandle isn’t active.

You can do that in several ways:

Returning a null handle

We return a nullptr handle in our Handlefactory.

Program (C++): Returning a null TranslateEditHandle
class NullFeatureHandleFactory : public FeatureHandlesProvider::IHandleFactory {
public:
  std::shared_ptr<IEditHandle> createTranslateHandle(const std::shared_ptr<ObservableFeature>& /*feature*/,
                                                     const std::shared_ptr<ObservableGeometry>& /*geometry*/,
                                                     const std::shared_ptr<ITranslateEditAction>& /*editAction*/,
                                                     const std::shared_ptr<FeatureEditContext>& /*context*/) override {
    return nullptr;
  }

  bool isTranslateHandleValid(const std::shared_ptr<IEditHandle>& /*translateHandle*/,
                              const std::shared_ptr<ObservableFeature>& /*feature*/,
                              const std::shared_ptr<ObservableGeometry>& /*geometry*/,
                              const std::shared_ptr<FeatureEditContext>& /*context*/) override {
    return true;
  }
};

C#

class NullFeatureHandleFactory : FeatureHandlesProvider.IHandleFactory
{
    public IEditHandle CreateTranslateHandle(ObservableFeature feature, ObservableGeometry geometry, ITranslateEditAction action,
        FeatureEditContext context)
    {
        return null;
    }

    public bool IsTranslateHandleValid(IEditHandle translateHandle, ObservableFeature feature, ObservableGeometry geometry,
        FeatureEditContext context)
    {
        return true;
    }
};

Returning a handle without an action

We return a TranslateEditHandle without an action, but with a shadow geometry provider. We use this provider to draw a draped version of our geometry if the shape is a 3D one. The CreateTranslateHandle method for this factory becomes:

Program (C++): Returning a handle without an action
std::shared_ptr<IEditHandle> createTranslateHandle(const std::shared_ptr<ObservableFeature>& /*feature*/,
                                                   const std::shared_ptr<ObservableGeometry>& geometry,
                                                   const std::shared_ptr<ITranslateEditAction>& /*editAction*/,
                                                   const std::shared_ptr<FeatureEditContext>& context) override {
  auto handle = std::make_shared<TranslateEditHandle>(geometry->getValue()->getReference(), context);
  handle->setShadowGeometryProvider(geometry); // To let the handle paint the helper lines in case of a 3D Polyline
  return handle;
}

C#

public IEditHandle CreateTranslateHandle(ObservableFeature feature, ObservableGeometry geometry, ITranslateEditAction action,
    FeatureEditContext context)
{
    var handle = new TranslateEditHandle(geometry.Value.Reference, context);
    // To let the handle paint the helper lines in case of a 3D Polyline
    handle.ShadowGeometryProvider = geometry;
    return handle;
}

Step 2 - Use the HandleFactory

Now, we want to start using the handle factory. To do so, we need an implementation of IFeatureEditConfiguration that uses the factory in a feature handles provider. We are using the handle factory with the helper line.

Program (C++): Use handle factory
class NoTranslateEditConfiguration final : public IFeatureEditConfiguration {
public:
  NoTranslateEditConfiguration() {
    auto featuresHandlesProvider = std::make_shared<FeatureHandlesProvider>();
    auto customFeatureHandleFactory = std::make_shared<StillVisibleFeatureHandleFactory>();
    featuresHandlesProvider->setHandleFactory(std::move(customFeatureHandleFactory));

    _featureHandlesProvider = featuresHandlesProvider;
  }

  void edit(const Feature& /*feature*/, LayerId /*layerId*/, const std::shared_ptr<Map>& /*map*/, FeatureEditConfigurationBuilder& builder) const override {
    // Use a custom handles provider for all features
    builder.handlesProvider(_featureHandlesProvider).submit();
  }

private:
  std::shared_ptr<IFeatureHandlesProvider> _featureHandlesProvider;
};

C#

class NullFeatureHandleFactory : FeatureHandlesProvider.IHandleFactory
{
    public IEditHandle CreateTranslateHandle(ObservableFeature feature, ObservableGeometry geometry, ITranslateEditAction action,
        FeatureEditContext context)
    {
        return null;
    }

    public bool IsTranslateHandleValid(IEditHandle translateHandle, ObservableFeature feature, ObservableGeometry geometry,
        FeatureEditContext context)
    {
        return true;
    }
};

class StillVisibleFeatureHandleFactory : FeatureHandlesProvider.IHandleFactory
{
    public IEditHandle CreateTranslateHandle(ObservableFeature feature, ObservableGeometry geometry, ITranslateEditAction action,
        FeatureEditContext context)
    {
        var handle = new TranslateEditHandle(geometry.Value.Reference, context);
        // To let the handle paint the helper lines in case of a 3D Polyline
        handle.ShadowGeometryProvider = geometry;
        return handle;
    }

    public bool IsTranslateHandleValid(IEditHandle translateHandle, ObservableFeature feature, ObservableGeometry geometry,
        FeatureEditContext context)
    {
        return true;
    }
};

class NoTranslateEditConfiguration : IFeatureEditConfiguration
{
    private IFeatureHandlesProvider _featureHandlesProvider;

    public NoTranslateEditConfiguration()
    {
        var featuresHandlesProvider = new FeatureHandlesProvider();
        var customFeatureHandleFactory = new StillVisibleFeatureHandleFactory();
        featuresHandlesProvider.HandleFactory = customFeatureHandleFactory;

        _featureHandlesProvider = featuresHandlesProvider;
    }

    public void Edit(Feature feature, ulong layerId, Map map, FeatureEditConfigurationBuilder builder)
    {
        builder.HandlesProvider(_featureHandlesProvider).Submit();
    }
};

Step 3 - Use the FeatureEditConfiguration in the Feature Layer

The final step is to use the edit configuration in the builder of the FeatureLayer.

Program (C++): Use edit configuration
auto editConfiguration = std::make_shared<NoTranslateEditConfiguration>();
return FeatureLayer::newBuilder().model(model).editable(true).editConfiguration(std::move(editConfiguration)).build();

C#

var editConfiguration = new NoTranslateEditConfiguration();
return FeatureLayer.NewBuilder().Model(model).Editable(true).EditConfiguration(editConfiguration).Build();