Bruce Reeves SRNS:The question is how to "reject" the datapoint when OnPostLocate() return false. When I datapoint while on the "rejected" element, the OnDataPoint() is still called, and I don't know how to reject it there...THe docs mention that LocateOneElement() can "remove the hit..."
Surprise, it's me!
LocateOneElement won't remove agenda entries when you pass true for newSearch, it will only add entries. LocateOneElement gets called with false from OnResetButton in order to support cycling through overlapping elements. For this reason it strikes me as problematic that you are trying to maintain your own duplicate ElementAgenda...the tool agenda, "GetElemAgendaP" is perfectly suited to hold your two lines in the order they are selected...
If your OnPostLocate rejects an element, LocateOneElement won't change the tool agenda count, that's how you could know whether the data button accepted an element or not. NOTE: LocateOneElement is calling DoLocate, if DoLocate returns a NULL HitPath, it early returns, otherwise it inserts the path into the tool's agenda. If you're not going to use the tool's agenda, you may as well just call DoLocate yourself from your data button and reset button methods...but my recommendation is to play nice with the base class.
MstnElementSetTool of course also has built-in support for multi-select. Here's an example, it can be simplified much more since you don't need to support more than 2 elements and you probably don't care about the IElementState goop. If there's something here that isn't in the published api, pretend it's psuedocode..
HTH
-B
/*=================================================================================**//**
* Example per-element info...save original locate hit path with element.
*
* @bsiclass
+===============+===============+===============+===============+===============+======*/
struct ExampleLocateInfo : RefCounted <IElementState>
{
private:
HitPathCP m_hitPath;
public:
ExampleLocateInfo::ExampleLocateInfo () {m_hitPath = NULL;}
ExampleLocateInfo::~ExampleLocateInfo () {mdlDisplayPath_release ((DisplayPathP) m_hitPath);}
void SetHitPathCP (HitPathCP hitPath) {mdlDisplayPath_release ((DisplayPathP) m_hitPath); m_hitPath = hitPath; mdlDisplayPath_addRef ((DisplayPathP) m_hitPath);}
HitPathCP GetHitPathCP () {return m_hitPath;}
}; // ExampleLocateInfo
/*=================================================================================**//**
* Contrived example tool:
*
* Allow user to locate multiple elements and create a linestring connecting the
* locate points. Tool completes when a minimum of 2 elements
* are selected, the control key is used to locate additional elements.
*
* Demonstrates using WantAdditionalLocate and extending BuildLocateAgenda to
* preserve the locate information using IElementSet. Using modifier transition
* event to enable/disable locate for additional input.
*
* @bsiclass
+===============+===============+===============+===============+===============+======*/
struct ExampleTool : MstnElementSetTool
{
private:
EditElemHandle m_result;
public:
/*---------------------------------------------------------------------------------**//**
* ExampleTool methods
+---------------+---------------+---------------+---------------+---------------+------*/
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
bool ExampleTool::DoComputeResult (MstnButtonEventCP ev)
{
m_result.Invalidate ();
EmbeddedDPoint3dArray* pointsP = jmdlEmbeddedDPoint3dArray_grab ();
EditElemHandleP curr = GetElemAgendaP ()->GetFirstP ();
EditElemHandleP end = curr + GetElemAgendaP ()->GetCount ();
for (; curr < end ; curr++)
{
ExampleLocateInfo* info = dynamic_cast <ExampleLocateInfo*> (curr->GetIElementState ());
if (NULL == info)
continue;
jmdlEmbeddedDPoint3dArray_addDPoint3d (pointsP, mdlHitPath_getHitPoint (info->GetHitPathCP ()));
}
MSElement elm;
MSElementDescrP edP;
mdlLineString_create (&elm, NULL, jmdlEmbeddedDPoint3dArray_getPtr (pointsP, 0), jmdlEmbeddedDPoint3dArray_getCount (pointsP));
mdlElmdscr_new (&edP, NULL, &elm);
m_result.SetElemDescr (edP, true, false);
jmdlEmbeddedDPoint3dArray_drop (pointsP);
return m_result.IsValid ();
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
void ExampleTool::SetupForLocate (int count)
{
__super::SetLocateCursor (count < 2 ? true : false, -1);
UInt32 msgId = PROMPT_ExampleToolComplete;
switch (count)
{
case 0:
msgId = PROMPT_ExampleToolFirst;
break;
case 1:
msgId = PROMPT_ExampleToolNext;
break;
}
mdlOutput_rscPrintf (MSG_PROMPT, NULL, STRINGLISTID_Prompts, msgId);
}
/*---------------------------------------------------------------------------------**//**
* MstnElementSet methods
+---------------+---------------+---------------+---------------+---------------+------*/
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual UsesSelection ExampleTool::AllowSelection () override
{
// In this example don't support selection sets...(or fences MstnElementSetTool default)
return USES_SS_None;
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual bool ExampleTool::DoGroups () override
{
// For this example don't include graphic/named group members for located element...
return false;
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual bool ExampleTool::WantDynamics () override
{
// A preview for this type of tool would use a decorator or transients, typically not dynamics...
return false;
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual bool ExampleTool::NeedAcceptPoint () override
{
// Accept point is required for multi-locate to give the user a chance to identity additional elements...
return true;
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual bool ExampleTool::OnModifyComplete (MstnButtonEventCP ev) override
{
// Agenda successfully processed...write the multi-element result...
if (m_result.IsValid ())
m_result.AddToModel (ACTIVEMODEL);
return __super::OnModifyComplete (ev);
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual StatusInt ExampleTool::OnElementModify (EditElemHandleR elHandle) override
{
// Located elements may be trimmed/extended etc. Return ERROR to leave unchanged...
return ERROR;
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual bool ExampleTool::SetupForModify (MstnButtonEventCP ev, bool isDynamics) override
{
// Called before each dynamics frame and once for final accept.
if (GetElemAgendaP ()->GetCount () < 2)
return false; // false if not enough input to process elements...
return DoComputeResult (ev);
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual EditElemHandleP ExampleTool::BuildLocateAgenda (HitPathCP path, MstnButtonEventCP ev) override
{
// Here we have both the new agenda entry and the current hit path...save it for later!
EditElemHandleP elHandle = __super::BuildLocateAgenda (path, ev);
if (elHandle)
{
ExampleLocateInfo* locateInfo = new ExampleLocateInfo;
locateInfo->SetHitPathCP (path);
elHandle->SetIElementState (locateInfo);
}
return elHandle;
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual bool ExampleTool::WantAdditionalLocate (MstnButtonEventCP ev) override
{
if (NULL == ev)
return true; // This is a multi-locate tool...
// Require a minumum of 2 elements, if control is down select additional elements...
return (GetElemAgendaP ()->GetCount () < 2 || ev->IsControlKey ());
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual bool ExampleTool::OnModifierKeyTransition (bool wentDown, int key) override
{
// Control key state change, may need to enable/disable auto-locate, change cursor, prompts. etc.
if (TOGGLESELECT_MODKEY != key)
return false;
if (GetElemAgendaP ()->GetCount () < 2)
return false;
SetupForLocate (wentDown ? 1 : 2);
return true;
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual void ExampleTool::SetupAndPromptForNextAction () override
{
// All changes to auto-locate/accusnap state and user prompts are done here!!!
SetupForLocate (GetElemAgendaP ()->GetCount ());
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual void ExampleTool::OnRestartCommand () override
{
// Must restart or call ExitTool!
ExampleTool* newTool = new ExampleTool ();
newTool->InstallTool ();
}
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
virtual bool ExampleTool::OnInstall () override
{
if (!__super::OnInstall ())
return false;
SetCmdNumber (CMD_EXAMPLE_TOOL); // For toolsettings/undo string...
SetCmdName (CMDNAME_ExampleTool, 0); // For command prompt...
return true;
}
}; // ExampleTool
/*---------------------------------------------------------------------------------**//**
* @bsimethod
+---------------+---------------+---------------+---------------+---------------+------*/
Private void exampleToolCommand
(
char* string,
Inputq_element* iqel
)
{
ExampleTool* tool = new ExampleTool ();
tool->InstallTool ();
}