From 68c8d15ed4c42810384efb8ab1697d2ca91cbf24 Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Fri, 21 Oct 2011 15:55:20 +0100 Subject: [PATCH] Improve split view delegate error handling. Fixed: if the split view delegate sent non numeric responses when asked to constrain divider positions, subviews would be resized with corrupt size information, which in turn could lead to infinite loops and redraw errors. These bad results are now handled more gracefully. --- AppKit/CPSplitView.j | 24 +++++++++++++++++++++--- Foundation/Foundation.h | 2 ++ 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 Foundation/Foundation.h diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index 23af7db60..5c1bdc99c 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "../Foundation/Foundation.h" + @import "CPButtonBar.j" @import "CPImage.j" @import "CPView.j" @@ -603,7 +605,15 @@ var CPSplitViewHorizontalImage = nil, { // not sure where this should override other positions? if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)]) - position = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex]; + { + var proposedPosition = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex]; + + // Silently ignore bad positions which could result from odd delegate responses. We don't want these + // bad results to go into the system and cause havoc with frame sizes as the split view tries to resize + // its subviews. + if (_IS_NUMERIC(proposedPosition)) + position = proposedPosition; + } var proposedMax = [self maxPossiblePositionOfDividerAtIndex:dividerIndex], proposedMin = [self minPossiblePositionOfDividerAtIndex:dividerIndex], @@ -611,10 +621,18 @@ var CPSplitViewHorizontalImage = nil, actualMin = proposedMin; if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)]) - actualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex]; + { + var proposedActualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex]; + if (_IS_NUMERIC(proposedActualMin)) + actualMin = proposedActualMin; + } if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)]) - actualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex]; + { + var proposedActualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex]; + if (_IS_NUMERIC(proposedActualMax)) + actualMax = proposedActualMax; + } var viewA = _subviews[dividerIndex], realPosition = MAX(MIN(position, actualMax), actualMin); diff --git a/Foundation/Foundation.h b/Foundation/Foundation.h new file mode 100644 index 000000000..b5666e138 --- /dev/null +++ b/Foundation/Foundation.h @@ -0,0 +1,2 @@ +// By Christian C. Salvadó, http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric/1830844#1830844 +#define _IS_NUMERIC(n) (!isNaN(parseFloat(n)) && isFinite(n))