This tutorial explains how you can customize an existing handles provider to:
-
Change the default settings of a handles provider
-
Customize the handles used by a handles provider
-
Make sure that the customized handles provider is used during editing
Other customizations
You need to customize a handles provider for advanced use cases only. For other customization methods, see this article. |
The code snippets in this tutorial are available in the editing sample.
See this article for more information about editing.
Configuring a handles provider
You can change the configuration of most handles provider implementations. For example, you can change the
minimum and maximum point counts for the PolylineHandlesProvider
and PolylineRingHandlesProvider
, or you can change the
handles they use.
The following sample code shows you how to create and customize a handles provider.
auto handlesProvider = std::make_shared<PolylineHandlesProvider>(); handlesProvider->setMaxPointCount(8);
After creating a handles provider, you must configure it so that it’s used during editing:
-
Make sure that an
IFeatureHandlesProvider
uses the geometry handles provider.Program: Let the feature handles provider use the custom geometry handles provider// Register the custom handles provider in a default composite with a high priority, so that it is used before all other handles providers // Using a composite instead of directly using the custom PolylineHandlesProvider makes sure that other geometries remain supported. auto geometryHandlesProvider = CompositeGeometryHandlesProvider::createDefault(); geometryHandlesProvider->add(handlesProvider, Priority::high()); // Make sure the custom geometry handles provider is used to editing the features auto featureHandlesProvider = std::make_shared<FeatureHandlesProvider>(); featureHandlesProvider->setGeometryHandlesProvider(geometryHandlesProvider); -
Configure that
IFeatureHandlesProvider
in anIFeatureEditConfiguration
Program: Configure the feature handles provider in a feature edit configurationclass CustomEditConfiguration final : public IFeatureEditConfiguration { public: 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; }; -
Configure that
IFeatureEditConfiguration
on theFeatureLayer
.Program: Configuring the feature edit configuration on the layer// Use a custom edit configuration that changes the editing behavior for this layer auto customEditConfiguration = std::make_shared<CustomEditConfiguration>(); // Register the configuration. This makes the layer editable by default return FeatureLayer::newBuilder() .model(model) // .title("Tutorial 1") .editConfiguration(customEditConfiguration) .build();
Changing the handles of a handle provider
For more fine-grained control over the handles used by a handles provider, you can implement your own handle factory. For example, if you implement your own handle factory for polylines, you can decide which handles it creates and uses to:
-
Move points
-
Remove points
-
Insert points
-
Change the elevation of a point
You can customize the handle factories for other geometries in a similar way. The handle to translate a
Feature
is provided by an IFeatureHandlesProvider
. You can use the handle factory for the default implementation,
FeatureHandlesProvider
to customize the translate handle.
The following sections show you how to implement and use a handle factory.
Using a handle factory wrapper
You can configure custom handle factory implementations, typically wrappers, on the corresponding handles provider.
// A custom handle factory provides fine-grained control over the handles that are used by the handles provider auto defaultHandleFactory = handlesProvider->getHandleFactory(); auto customHandleFactory = std::make_shared<CustomPolylineHandleFactory>(defaultHandleFactory); handlesProvider->setHandleFactory(customHandleFactory);
Omitting a handle
To omit a type of handle, the corresponding factory method must return null.
std::shared_ptr<IEditHandle> CustomPolylineHandleFactory::createInsertPointHandle(const std::shared_ptr<Observable<std::shared_ptr<Polyline>>>& /*polyline*/, size_t /*insertIndex*/, const std::shared_ptr<IPointEditAction>& /*editAction*/, const std::shared_ptr<FeatureEditContext>& /*context*/) { // Make sure that PolylineHandlesProvider doesn't create insert handles anymore // Note that it will still create append and prepend handles though. return nullptr; }
Replacing a handle
To replace a handle, you must re-implement the corresponding factory method. In the following example, we replace the handle to remove points from a polyline.
std::shared_ptr<IEditHandle> CustomPolylineHandleFactory::createRemovePointHandle(const std::shared_ptr<Observable<std::shared_ptr<Polyline>>>& polyline, size_t pointIndex, const std::shared_ptr<IPointEditAction>& editAction, const std::shared_ptr<FeatureEditContext>& /*context*/) { // Derive an observable Point from the observable Polyline. This point will be updated whenever the polyline is changed auto observableLocation = ObservablePolylineUtil::derivePointAtIndex(polyline, pointIndex); // Create a handle that is initially positioned on this location auto handle = std::make_shared<PointEditHandle>(observableLocation); // The handle will call the edit action when clicking on it using the right mouse button handle->addOnClickAction(editAction, 1).mouseButton(MouseButton::right()).cursor(MouseCursor::arrow()); // The handle will call the edit action when performing a touch long press action handle->addOnTouchLongPressAction(editAction).cursor(MouseCursor::arrow()); // Use a small red icon handle->setRegularIcon(std::make_shared<BasicIcon>(IconType::FilledRectangle, 6, Color(255, 0, 0, 64))); handle->setHighlightedIcon(std::make_shared<BasicIcon>(IconType::FilledRectangle, 6, Color(255, 0, 0, 192))); return handle; }
Adding a handle
You can’t use the handle factories to add an extra handle. It requires a different approach. For a demonstration, see this tutorial.