Commit 55300fa7 authored by mlarsen's avatar mlarsen

Adding the ability to pick a range on nodes or zones


git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@29956 18c085ea-50e0-402c-830e-de6fd14e8384
parent d77ee51c
......@@ -227,6 +227,7 @@ void PickAttributes::Init()
hasMixedGhostTypes = -1;
linesData = false;
showPickHighlight = false;
notifyEnabled = true;
inputTopoDim = -1;
meshCoordType = XY;
createSpreadsheet = false;
......@@ -348,6 +349,7 @@ void PickAttributes::Copy(const PickAttributes &obj)
hasMixedGhostTypes = obj.hasMixedGhostTypes;
linesData = obj.linesData;
showPickHighlight = obj.showPickHighlight;
notifyEnabled = obj.notifyEnabled;
inputTopoDim = obj.inputTopoDim;
meshCoordType = obj.meshCoordType;
createSpreadsheet = obj.createSpreadsheet;
......@@ -615,6 +617,7 @@ PickAttributes::operator == (const PickAttributes &obj) const
(hasMixedGhostTypes == obj.hasMixedGhostTypes) &&
(linesData == obj.linesData) &&
(showPickHighlight == obj.showPickHighlight) &&
(notifyEnabled == obj.notifyEnabled) &&
(inputTopoDim == obj.inputTopoDim) &&
(meshCoordType == obj.meshCoordType) &&
(createSpreadsheet == obj.createSpreadsheet) &&
......@@ -830,6 +833,7 @@ PickAttributes::SelectAll()
Select(ID_hasMixedGhostTypes, (void *)&hasMixedGhostTypes);
Select(ID_linesData, (void *)&linesData);
Select(ID_showPickHighlight, (void *)&showPickHighlight);
Select(ID_notifyEnabled, (void *)&notifyEnabled);
Select(ID_inputTopoDim, (void *)&inputTopoDim);
Select(ID_meshCoordType, (void *)&meshCoordType);
Select(ID_createSpreadsheet, (void *)&createSpreadsheet);
......@@ -1030,6 +1034,7 @@ PickAttributes::CreateNode(DataNode *parentNode, bool completeSave, bool forceAd
// hasMixedGhostTypes is not persistent and should not be saved.
// linesData is not persistent and should not be saved.
// showPickHighlight is not persistent and should not be saved.
// notifyEnabled is not persistent and should not be saved.
// inputTopoDim is not persistent and should not be saved.
// meshCoordType is not persistent and should not be saved.
if(completeSave || !FieldsEqual(ID_createSpreadsheet, &defaultObject))
......@@ -1168,6 +1173,7 @@ PickAttributes::SetFromNode(DataNode *parentNode)
// hasMixedGhostTypes is not persistent and was not saved.
// linesData is not persistent and was not saved.
// showPickHighlight is not persistent and was not saved.
// notifyEnabled is not persistent and was not saved.
// inputTopoDim is not persistent and was not saved.
// meshCoordType is not persistent and was not saved.
if((node = searchNode->GetNode("createSpreadsheet")) != 0)
......@@ -1630,6 +1636,13 @@ PickAttributes::SetShowPickHighlight(bool showPickHighlight_)
Select(ID_showPickHighlight, (void *)&showPickHighlight);
}
void
PickAttributes::SetNotifyEnabled(bool notifyEnabled_)
{
notifyEnabled = notifyEnabled_;
Select(ID_notifyEnabled, (void *)&notifyEnabled);
}
void
PickAttributes::SetInputTopoDim(int inputTopoDim_)
{
......@@ -2231,6 +2244,12 @@ PickAttributes::GetShowPickHighlight() const
return showPickHighlight;
}
bool
PickAttributes::GetNotifyEnabled() const
{
return notifyEnabled;
}
int
PickAttributes::GetInputTopoDim() const
{
......@@ -2777,6 +2796,7 @@ PickAttributes::GetFieldName(int index) const
case ID_hasMixedGhostTypes: return "hasMixedGhostTypes";
case ID_linesData: return "linesData";
case ID_showPickHighlight: return "showPickHighlight";
case ID_notifyEnabled: return "notifyEnabled";
case ID_inputTopoDim: return "inputTopoDim";
case ID_meshCoordType: return "meshCoordType";
case ID_createSpreadsheet: return "createSpreadsheet";
......@@ -2873,6 +2893,7 @@ PickAttributes::GetFieldType(int index) const
case ID_hasMixedGhostTypes: return FieldType_int;
case ID_linesData: return FieldType_bool;
case ID_showPickHighlight: return FieldType_bool;
case ID_notifyEnabled: return FieldType_bool;
case ID_inputTopoDim: return FieldType_int;
case ID_meshCoordType: return FieldType_enum;
case ID_createSpreadsheet: return FieldType_bool;
......@@ -2969,6 +2990,7 @@ PickAttributes::GetFieldTypeName(int index) const
case ID_hasMixedGhostTypes: return "int";
case ID_linesData: return "bool";
case ID_showPickHighlight: return "bool";
case ID_notifyEnabled: return "bool";
case ID_inputTopoDim: return "int";
case ID_meshCoordType: return "enum";
case ID_createSpreadsheet: return "bool";
......@@ -3353,6 +3375,11 @@ PickAttributes::FieldsEqual(int index_, const AttributeGroup *rhs) const
retval = (showPickHighlight == obj.showPickHighlight);
}
break;
case ID_notifyEnabled:
{ // new scope
retval = (notifyEnabled == obj.notifyEnabled);
}
break;
case ID_inputTopoDim:
{ // new scope
retval = (inputTopoDim == obj.inputTopoDim);
......@@ -4630,6 +4657,41 @@ PickAttributes::AddLine(const double *_c0, const double *_c1, const int &pos)
}
// ****************************************************************************
// Method: PickAttributes::Notify
//
// Purpose:
// Notifies the observers. This is an override of an inherented method that
// adds the ability to disable notification. This is desirable when picking
// ranges of elements, possibly 100+, for visual reasons only and not to
// encur the overhead of waiting for all the tabs to appear in the GUI.
//
// Programmer: Matt Larsen
// Creation: December 12, 2016
//
// Modifications:
//
// ****************************************************************************
//
void
PickAttributes::Notify()
{
//
// Check to see if we want to notify the window
//
if(notifyEnabled)
{
// Call the base class's Notify method.
Subject::Notify();
// Now that all the Obsevrers have been called, unselect all the
// attributes.
UnSelectAll();
}
}
// ****************************************************************************
// Method: PickAttributes::ClearLines
//
......
......@@ -1241,6 +1241,44 @@ PickAttributes::AddLine(const double *_c0, const double *_c1, const int &pos)
}
Function: Notify
Declaration: void Notify();
Definition:
// ****************************************************************************
// Method: PickAttributes::Notify
//
// Purpose:
// Notifies the observers. This is an override of an inherented method that
// adds the ability to disable notification. This is desirable when picking
// ranges of elements, possibly 100+, for visual reasons only and not to
// encur the overhead of waiting for all the tabs to appear in the GUI.
//
// Programmer: Matt Larsen
// Creation: December 12, 2016
//
// Modifications:
//
// ****************************************************************************
//
void
PickAttributes::Notify()
{
//
// Check to see if we want to notify the window
//
if(notifyEnabled)
{
// Call the base class's Notify method.
Subject::Notify();
// Now that all the Obsevrers have been called, unselect all the
// attributes.
UnSelectAll();
}
}
Function: ClearLines
Declaration: void ClearLines();
Definition:
......@@ -1489,3 +1527,4 @@ PyPickAttributes_CallLogRoutine(Subject *subj, void *data)
}
}
......@@ -203,6 +203,7 @@ public:
void SetHasMixedGhostTypes(int hasMixedGhostTypes_);
void SetLinesData(bool linesData_);
void SetShowPickHighlight(bool showPickHighlight_);
void SetNotifyEnabled(bool notifyEnabled_);
void SetInputTopoDim(int inputTopoDim_);
void SetMeshCoordType(CoordinateType meshCoordType_);
void SetCreateSpreadsheet(bool createSpreadsheet_);
......@@ -303,6 +304,7 @@ public:
int GetHasMixedGhostTypes() const;
bool GetLinesData() const;
bool GetShowPickHighlight() const;
bool GetNotifyEnabled() const;
int GetInputTopoDim() const;
CoordinateType GetMeshCoordType() const;
bool GetCreateSpreadsheet() const;
......@@ -364,6 +366,7 @@ public:
void SetRayPoint1(const doubleVector &);
void SetRayPoint2(const doubleVector &);
void AddLine(const double *_c0, const double *_c1, const int &pos);
void Notify();
void ClearLines();
void CreateOutputMapNode(MapNode &m, bool withLetter);
void CreateXMLString(std::string &os, bool withLetter = true);
......@@ -433,6 +436,7 @@ public:
ID_hasMixedGhostTypes,
ID_linesData,
ID_showPickHighlight,
ID_notifyEnabled,
ID_inputTopoDim,
ID_meshCoordType,
ID_createSpreadsheet,
......@@ -511,6 +515,7 @@ private:
int hasMixedGhostTypes;
bool linesData;
bool showPickHighlight;
bool notifyEnabled;
int inputTopoDim;
int meshCoordType;
bool createSpreadsheet;
......@@ -525,6 +530,6 @@ private:
static const char *TypeMapFormatString;
static const private_tmfs_t TmfsStruct;
};
#define PICKATTRIBUTES_TMFS "s*bbbbbbbbbsbiiii*d*iissDDDd*DDsii*s*s*s*s*s*ba*s*bsbbbbbbssi*bbbbbii*bbbiibbiibssbimm"
#define PICKATTRIBUTES_TMFS "s*bbbbbbbbbsbiiii*d*iissDDDd*DDsii*s*s*s*s*s*ba*s*bsbbbbbbssi*bbbbbii*bbbiibbbiibssbimm"
#endif
......@@ -196,6 +196,9 @@
<Field name="showPickHighlight" label="showPickHighlight" type="bool" internal="false" persistent="false">
false
</Field>
<Field name="notifyEnabled" label="notifyEnabled" type="bool" internal="false" persistent="false">
true
</Field>
<Field name="inputTopoDim" label="inputTopoDim" type="int" internal="true" persistent="false">
-1
</Field>
......@@ -234,6 +237,8 @@
</Function>
<Function name="AddLine" user="true" member="true">
</Function>
<Function name="Notify" user="true" member="true">
</Function>
<Function name="ClearLines" user="true" member="true">
</Function>
<Function name="CreateOutputMapNode" user="true" member="true">
......
......@@ -1187,3 +1187,129 @@ StringHelpers::UpperCase(const std::string &src)
return tmp;
}
// ****************************************************************************
// Method: StringHelpers::StringToInt
//
// Purpose:
// Utility method to convert a string to an int. returns true if the
// conversion was successful.
// Arguments
// input: the string to convert to an int
// output: an integer representation of the string
//
// Returns:
// boolean indicating if the conversion was successful.
//
// Progammer: Matt Larsen
// Creation: Dec 12, 2016
//
// Modifications:
//
// ****************************************************************************
bool
StringHelpers::StringToInt(const string &input, int &output)
{
bool valid
= input.find_first_not_of(" 0123456789") == std::string::npos;
if(!valid) return false;
output = atoi(input.c_str());
//
// Check for conversion errors
//
if(output == 0 && input != "0")
return false;
return true;
}
//
// ****************************************************************************
// Method: StringHelpers::ParseRange
//
// Purpose:
// To parse a string that constains a range of positive integers
// in a comma separated list. For example, "1,5-6,10" becomes "1,5,6,10".
//
//
// Progammer: Matt Larsen
// Creation: Dec 12, 2016
//
// Modifications:
//
// ****************************************************************************
bool
StringHelpers::ParseRange(const string range, std::vector<int> &list)
{
std::vector<std::string> rangeTokens = StringHelpers::split(range, ',');
bool parseError = false;
for(int i =0; i < rangeTokens.size(); ++i)
{
int first = 0;
int last = 0;
std::vector<std::string> currentRange
= StringHelpers::split(rangeTokens.at(i),'-');
const int size = static_cast<int>(currentRange.size());
//
// Check to see that we have exactly one or two items
//
if(size < 1 || size > 2)
{
parseError = true;
continue;
}
size_t dashPos = rangeTokens[i].find("-");
bool hasDash = dashPos != std::string::npos;
if(hasDash && size == 1)
{
parseError = true;
continue;
}
bool valid = StringHelpers::StringToInt(currentRange[0], first);
if(!valid)
{
parseError = true;
continue;
}
if(size == 1)
{
list.push_back(first);
continue;
}
valid = StringHelpers::StringToInt(currentRange[1], last);
if(!valid)
{
parseError = true;
continue;
}
//
// Allow for backward range and don't go into inf loop
//
if(first > last)
{
int tmp = first;
first = last;
last = tmp;
}
for(int n = first; n <= last; ++n)
{
list.push_back(n);
}
}
return parseError;
}
......@@ -116,6 +116,8 @@ namespace StringHelpers
const std::string &str_b);
std::string UTILITY_API UpperCase(const std::string &src);
bool UTILITY_API StringToInt(const std::string &, int &);
bool UTILITY_API ParseRange(const std::string , std::vector<int> &);
// ****************************************************************************
// Function: str_to_u_numeric
//
......
......@@ -390,6 +390,44 @@ QvisPickQueryWidget::GetElement(int *num)
}
// ****************************************************************************
// Method: QvisPickQueryWidget::GetElementRange
//
// Purpose:
// Retrieves the element range from the text field.
//
// Arguments:
// range : output value that will be non-empty if the text field constains
// a possible range. Parsing occurs in the view query manager
//
// Returns: True if it worked.
//
// Programmer: Matt Larsen
// Creation: December 12, 2016
//
// Modifications:
//
// ****************************************************************************
bool
QvisPickQueryWidget::GetElementRange(std::string &range)
{
QString temp(element->displayText().simplified());
bool okay = !temp.isEmpty();
if (okay)
{
std::string possibleRange = temp.toStdString();
size_t hasComma = possibleRange.find(",");
size_t hasDash = possibleRange.find("-");
if(hasComma != std::string::npos || hasDash != std::string::npos)
{
range = possibleRange;
}
else range = "";
}
return okay;
}
// ****************************************************************************
// Method: QvisPickQueryWidget::GetElementType
//
......@@ -457,6 +495,7 @@ QvisPickQueryWidget::GetQueryParameters(MapNode &params)
int curvePlotType = GetPlotType();
int preserveCoord = (int) GetTimePreservesCoord();
int dom = 0, el = 0;
std::string range;
switch (pickType->currentIndex())
{
case 0: // Pick by zone coordinate
......@@ -482,6 +521,8 @@ QvisPickQueryWidget::GetQueryParameters(MapNode &params)
noerrors = false;
if (!GetDomain(&dom))
noerrors = false;
if (!GetElementRange(range))
noerrors = false;
if (noerrors)
{
if (GetElementType() == 0)
......@@ -495,6 +536,8 @@ QvisPickQueryWidget::GetQueryParameters(MapNode &params)
case 3: // Pick by global element
if (!GetElement(&el))
noerrors = false;
if (!GetElementRange(range))
noerrors = false;
if (noerrors)
{
if (GetElementType() == 0)
......@@ -513,6 +556,8 @@ QvisPickQueryWidget::GetQueryParameters(MapNode &params)
{
params["curve_plot_type"] = curvePlotType;
params["preserve_coord"] = preserveCoord;
if(range != "")
params["pick_range"] = range;
}
return noerrors;
}
......
......@@ -62,6 +62,9 @@ class MapNode;
// Creation: June 9, 2011
//
// Modifications:
// Matt Larsen, December 12, 2016
// added GetElementRange to detect if a range of picks has been entered in
// the pick window.
//
// ****************************************************************************
......@@ -86,6 +89,7 @@ private:
bool GetPoint(double *pt);
bool GetDomain(int *);
bool GetElement(int *);
bool GetElementRange(std::string &);
int GetPlotType(void);
int GetElementType(void);
bool GetTimePreservesCoord(void);
......
......@@ -59,7 +59,7 @@ import java.lang.Double;
public class PickAttributes extends AttributeSubject
{
private static int PickAttributes_numAdditionalAtts = 72;
private static int PickAttributes_numAdditionalAtts = 73;
// Enum values
public final static int PICKTYPE_ZONE = 0;
......@@ -160,6 +160,7 @@ public class PickAttributes extends AttributeSubject
hasMixedGhostTypes = -1;
linesData = false;
showPickHighlight = false;
notifyEnabled = true;
inputTopoDim = -1;
meshCoordType = COORDINATETYPE_XY;
createSpreadsheet = false;
......@@ -254,6 +255,7 @@ public class PickAttributes extends AttributeSubject
hasMixedGhostTypes = -1;
linesData = false;
showPickHighlight = false;
notifyEnabled = true;
inputTopoDim = -1;
meshCoordType = COORDINATETYPE_XY;
createSpreadsheet = false;
......@@ -414,6 +416,7 @@ public class PickAttributes extends AttributeSubject
hasMixedGhostTypes = obj.hasMixedGhostTypes;
linesData = obj.linesData;
showPickHighlight = obj.showPickHighlight;
notifyEnabled = obj.notifyEnabled;
inputTopoDim = obj.inputTopoDim;
meshCoordType = obj.meshCoordType;
createSpreadsheet = obj.createSpreadsheet;
......@@ -656,6 +659,7 @@ public class PickAttributes extends AttributeSubject
(hasMixedGhostTypes == obj.hasMixedGhostTypes) &&
(linesData == obj.linesData) &&
(showPickHighlight == obj.showPickHighlight) &&
(notifyEnabled == obj.notifyEnabled) &&
(inputTopoDim == obj.inputTopoDim) &&
(meshCoordType == obj.meshCoordType) &&
(createSpreadsheet == obj.createSpreadsheet) &&
......@@ -1090,58 +1094,64 @@ public class PickAttributes extends AttributeSubject
Select(62);
}
public void SetNotifyEnabled(boolean notifyEnabled_)
{
notifyEnabled = notifyEnabled_;
Select(63);
}
public void SetInputTopoDim(int inputTopoDim_)
{
inputTopoDim = inputTopoDim_;
Select(63);
Select(64);
}
public void SetMeshCoordType(int meshCoordType_)
{
meshCoordType = meshCoordType_;
Select(64);
Select(65);
}
public void SetCreateSpreadsheet(boolean createSpreadsheet_)
{
createSpreadsheet = createSpreadsheet_;
Select(65);
Select(66);
}
public void SetSubsetName(String subsetName_)
{
subsetName = subsetName_;
Select(66);
Select(67);
}
public void SetFloatFormat(String floatFormat_)
{
floatFormat = floatFormat_;
Select(67);
Select(68);
}
public void SetTimePreserveCoord(boolean timePreserveCoord_)
{
timePreserveCoord = timePreserveCoord_;
Select(68);
Select(69);
}
public void SetTimeCurveType(int timeCurveType_)
{
timeCurveType = timeCurveType_;
Select(69);
Select(70);
}
public void SetTimeOptions(MapNode timeOptions_)
{
timeOptions = timeOptions_;
Select(70);
Select(71);
}
public void SetPlotRequested(MapNode plotRequested_)
{
plotRequested = plotRequested_;
Select(71);
Select(72);
}
// Property getting methods
......@@ -1208,6 +1218,7 @@ public class PickAttributes extends AttributeSubject
public int GetHasMixedGhostTypes() { return hasMixedGhostTypes; }
public boolean GetLinesData() { return linesData; }
public boolean GetShowPickHighlight() { return showPickHighlight; }
public boolean GetNotifyEnabled() { return notifyEnabled; }
public int GetInputTopoDim() { return inputTopoDim; }
public int GetMeshCoordType() { return meshCoordType; }
public boolean GetCreateSpreadsheet() { return createSpreadsheet; }
......@@ -1355,22 +1366,24 @@ public class PickAttributes extends AttributeSubject
if(WriteSelect(62, buf))
buf.WriteBool(showPickHighlight);
if(WriteSelect(63, buf))
buf.WriteInt(inputTopoDim);
buf.WriteBool(notifyEnabled);
if(WriteSelect(64, buf))
buf.WriteInt(meshCoordType);
buf.WriteInt(inputTopoDim);
if(WriteSelect(65, buf))
buf.WriteBool(createSpreadsheet);
buf.WriteInt(meshCoordType);
if(WriteSelect(66, buf))
buf.WriteString(subsetName);
buf.WriteBool(createSpreadsheet);
if(WriteSelect(67, buf))
buf.WriteString(floatFormat);
buf.WriteString(subsetName);
if(WriteSelect(68, buf))
buf.WriteBool(timePreserveCoord);
buf.WriteString(floatFormat);
if(WriteSelect(69, buf))
buf.WriteInt(timeCurveType);
buf.WriteBool(timePreserveCoord);
if(WriteSelect(70, buf))
timeOptions.Write(buf);
buf.WriteInt(timeCurveType);
if(WriteSelect(71, buf))
timeOptions.Write(buf);
if(WriteSelect(72, buf))
plotRequested.Write(buf);
}
......@@ -1578,30 +1591,33 @@ public class PickAttributes extends AttributeSubject
SetShowPickHighlight(buf.ReadBool());
break;
case 63:
SetInputTopoDim(buf.ReadInt());
SetNotifyEnabled(buf.ReadBool());
break;
case 64:
SetMeshCoordType(buf.ReadInt());
SetInputTopoDim(buf.ReadInt());
break;
case 65:
SetCreateSpreadsheet(buf.ReadBool());
SetMeshCoordType(buf.ReadInt());
break;
case 66:
SetSubsetName(buf.ReadString());
SetCreateSpreadsheet(buf.ReadBool());
break;
case 67:
SetFloatFormat(buf.ReadString());
SetSubsetName(buf.ReadString());
break;
case 68:
SetTimePreserveCoord(buf.ReadBool());
SetFloatFormat(buf.ReadString());
break;
case 69:
SetTimeCurveType(buf.ReadInt());
SetTimePreserveCoord(buf.ReadBool());
break;
case 70:
timeOptions.Read(buf);
SetTimeCurveType(buf.ReadInt());
break;
case 71:
timeOptions.Read(buf);
break;
case 72:
plotRequested.Read(buf);
break;
}
......@@ -1695,6 +1711,7 @@ public class PickAttributes extends AttributeSubject
str = str + intToString("hasMixedGhostTypes", hasMixedGhostTypes, indent) + "\n";
str = str + boolToString("linesData", linesData, indent) + "\n";
str = str + boolToString("showPickHighlight", showPickHighlight, indent) + "\n";
str = str + boolToString("notifyEnabled", notifyEnabled, indent) + "\n";
str = str + intToString("inputTopoDim", inputTopoDim, indent) + "\n";
str = str + indent + "meshCoordType = ";
if(meshCoordType == COORDINATETYPE_XY)
......@@ -1817,6 +1834,7 @@ public class PickAttributes extends AttributeSubject
private int hasMixedGhostTypes;
private boolean linesData;
private boolean showPickHighlight;
private boolean notifyEnabled;
private int inputTopoDim;
private int meshCoordType;
private boolean createSpreadsheet;
......
......@@ -65,6 +65,7 @@
#include <QueryAttributes.h>
#include <QueryList.h>
#include <QueryOverTimeAttributes.h>
#include <StringHelpers.h>
#include <ViewerActionManager.h>
#include <ViewerEngineManagerInterface.h>
#include <ParsingExprList.h>
......@@ -90,6 +91,7 @@
#include <stdio.h>
#include <set>
#include <sstream>
#include <string>
#include <vector>
......@@ -3261,7 +3263,6 @@ ViewerQueryManager::HandlePickCache()
handlingCache = false;
}
// ****************************************************************************
// Method: ViewerQueryManager::PointQuery
//
......@@ -3303,6 +3304,9 @@ ViewerQueryManager::HandlePickCache()
// Kathleen Biagas, Tue Mar 25 07:56:00 PDT 2014
// Check if 'vars' is a single string.
//
// Matt Larseb, Mon Dec 12 08:11:00 PDT 2016
// Adding detection of a range of picks and looping over them.
//