Highlighting
When using selection, highlighting is important visual feedback expected by the user. Like selection, highlighting can be applied at different levels (segment, entity, and subentity). In this section, we’ll discuss highlighting by KeyPath. A key path is like a fully-qualified filename - it is an unambiguous list of segment keys from the root segment to the selected segment.
Although not strictly necessary, the sandbox bundles highlighting into its subclassed SandboxHighlightOperator
. If you bring up SandboxHighlightOperator::HighlightCommon()
, you’ll see the following code:
HPS::HighlightOptionsKit highlight_options(HPS::HighlightOptionsKit::GetDefault());
highlight_options.SetStyleName("highlight_style");
highlight_options.SetSubentityHighlighting(SelectionLevel == HPS::Selection::Level::Subentity);
highlight_options.SetOverlay(HPS::Drawing::Overlay::InPlace);
The first two lines of code are building a highlight style using a HPS::HighlightOptionsKit. In this case, the default options are being supplied by HPS::HighlightOptionsKit::GetDefault (this is where the orange color comes from). Next, the style is given the generic name “highlight_style”, which is required. This way of building a style is sufficient for this simple application, but style needs can vary widely and be very complex. Please see our Programming Guide page on highlight styles for full details on building styles.
Next, the code takes one of two paths depending on whether the current model is a CAD model or not. If it is a CAD model, you’ll see the CAD data being highlighted as well as the geometry:
if (!cad_model.Empty())
{
// since we have a CADModel, we want to highlight the components, not just the Visualize geometry
HPS::SelectionResultsIterator it = selection_results.GetIterator();
HPS::Canvas canvas = cview->GetCanvas();
while (it.IsValid())
{
HPS::ComponentPath component_path = cad_model.GetComponentPath(it.GetItem());
if (!component_path.Empty())
{
// Make the selected component get highlighted in the model browser
highlight_options.SetNotification(true);
component_path.Highlight(canvas, highlight_options);
// if we selected PMI, highlight the associated components (if any)
HPS::Component const & leaf_component = component_path.Front();
if (leaf_component.HasComponentType(HPS::Component::ComponentType::ExchangePMIMask))
{
// Only highlight the Visualize geometry for the associated components, don't highlight the associated components in the model browser
highlight_options.SetNotification(false);
for (auto const & reference : leaf_component.GetReferences())
HPS::ComponentPath(1, &reference).Highlight(canvas, highlight_options);
}
}
it.Next();
}
}
This code snippet shows the selected object grouped into an array with a HPS::SelectionResultsIterator, then the highlight style is applied to each. However, if there is no CAD model, there are no additional components to highlight, so this simple code does this job:
else
{
// since there is no CADModel, just highlight the Visualize geometry
cview->GetCanvas().GetWindowKey().GetHighlightControl().Highlight(selection_results, highlight_options);
HPS::Database::GetEventDispatcher().InjectEvent(HPS::HighlightEvent(HPS::HighlightEvent::Action::Highlight, selection_results, highlight_options));
}
The last snippet shows the highlight style created in the first part being applied to those selected objects. The end of this function redraws the scene with the highlighted geometry by calling cview->Update()
. With few exceptions, HNP will not detect and update changes for you - so it is always important to call Update()
whenever a redraw is needed. Keep in mind that very large models can be expensive to redraw, so use Update()
accordingly!
If your application requires logic in addition to highlighting, you can use the HPS::SelectionResultsIterator shown in the examples above to get the geometry keys that were selected. From there, any sort of logic can be built in to your operator to achieve your goals.