Relax range setting constraints for arrays.

- VariablesView now detects if a container's range is fixed or not,
and uses that to adjust both the prompt it displays and whether or not
the parsed ranges are bounds checked.
- ArrayValueNode now returns the currently user-set range rather than
the dimension constraints, since those might not always be accurate.
This commit is contained in:
Rene Gollent
2013-05-20 19:03:53 -04:00
parent 570241e8b7
commit f297d6591d
5 changed files with 61 additions and 24 deletions
@@ -1593,11 +1593,17 @@ VariablesView::MessageReceived(BMessage* message)
->SelectionModel()->NodeAt(0); ->SelectionModel()->NodeAt(0);
int32 lowerBound, upperBound; int32 lowerBound, upperBound;
ValueNode* valueNode = node->NodeChild()->Node(); ValueNode* valueNode = node->NodeChild()->Node();
if (!valueNode->IsRangedContainer()) if (!valueNode->IsRangedContainer()) {
valueNode = node->ChildAt(0)->NodeChild()->Node(); valueNode = node->ChildAt(0)->NodeChild()->Node();
if (!valueNode->IsRangedContainer())
break;
}
if (valueNode->SupportedChildRange(lowerBound, upperBound) != B_OK) bool fixedRange = valueNode->IsContainerRangeFixed();
if (valueNode->SupportedChildRange(lowerBound, upperBound)
!= B_OK) {
break; break;
}
BMessage* promptMessage = new(std::nothrow) BMessage( BMessage* promptMessage = new(std::nothrow) BMessage(
MSG_SET_CONTAINER_RANGE); MSG_SET_CONTAINER_RANGE);
@@ -1606,9 +1612,16 @@ VariablesView::MessageReceived(BMessage* message)
ObjectDeleter<BMessage> messageDeleter(promptMessage); ObjectDeleter<BMessage> messageDeleter(promptMessage);
promptMessage->AddPointer("node", node); promptMessage->AddPointer("node", node);
promptMessage->AddBool("fixedRange", fixedRange);
BString infoText; BString infoText;
infoText.SetToFormat("Allowed range: %" B_PRId32 if (fixedRange) {
"-%" B_PRId32 ".", lowerBound, upperBound); infoText.SetToFormat("Allowed range: %" B_PRId32
"-%" B_PRId32 ".", lowerBound, upperBound);
} else {
infoText.SetToFormat("Current range: %" B_PRId32
"-%" B_PRId32 ".", lowerBound, upperBound);
}
PromptWindow* promptWindow = new(std::nothrow) PromptWindow( PromptWindow* promptWindow = new(std::nothrow) PromptWindow(
"Set Range", "Range: ", infoText.String(), BMessenger(this), "Set Range", "Range: ", infoText.String(), BMessenger(this),
promptMessage); promptMessage);
@@ -1631,13 +1644,15 @@ VariablesView::MessageReceived(BMessage* message)
if (valueNode->SupportedChildRange(lowerBound, upperBound) != B_OK) if (valueNode->SupportedChildRange(lowerBound, upperBound) != B_OK)
break; break;
bool fixedRange = message->FindBool("fixedRange");
BString rangeExpression = message->FindString("text"); BString rangeExpression = message->FindString("text");
if (rangeExpression.Length() == 0) if (rangeExpression.Length() == 0)
break; break;
RangeList ranges; RangeList ranges;
status_t result = UiUtils::ParseRangeExpression( status_t result = UiUtils::ParseRangeExpression(
rangeExpression, lowerBound, upperBound, ranges); rangeExpression, lowerBound, upperBound, fixedRange, ranges);
if (result != B_OK) if (result != B_OK)
break; break;
@@ -411,7 +411,7 @@ static status_t ParseRangeString(BString& rangeString, int32& lowerBound,
/*static*/ status_t /*static*/ status_t
UiUtils::ParseRangeExpression(const BString& rangeExpression, int32 lowerBound, UiUtils::ParseRangeExpression(const BString& rangeExpression, int32 lowerBound,
int32 upperBound, RangeList& _output) int32 upperBound, bool fixedRange, RangeList& _output)
{ {
if (rangeExpression.IsEmpty()) if (rangeExpression.IsEmpty())
return B_BAD_DATA; return B_BAD_DATA;
@@ -440,7 +440,8 @@ UiUtils::ParseRangeExpression(const BString& rangeExpression, int32 lowerBound,
if (result != B_OK) if (result != B_OK)
return result; return result;
if (lowValue < lowerBound || highValue > upperBound)
if (fixedRange && (lowValue < lowerBound || highValue > upperBound))
return B_BAD_VALUE; return B_BAD_VALUE;
result = _output.AddRange(lowValue, highValue); result = _output.AddRange(lowValue, highValue);
@@ -55,6 +55,7 @@ public:
static status_t ParseRangeExpression( static status_t ParseRangeExpression(
const BString& rangeString, const BString& rangeString,
int32 lowerBound, int32 upperBound, int32 lowerBound, int32 upperBound,
bool fixedRange,
RangeList& _output); RangeList& _output);
}; };
@@ -31,7 +31,10 @@ AbstractArrayValueNode::AbstractArrayValueNode(ValueNodeChild* nodeChild,
: :
ValueNode(nodeChild), ValueNode(nodeChild),
fType(type), fType(type),
fDimension(dimension) fDimension(dimension),
fLowerBound(0),
fUpperBound(0),
fBoundsInitialized(false)
{ {
fType->AcquireReference(); fType->AcquireReference();
} }
@@ -106,6 +109,8 @@ void
AbstractArrayValueNode::ClearChildren() AbstractArrayValueNode::ClearChildren()
{ {
fChildren.MakeEmpty(); fChildren.MakeEmpty();
fLowerBound = 0;
fUpperBound = 0;
if (fContainer != NULL) if (fContainer != NULL)
fContainer->NotifyValueNodeChildrenDeleted(this); fContainer->NotifyValueNodeChildrenDeleted(this);
} }
@@ -121,14 +126,22 @@ AbstractArrayValueNode::CreateChildrenInRange(int32 lowIndex,
int32 dimensionCount = fType->CountDimensions(); int32 dimensionCount = fType->CountDimensions();
bool isFinalDimension = fDimension + 1 == dimensionCount; bool isFinalDimension = fDimension + 1 == dimensionCount;
status_t error = B_OK;
int32 lowerBound, upperBound; if (!fBoundsInitialized) {
if (SupportedChildRange(lowerBound, upperBound) == B_OK) { int32 lowerBound, upperBound;
// clamp inputs to supported range. error = SupportedChildRange(lowerBound, upperBound);
if (lowIndex < lowerBound) if (error != B_OK)
lowIndex = lowerBound; return error;
if (highIndex > upperBound)
highIndex = upperBound; fLowerBound = lowerBound;
fUpperBound = upperBound;
fBoundsInitialized = true;
} else {
if (lowIndex < fLowerBound)
fLowerBound = lowIndex;
if (highIndex > fUpperBound)
fUpperBound = highIndex;
} }
// create children for the array elements // create children for the array elements
@@ -166,19 +179,23 @@ status_t
AbstractArrayValueNode::SupportedChildRange(int32& lowIndex, AbstractArrayValueNode::SupportedChildRange(int32& lowIndex,
int32& highIndex) const int32& highIndex) const
{ {
ArrayDimension* dimension = fType->DimensionAt(fDimension); if (!fBoundsInitialized) {
ArrayDimension* dimension = fType->DimensionAt(fDimension);
SubrangeType* dimensionType = dynamic_cast<SubrangeType*>( SubrangeType* dimensionType = dynamic_cast<SubrangeType*>(
dimension->GetType()); dimension->GetType());
if (dimensionType != NULL) { if (dimensionType != NULL) {
lowIndex = dimensionType->LowerBound().ToInt32(); lowIndex = dimensionType->LowerBound().ToInt32();
highIndex = dimensionType->UpperBound().ToInt32(); highIndex = dimensionType->UpperBound().ToInt32();
} else
return B_OK; return B_UNSUPPORTED;
} else {
lowIndex = fLowerBound;
highIndex = fUpperBound;
} }
return B_UNSUPPORTED; return B_OK;
} }
@@ -54,6 +54,9 @@ protected:
ArrayType* fType; ArrayType* fType;
ChildList fChildren; ChildList fChildren;
int32 fDimension; int32 fDimension;
int32 fLowerBound;
int32 fUpperBound;
bool fBoundsInitialized;
}; };