Merge branch 'refs/heads/master' into upstream_master
@@ -631,7 +631,10 @@ CPCriticalAlertStyle = 2;
|
||||
- (@action)_takeReturnCodeFrom:(id)aSender
|
||||
{
|
||||
if ([_window isSheet])
|
||||
{
|
||||
[CPApp endSheet:_window returnCode:[aSender tag]];
|
||||
[_window orderOut:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[CPApp abortModal];
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
|
||||
|
||||
var CPMainCibFile = @"CPMainCibFile",
|
||||
CPMainCibFileHumanFriendly = @"Main cib file base name";
|
||||
CPMainCibFileHumanFriendly = @"Main cib file base name",
|
||||
CPEventModifierFlags = 0;
|
||||
|
||||
CPApp = nil;
|
||||
|
||||
@@ -575,6 +576,7 @@ CPRunContinuesResponse = -1002;
|
||||
- (void)sendEvent:(CPEvent)anEvent
|
||||
{
|
||||
_currentEvent = anEvent;
|
||||
CPEventModifierFlags = [anEvent modifierFlags];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
var willPropagate = [[[anEvent window] platformWindow] _willPropagateCurrentDOMEvent];
|
||||
@@ -931,15 +933,21 @@ CPRunContinuesResponse = -1002;
|
||||
*/
|
||||
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
|
||||
{
|
||||
var styleMask = [aSheet styleMask];
|
||||
if (!(styleMask & CPDocModalWindowMask))
|
||||
if ([aWindow isSheet])
|
||||
{
|
||||
[CPException raise:CPInternalInconsistencyException reason:@"Currently only CPDocModalWindowMask style mask is supported for attached sheets"];
|
||||
[CPException raise:CPInternalInconsistencyException reason:@"The target window of beginSheet: cannot be a sheet"];
|
||||
return;
|
||||
}
|
||||
|
||||
[aWindow orderFront:self];
|
||||
[aSheet setPlatformWindow:[aWindow platformWindow]];
|
||||
[aSheet._windowView _enableSheet:YES];
|
||||
|
||||
// -dw- if a sheet is already visible, we skip this since it serves no purpose and causes
|
||||
// orderOut: to be called on the sheet, which is not what we want.
|
||||
if (![aWindow isVisible])
|
||||
{
|
||||
[aWindow orderFront:self];
|
||||
[aSheet setPlatformWindow:[aWindow platformWindow]];
|
||||
}
|
||||
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
|
||||
}
|
||||
|
||||
@@ -968,7 +976,7 @@ CPRunContinuesResponse = -1002;
|
||||
if (context != nil && context["sheet"] === sheet)
|
||||
{
|
||||
context["returnCode"] = returnCode;
|
||||
[aWindow _detachSheetWindow];
|
||||
[aWindow _endSheet];
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1190,7 +1198,10 @@ _CPRunModalLoop = function(anEvent)
|
||||
// yet it works when there is a modal window. Maybe it starts its own modal session, but interaction with the original
|
||||
// modal window seems to continue working as well. Regardless of correctness, this solution beats popovers not working
|
||||
// at all from sheets.
|
||||
if (theWindow == modalSession._window || [theWindow worksWhenModal] || ([theWindow isKindOfClass:_CPAttachedWindow] && [[theWindow targetView] window] === modalSession._window))
|
||||
if (theWindow == modalSession._window ||
|
||||
[theWindow worksWhenModal] ||
|
||||
[theWindow attachedSheet] == modalSession._window || // -dw- allow modal parent of sheet to be repositioned
|
||||
([theWindow isKindOfClass:_CPAttachedWindow] && [[theWindow targetView] window] === modalSession._window))
|
||||
[theWindow sendEvent:anEvent];
|
||||
};
|
||||
|
||||
@@ -1379,3 +1390,16 @@ var _CPAppBootstrapperActions = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPEvent (CPApplicationModifierFlags)
|
||||
|
||||
/*!
|
||||
Returns the currently pressed modifier flags.
|
||||
*/
|
||||
+ (unsigned)modifierFlags
|
||||
{
|
||||
return CPEventModifierFlags;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -946,36 +946,38 @@
|
||||
_disableSetContent = YES;
|
||||
|
||||
var arrangedObjects = [self arrangedObjects],
|
||||
index = [anIndexSet lastIndex],
|
||||
position = CPNotFound,
|
||||
newSelectionIndexes = [_selectionIndexes copy];
|
||||
|
||||
while (index !== CPNotFound)
|
||||
{
|
||||
var object = [arrangedObjects objectAtIndex:index];
|
||||
|
||||
// First try the simple case which should work if there are no sort descriptors.
|
||||
if ([_contentObject objectAtIndex:index] === object)
|
||||
[_contentObject removeObjectAtIndex:index];
|
||||
else
|
||||
[anIndexSet enumerateIndexesWithOptions:CPEnumerationReverse
|
||||
usingBlock:function(anIndex)
|
||||
{
|
||||
// Since we don't have a reverse mapping between the sorted order and the
|
||||
// unsorted one, we'll just simply have to remove an arbitrary pointer. It might
|
||||
// be the 'wrong' one - as in not the one the user selected - but the wrong
|
||||
// one is still just another pointer to the same object, so the user will not
|
||||
// be able to see any difference.
|
||||
contentIndex = [_contentObject indexOfObjectIdenticalTo:object];
|
||||
[_contentObject removeObjectAtIndex:contentIndex];
|
||||
}
|
||||
[arrangedObjects removeObjectAtIndex:index];
|
||||
var object = [arrangedObjects objectAtIndex:anIndex];
|
||||
|
||||
// Deselect this row if it was selected, and either way shift all selection indexes
|
||||
// following it up by 1.
|
||||
[newSelectionIndexes removeIndex:index];
|
||||
[newSelectionIndexes shiftIndexesStartingAtIndex:index by:-1];
|
||||
// First try the simple case which should work if there are no sort descriptors.
|
||||
if ([_contentObject objectAtIndex:anIndex] === object)
|
||||
[_contentObject removeObjectAtIndex:anIndex];
|
||||
else
|
||||
{
|
||||
// Since we don't have a reverse mapping between the sorted order and the
|
||||
// unsorted one, we'll just simply have to remove an arbitrary pointer. It might
|
||||
// be the 'wrong' one - as in not the one the user selected - but the wrong
|
||||
// one is still just another pointer to the same object, so the user will not
|
||||
// be able to see any difference.
|
||||
contentIndex = [_contentObject indexOfObjectIdenticalTo:object];
|
||||
[_contentObject removeObjectAtIndex:contentIndex];
|
||||
}
|
||||
[arrangedObjects removeObjectAtIndex:anIndex];
|
||||
|
||||
if (!_avoidsEmptySelection || [newSelectionIndexes count] > 1)
|
||||
{
|
||||
[newSelectionIndexes removeIndex:anIndex];
|
||||
[newSelectionIndexes shiftIndexesStartingAtIndex:anIndex by:-1];
|
||||
}
|
||||
else if ([newSelectionIndexes lastIndex] !== anIndex)
|
||||
[newSelectionIndexes shiftIndexesStartingAtIndex:anIndex by:-1];
|
||||
}];
|
||||
|
||||
index = [anIndexSet indexLessThanIndex:index];
|
||||
}
|
||||
// Allow handlesContentAsCompoundValue reverse sets to trigger.
|
||||
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
|
||||
_disableSetContent = NO;
|
||||
|
||||
@@ -67,13 +67,28 @@ CPHTML5DragAndDropSourceYOffBy1 = 1 << 26;
|
||||
|
||||
CPSOPDisabledFromFileURLs = 1 << 27;
|
||||
|
||||
// element.style.font can be set for an element not in the DOM.
|
||||
CPInputSetFontOutsideOfDOM = 1 << 28;
|
||||
|
||||
// Input elements have 1 px of extra padding on the left regardless of padding setting.
|
||||
CPInput1PxLeftPadding = 1 << 29;
|
||||
CPInputOnInputEventFeature = 1 << 30;
|
||||
|
||||
// When an absolutely positioned div (CPView) with an absolutely positioned canvas in it (CPView with drawRect:) moves things on top of the canvas
|
||||
// (subviews) don't redraw correctly. E.g. if you have a bunch of text fields in a CPBox in a sheet which animates in, some of the text fields might
|
||||
// not be visible because the CPBox has a canvas at the bottom and the box moved form offscreen to onscreen.
|
||||
// This bug is probably very related: https://bugs.webkit.org/show_bug.cgi?id=67203
|
||||
CPCanvasParentDrawErrorsOnMovementBug = 1 << 0;
|
||||
|
||||
var USER_AGENT = "",
|
||||
PLATFORM_ENGINE = CPUnknownBrowserEngine,
|
||||
PLATFORM_FEATURES = 0;
|
||||
PLATFORM_FEATURES = 0,
|
||||
PLATFORM_BUGS = 0;
|
||||
|
||||
// default these features to true
|
||||
|
||||
PLATFORM_FEATURES |= CPInputTypeCanBeChangedFeature;
|
||||
PLATFORM_FEATURES |= CPInputSetFontOutsideOfDOM;
|
||||
|
||||
if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
|
||||
USER_AGENT = window.navigator.userAgent;
|
||||
@@ -99,6 +114,9 @@ else if (typeof window !== "undefined" && window.attachEvent) // Must follow Ope
|
||||
PLATFORM_FEATURES |= CPOpacityRequiresFilterFeature;
|
||||
|
||||
PLATFORM_FEATURES &= ~CPInputTypeCanBeChangedFeature;
|
||||
|
||||
// Tested in Internet Explore 8 and 9.
|
||||
PLATFORM_FEATURES &= ~CPInputSetFontOutsideOfDOM;
|
||||
}
|
||||
|
||||
// WebKit
|
||||
@@ -135,8 +153,16 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
|
||||
if (majorVersion < 532 || (majorVersion === 532 && minorVersion < 6))
|
||||
PLATFORM_FEATURES |= CPHTML5DragAndDropSourceYOffBy1;
|
||||
|
||||
// This is supposedly fixed in webkit r123603. Seems to work in Chrome 21 but not Safari 6.0.
|
||||
if (majorVersion < 537)
|
||||
PLATFORM_FEATURES |= CPInput1PxLeftPadding;
|
||||
|
||||
if (USER_AGENT.indexOf("Chrome") === CPNotFound)
|
||||
PLATFORM_FEATURES |= CPSOPDisabledFromFileURLs;
|
||||
|
||||
// Assume this bug was introduced around Safari 5.1/Chrome 16. This could probably be tighter.
|
||||
if (majorVersion > 533)
|
||||
PLATFORM_BUGS |= CPCanvasParentDrawErrorsOnMovementBug;
|
||||
}
|
||||
|
||||
// KHTML
|
||||
@@ -160,6 +186,9 @@ else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
|
||||
|
||||
if (version < 3.0)
|
||||
PLATFORM_FEATURES |= CPJavaScriptMouseWheelValues_8_15;
|
||||
|
||||
// Some day this might be fixed and should be version prefixed. No known fixed version yet.
|
||||
PLATFORM_FEATURES |= CPInput1PxLeftPadding;
|
||||
}
|
||||
|
||||
// Feature Specific Checks
|
||||
@@ -185,6 +214,16 @@ if (typeof document != "undefined")
|
||||
PLATFORM_FEATURES |= CPJavaScriptInnerTextFeature;
|
||||
else if (DOMElement.textContent != undefined)
|
||||
PLATFORM_FEATURES |= CPJavaScriptTextContentFeature;
|
||||
|
||||
var DOMInputElement = document.createElement("input");
|
||||
if ("oninput" in DOMInputElement)
|
||||
PLATFORM_FEATURES |= CPInputOnInputEventFeature;
|
||||
else if (typeof DOMInputElement.setAttribute === "function")
|
||||
{
|
||||
DOMInputElement.setAttribute("oninput", "return;");
|
||||
if (typeof DOMInputElement.oninput === "function")
|
||||
PLATFORM_FEATURES |= CPInputOnInputEventFeature;
|
||||
}
|
||||
}
|
||||
|
||||
function CPFeatureIsCompatible(aFeature)
|
||||
@@ -192,6 +231,11 @@ function CPFeatureIsCompatible(aFeature)
|
||||
return PLATFORM_FEATURES & aFeature;
|
||||
}
|
||||
|
||||
function CPPlatformHasBug(aBug)
|
||||
{
|
||||
return PLATFORM_BUGS & aBug;
|
||||
}
|
||||
|
||||
function CPBrowserIsEngine(anEngine)
|
||||
{
|
||||
return PLATFORM_ENGINE === anEngine;
|
||||
|
||||
@@ -516,7 +516,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
*/
|
||||
- (CPString)stringValue
|
||||
{
|
||||
if (_formatter && _value !== undefined && _value !== nil)
|
||||
if (_formatter && _value !== undefined)
|
||||
{
|
||||
var formattedValue = [self hasThemeState:CPThemeStateEditing] ? [_formatter editingStringForObjectValue:_value] : [_formatter stringForObjectValue:_value];
|
||||
|
||||
|
||||
@@ -204,6 +204,8 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
BOOL _isARepeat;
|
||||
unsigned _keyCode;
|
||||
DOMEvent _DOMEvent;
|
||||
int _data1;
|
||||
int _data2;
|
||||
|
||||
float _deltaX;
|
||||
float _deltaY;
|
||||
@@ -517,6 +519,16 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
return _DOMEvent;
|
||||
}
|
||||
|
||||
- (int)data1
|
||||
{
|
||||
return _data1;
|
||||
}
|
||||
|
||||
- (int)data2
|
||||
{
|
||||
return _data2;
|
||||
}
|
||||
|
||||
// Getting Scroll Wheel Event Information
|
||||
/*!
|
||||
Returns the change in the x-axis for a mouse event.
|
||||
@@ -630,6 +642,29 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
_CPEventPeriodicEventTimer = nil;
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
switch (_type)
|
||||
{
|
||||
case CPKeyDown:
|
||||
case CPKeyUp:
|
||||
case CPFlagsChanged:
|
||||
return [CPString stringWithFormat:@"CPEvent: type=%d loc=%@ time=%.1f flags=0x%X win=%@ winNum=%d ctxt=%@ chars=\"%@\" unmodchars=\"%@\" repeat=%d keyCode=%d", _type, CPStringFromPoint(_location), _timestamp, _modifierFlags, _window, _windowNumber, _context, _characters, _charactersIgnoringModifiers, _isARepeat, _keyCode];
|
||||
case CPLeftMouseDown:
|
||||
case CPLeftMouseUp:
|
||||
case CPRightMouseDown:
|
||||
case CPRightMouseUp:
|
||||
case CPMouseMoved:
|
||||
case CPLeftMouseDragged:
|
||||
case CPRightMouseDragged:
|
||||
case CPMouseEntered:
|
||||
case CPMouseExited:
|
||||
return [CPString stringWithFormat:@"CPEvent: type=%d loc=%@ time=%.1f flags=0x%X win=%@ winNum=%d ctxt=%@ evNum=%d click=%d buttonNumber=%d pressure=%f", _type, CPStringFromPoint(_location), _timestamp, _modifierFlags, _window, _windowNumber, _context, _eventNumber, _clickCount, [self buttonNumber], _pressure];
|
||||
default:
|
||||
return [CPString stringWithFormat:@"CPEvent: type=%d loc=%@ time=%.1f flags=0x%X win=%@ winNum=%d ctxt=%@ subtype=%d data1=%d data2=%d", _type, CPStringFromPoint(_location), _timestamp, _modifierFlags, _window, _windowNumber, _context, _subtype, _data1, _data2];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
function _CPEventFirePeriodEvent()
|
||||
|
||||
@@ -190,7 +190,7 @@ var CPBindingOperationAnd = 0,
|
||||
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||
keyPath = [_info objectForKey:CPObservedKeyPathKey],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
newValue = [_source valueForKeyPath:aBinding];
|
||||
newValue = [self valueForBinding:aBinding];
|
||||
|
||||
newValue = [self reverseTransformValue:newValue withOptions:options];
|
||||
|
||||
@@ -199,6 +199,11 @@ var CPBindingOperationAnd = 0,
|
||||
[self unsuppressSpecificNotificationFromObject:destination keyPath:keyPath];
|
||||
}
|
||||
|
||||
- (id)valueForBinding:(CPString)aBinding
|
||||
{
|
||||
return [_source valueForKeyPath:aBinding];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
|
||||
{
|
||||
if (!changes)
|
||||
@@ -546,20 +551,35 @@ CPNotApplicableMarker = @"CPNotApplicableMarker";
|
||||
CPNullMarker = @"CPNullMarker";
|
||||
|
||||
// Binding name constants
|
||||
CPAlignmentBinding = @"alignment";
|
||||
CPEditableBinding = @"editable";
|
||||
CPEnabledBinding = @"enabled";
|
||||
CPFontBinding = @"font";
|
||||
CPHiddenBinding = @"hidden";
|
||||
CPSelectedIndexBinding = @"selectedIndex";
|
||||
CPTextColorBinding = @"textColor";
|
||||
CPToolTipBinding = @"toolTip";
|
||||
CPValueBinding = @"value";
|
||||
CPValueURLBinding = @"valueURL";
|
||||
CPValuePathBinding = @"valuePath";
|
||||
CPDataBinding = @"data";
|
||||
CPContentBinding = @"content";
|
||||
CPContentValuesBinding = @"contentValues";
|
||||
CPAlignmentBinding = @"alignment";
|
||||
CPContentArrayBinding = @"contentArray";
|
||||
CPContentBinding = @"content";
|
||||
CPContentObjectBinding = @"contentObject";
|
||||
CPContentObjectsBinding = @"contentObjects";
|
||||
CPContentValuesBinding = @"contentValues";
|
||||
CPEditableBinding = @"editable";
|
||||
CPEnabledBinding = @"enabled";
|
||||
CPFontBinding = @"font";
|
||||
CPFontNameBinding = @"fontName";
|
||||
CPFontBoldBinding = @"fontBold";
|
||||
CPHiddenBinding = @"hidden";
|
||||
CPFilterPredicateBinding = @"filterPredicate";
|
||||
CPPredicateBinding = @"predicate";
|
||||
CPSelectedIndexBinding = @"selectedIndex";
|
||||
CPSelectedLabelBinding = @"selectedLabel";
|
||||
CPSelectedObjectBinding = @"selectedObject";
|
||||
CPSelectedObjectsBinding = @"selectedObjects";
|
||||
CPSelectedTagBinding = @"selectedTag";
|
||||
CPSelectedValueBinding = @"selectedValue";
|
||||
CPSelectedValuesBinding = @"selectedValues";
|
||||
CPSelectionIndexesBinding = @"selectionIndexes";
|
||||
CPTextColorBinding = @"textColor";
|
||||
CPTitleBinding = @"title";
|
||||
CPToolTipBinding = @"toolTip";
|
||||
CPValueBinding = @"value";
|
||||
CPValueURLBinding = @"valueURL";
|
||||
CPValuePathBinding = @"valuePath";
|
||||
CPDataBinding = @"data";
|
||||
|
||||
//Binding options constants
|
||||
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelection";
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
@import <Foundation/CPGeometry.j>
|
||||
|
||||
@import "CPButton.j"
|
||||
@import "CPKeyValueBinding.j"
|
||||
@import "CPMenu.j"
|
||||
@import "CPMenuItem.j"
|
||||
|
||||
|
||||
var VISIBLE_MARGIN = 7.0;
|
||||
|
||||
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
@@ -247,22 +247,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
return _selectedIndex;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (int)_selectedTag
|
||||
{
|
||||
return [[self selectedItem] tag];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_setSelectedTag:(int)aTag
|
||||
{
|
||||
[self selectItemWithTag:aTag];
|
||||
}
|
||||
|
||||
// Setting the Current Selection
|
||||
/*!
|
||||
Selects the specified menu item.
|
||||
@@ -787,16 +771,286 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
- (void)_reverseSetBinding
|
||||
{
|
||||
var binderClass = [[self class] _binderClassForBinding:CPSelectedIndexBinding],
|
||||
theBinding = [binderClass getBinding:CPSelectedIndexBinding forObject:self];
|
||||
|
||||
[theBinding reverseSetValueFor:@"objectValue"];
|
||||
[_CPPopUpButtonSelectionBinder reverseSetValueForObject:self];
|
||||
|
||||
[super _reverseSetBinding];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPPopUpButton (BindingSupport)
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||
{
|
||||
if (aBinding == CPSelectedIndexBinding ||
|
||||
aBinding == CPSelectedObjectBinding ||
|
||||
aBinding == CPSelectedTagBinding ||
|
||||
aBinding == CPSelectedValueBinding ||
|
||||
aBinding == CPContentBinding ||
|
||||
aBinding == CPContentObjectsBinding ||
|
||||
aBinding == CPContentValuesBinding)
|
||||
{
|
||||
var capitalizedBinding = aBinding.charAt(0).toUpperCase() + aBinding.substr(1);
|
||||
|
||||
return [CPClassFromString(@"_CPPopUpButton" + capitalizedBinding + "Binder") class];
|
||||
}
|
||||
|
||||
return [super _binderClassForBinding:aBinding];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPPopUpButtonContentBinder : CPBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (CPInteger)_getInsertNullOffset
|
||||
{
|
||||
var options = [_info objectForKey:CPOptionsKey];
|
||||
|
||||
return [options objectForKey:CPInsertsNullPlaceholderBindingOption] ? 1 : 0;
|
||||
}
|
||||
|
||||
- (CPString)_getNullPlaceholder
|
||||
{
|
||||
var options = [_info objectForKey:CPOptionsKey],
|
||||
placeholder = [options objectForKey:CPNullPlaceholderBindingOption] || @"";
|
||||
|
||||
if (placeholder === [CPNull null])
|
||||
placeholder = @"";
|
||||
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
- (id)transformValue:(CPArray)contentArray withOptions:(CPDictionary)options
|
||||
{
|
||||
// Desactivate the full array transformation forced by super because we don't want this. We want individual transformations (see below).
|
||||
return contentArray;
|
||||
}
|
||||
|
||||
- (void)setValue:(CPArray)contentArray forBinding:(CPString)aBinding
|
||||
{
|
||||
[self _setContent:contentArray];
|
||||
[self _setContentValuesIfNeeded:contentArray];
|
||||
}
|
||||
|
||||
- (void)valueForBinding:(CPString)aBinding
|
||||
{
|
||||
return [self _content];
|
||||
}
|
||||
|
||||
- (void)_setContent:(CPArray)aValue
|
||||
{
|
||||
var count = [aValue count],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
offset = [self _getInsertNullOffset];
|
||||
|
||||
if (count + offset != [_source numberOfItems])
|
||||
{
|
||||
[_source removeAllItems];
|
||||
|
||||
if (offset)
|
||||
[_source addItemWithTitle:[self _getNullPlaceholder]];
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var item = [[CPMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:nil];
|
||||
[self _setValue:[aValue objectAtIndex:i] forItem:item withOptions:options];
|
||||
[_source addItem:item];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
[self _setValue:[aValue objectAtIndex:i] forItem:[_source itemAtIndex:i + offset] withOptions:options];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_setContentValuesIfNeeded:(CPArray)values
|
||||
{
|
||||
var offset = [self _getInsertNullOffset];
|
||||
|
||||
if (![_source infoForBinding:CPContentValuesBinding])
|
||||
{
|
||||
if (offset)
|
||||
[[_source itemAtIndex:0] setTitle:[self _getNullPlaceholder]];
|
||||
|
||||
var count = [values count];
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
[[_source itemAtIndex:i + offset] setTitle:[[values objectAtIndex:i] description]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_setValue:(id)aValue forItem:(CPMenuItem)aMenuItem withOptions:(CPDictionary)options
|
||||
{
|
||||
var value = [self _transformValue:aValue withOptions:options];
|
||||
[aMenuItem setRepresentedObject:value];
|
||||
}
|
||||
|
||||
- (id)_transformValue:(id)aValue withOptions:(CPDictionary)options
|
||||
{
|
||||
return [super transformValue:aValue withOptions:options];
|
||||
}
|
||||
|
||||
- (CPArray)_content
|
||||
{
|
||||
return [_source valueForKeyPath:@"itemArray.representedObject"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPPopUpButtonContentValuesBinder : _CPPopUpButtonContentBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
|
||||
{
|
||||
[super _setContent:aValue];
|
||||
}
|
||||
|
||||
- (void)_setValue:(id)aValue forItem:(CPMenuItem)aMenuItem withOptions:(CPDictionary)options
|
||||
{
|
||||
if (aValue === [CPNull null])
|
||||
aValue = nil;
|
||||
|
||||
var value = [self _transformValue:aValue withOptions:options];
|
||||
[aMenuItem setTitle:value];
|
||||
}
|
||||
|
||||
- (CPArray)_content
|
||||
{
|
||||
return [_source valueForKeyPath:@"itemArray.title"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var binderForObject = {};
|
||||
|
||||
@implementation _CPPopUpButtonSelectionBinder : CPBinder
|
||||
{
|
||||
CPString _selectionBinding @accessors;
|
||||
}
|
||||
|
||||
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
|
||||
{
|
||||
self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
|
||||
|
||||
if (self)
|
||||
{
|
||||
binderForObject[[aSource UID]] = self;
|
||||
_selectionBinding = aName;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (void)reverseSetValueForObject:(id)aSource
|
||||
{
|
||||
var binder = binderForObject[[aSource UID]];
|
||||
[binder reverseSetValueFor:[binder _selectionBinding]];
|
||||
}
|
||||
|
||||
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
|
||||
{
|
||||
[self setValue:aValue forBinding:aBinding];
|
||||
}
|
||||
|
||||
- (CPInteger)_getInsertNullOffset
|
||||
{
|
||||
var options = [[CPBinder infoForBinding:CPContentBinding forObject:_source] objectForKey:CPOptionsKey];
|
||||
|
||||
return [options objectForKey:CPInsertsNullPlaceholderBindingOption] ? 1 : 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPPopUpButtonSelectedIndexBinder : _CPPopUpButtonSelectionBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
|
||||
{
|
||||
[_source selectItemAtIndex:aValue + [self _getInsertNullOffset]];
|
||||
}
|
||||
|
||||
- (id)valueForBinding:(CPString)aBinding
|
||||
{
|
||||
return [_source indexOfSelectedItem] - [self _getInsertNullOffset];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPPopUpButtonSelectedObjectBinder : _CPPopUpButtonSelectionBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
|
||||
{
|
||||
var index = [_source indexOfItemWithRepresentedObject:aValue],
|
||||
offset = [self _getInsertNullOffset];
|
||||
|
||||
// If the content binding has the option CPNullPlaceholderBindingOption and the object to select is nil, select the first item (i.e., the placeholder).
|
||||
// Other cases to consider:
|
||||
// 1. no binding:
|
||||
// 1.1 there's no item with a represented object matching the object to select.
|
||||
// 1.2 the object to select is nil/CPNull
|
||||
// 2. there's a binding:
|
||||
// 2.1 there's a CPNullPlaceholderBindingOption:
|
||||
// 2.1.1 there's no item with a represented object matching the object to select?
|
||||
// 2.1.2 the object to select is nil/CPNull
|
||||
// 2.2 there's no CPNullPlaceholderBindingOption:
|
||||
// 2.2.1 there's no item with a represented object matching the object to select?
|
||||
// 2.2.2 the object to select is nil/CPNull
|
||||
// More cases? Behaviour that depends on array controller settings?
|
||||
|
||||
if (offset === 1 && index === CPNotFound)
|
||||
index = 0;
|
||||
|
||||
[_source selectItemAtIndex:index];
|
||||
}
|
||||
|
||||
- (id)valueForBinding:(CPString)aBinding
|
||||
{
|
||||
return [[_source selectedItem] representedObject];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPPopUpButtonSelectedTagBinder : _CPPopUpButtonSelectionBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
|
||||
{
|
||||
[_source selectItemWithTag:aValue];
|
||||
}
|
||||
|
||||
- (id)valueForBinding:(CPString)aBinding
|
||||
{
|
||||
return [[_source selectedItem] tag];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPPopUpButtonSelectedValueBinder : _CPPopUpButtonSelectionBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
|
||||
{
|
||||
[_source selectItemWithTitle:aValue];
|
||||
}
|
||||
|
||||
- (id)valueForBinding:(CPString)aBinding
|
||||
{
|
||||
return [_source titleOfSelectedItem];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var DEPRECATED_CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||
DEPRECATED_CPPopUpButtonSelectedIndexKey = @"CPPopUpButtonSelectedIndexKey";
|
||||
|
||||
|
||||
@@ -79,11 +79,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
{
|
||||
_selectedIndex = CPNotFound;
|
||||
|
||||
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
|
||||
_tabs = [[CPSegmentedControl alloc] initWithFrame:_CGRectMake(0, 0, 0, 0)];
|
||||
[_tabs setHitTests:NO];
|
||||
|
||||
var height = [_tabs valueForThemeAttribute:@"default-height"];
|
||||
[_tabs setFrameSize:CGSizeMake(0, height)];
|
||||
[_tabs setFrameSize:_CGSizeMake(0, height)];
|
||||
|
||||
_box = [[CPBox alloc] initWithFrame:[self bounds]];
|
||||
[self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]];
|
||||
@@ -350,11 +350,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
else
|
||||
{
|
||||
var aFrame = [self frame],
|
||||
segmentedHeight = CGRectGetHeight([_tabs frame]),
|
||||
segmentedHeight = _CGRectGetHeight([_tabs frame]),
|
||||
origin = _type === CPTopTabsBezelBorder ? segmentedHeight / 2 : 0;
|
||||
|
||||
[_box setFrame:CGRectMake(0, origin, CGRectGetWidth(aFrame),
|
||||
CGRectGetHeight(aFrame) - segmentedHeight / 2)];
|
||||
[_box setFrame:_CGRectMake(0, origin, _CGRectGetWidth(aFrame),
|
||||
_CGRectGetHeight(aFrame) - segmentedHeight / 2)];
|
||||
|
||||
[self addSubview:_tabs];
|
||||
}
|
||||
@@ -439,22 +439,22 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
|
||||
- (void)_repositionTabs
|
||||
{
|
||||
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
|
||||
verticalCenterOfTabs = CGRectGetHeight([_tabs bounds]) / 2;
|
||||
var horizontalCenterOfSelf = _CGRectGetWidth([self bounds]) / 2,
|
||||
verticalCenterOfTabs = _CGRectGetHeight([_tabs bounds]) / 2;
|
||||
|
||||
if (_type === CPBottomTabsBezelBorder)
|
||||
[_tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
|
||||
[_tabs setCenter:_CGPointMake(horizontalCenterOfSelf, _CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
|
||||
else
|
||||
[_tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
|
||||
[_tabs setCenter:_CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
|
||||
}
|
||||
|
||||
- (void)_setSelectedIndex:(CPNumber)index
|
||||
{
|
||||
_selectedIndex = index;
|
||||
[self _setContentViewForItem:[_items objectAtIndex:_selectedIndex]];
|
||||
[self _setContentViewFromItem:[_items objectAtIndex:_selectedIndex]];
|
||||
}
|
||||
|
||||
- (void)_setContentViewForItem:(CPTabViewItem)anItem
|
||||
- (void)_setContentViewFromItem:(CPTabViewItem)anItem
|
||||
{
|
||||
[_box setContentView:[anItem view]];
|
||||
}
|
||||
@@ -471,9 +471,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
}
|
||||
|
||||
if (_selectedIndex === CPNotFound)
|
||||
{
|
||||
[self selectFirstTabViewItem:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -4037,8 +4037,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
*/
|
||||
- (BOOL)startTrackingAt:(CGPoint)aPoint
|
||||
{
|
||||
if (![[self window] makeFirstResponder:self])
|
||||
return NO;
|
||||
// Try to become the first responder, but if we can't, that's okay.
|
||||
[[self window] makeFirstResponder:self];
|
||||
|
||||
var row = [self rowAtPoint:aPoint];
|
||||
|
||||
@@ -4189,9 +4189,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
*/
|
||||
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
|
||||
{
|
||||
if ([[self window] firstResponder] !== self)
|
||||
return;
|
||||
|
||||
_isSelectingSession = NO;
|
||||
|
||||
var CLICK_TIME_DELTA = 1000,
|
||||
|
||||
@@ -46,7 +46,8 @@ var CPTextFieldDOMInputElement = nil,
|
||||
CPTextFieldInputIsActive = NO,
|
||||
CPTextFieldCachedSelectStartFunction = nil,
|
||||
CPTextFieldCachedDragFunction = nil,
|
||||
CPTextFieldBlurFunction = nil;
|
||||
CPTextFieldBlurFunction = nil,
|
||||
CPTextFieldInputFunction = nil;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -211,6 +212,25 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
};
|
||||
|
||||
if (CPFeatureIsCompatible(CPInputOnInputEventFeature))
|
||||
{
|
||||
CPTextFieldInputFunction = function(anEvent)
|
||||
{
|
||||
if (!CPTextFieldInputOwner)
|
||||
return;
|
||||
|
||||
var cappEvent = [CPEvent keyEventWithType:CPKeyUp location:_CGPointMakeZero() modifierFlags:0
|
||||
timestamp:[CPEvent currentTimestamp] windowNumber:[[CPApp keyWindow] windowNumber] context:nil
|
||||
characters:nil charactersIgnoringModifiers:nil isARepeat:NO keyCode:nil];
|
||||
|
||||
[CPTextFieldInputOwner keyUp:cappEvent];
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
CPTextFieldDOMInputElement.oninput = CPTextFieldInputFunction;
|
||||
}
|
||||
|
||||
//FIXME make this not onblur
|
||||
CPTextFieldDOMInputElement.onblur = CPTextFieldBlurFunction;
|
||||
|
||||
@@ -474,13 +494,31 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[[CPTextFieldInputOwner window] makeFirstResponder:nil];
|
||||
#endif
|
||||
|
||||
// As long as we are the first responder we need to monitor the key status of our window.
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:) name:CPWindowDidResignKeyNotification object:[self window]];
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:) name:CPWindowDidBecomeKeyNotification object:[self window]];
|
||||
|
||||
_isEditing = NO;
|
||||
|
||||
if ([[self window] isKeyWindow])
|
||||
[self _becomeFirstKeyResponder];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
A text field can be the first responder without necessarily being the focus of keyboard input. For example, it might be the first responder of window A but window B is the main and key window. It's important we don't put a focused input field into a text field in a non key window, even if that field is the first responder, because the key window might also have a first responder text field which the user will expect to receive keyboard input.
|
||||
|
||||
Since a first responder but non-key window text field can't receive input it should not even look like an active text field (Cocoa has a "slightly active" text field look it uses when another window is the key window, but Cappuccino doesn't today.)
|
||||
*/
|
||||
- (void)_becomeFirstKeyResponder
|
||||
{
|
||||
[self setThemeState:CPThemeStateEditing];
|
||||
|
||||
[self _updatePlaceholderState];
|
||||
|
||||
[self setNeedsLayout];
|
||||
|
||||
_isEditing = NO;
|
||||
_stringValue = [self stringValue];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
@@ -491,7 +529,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
element.value = _stringValue;
|
||||
element.style.color = [[self currentValueForThemeAttribute:@"text-color"] cssString];
|
||||
element.style.font = [font cssString];
|
||||
if (CPFeatureIsCompatible(CPInputSetFontOutsideOfDOM))
|
||||
element.style.font = [font cssString];
|
||||
element.style.zIndex = 1000;
|
||||
|
||||
switch ([self alignment])
|
||||
@@ -526,12 +565,22 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
}
|
||||
|
||||
element.style.top = topPoint;
|
||||
element.style.left = (_CGRectGetMinX(contentRect) - 1) + "px"; // -1 because input element seems to have 1px left inset
|
||||
var left = _CGRectGetMinX(contentRect);
|
||||
// If the browser has a built in left padding, compensate for it. We need the input text to be exactly on top of the original text.
|
||||
if (CPFeatureIsCompatible(CPInput1PxLeftPadding))
|
||||
left -= 1;
|
||||
element.style.left = left + "px";
|
||||
element.style.width = _CGRectGetWidth(contentRect) + "px";
|
||||
element.style.height = lineHeight + "px";
|
||||
element.style.height = ROUND(lineHeight) + "px";
|
||||
element.style.lineHeight = ROUND(lineHeight) + "px";
|
||||
element.style.verticalAlign = @"top";
|
||||
|
||||
_DOMElement.appendChild(element);
|
||||
|
||||
// The font change above doesn't work for some browsers if the element isn't already .appendChild'ed.
|
||||
if (!CPFeatureIsCompatible(CPInputSetFontOutsideOfDOM))
|
||||
element.style.font = [font cssString];
|
||||
|
||||
window.setTimeout(function()
|
||||
{
|
||||
element.focus();
|
||||
@@ -559,14 +608,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
|
||||
}
|
||||
#endif
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateEditing];
|
||||
// When we are no longer the first responder we don't worry about the key status of our window anymore.
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidResignKeyNotification object:[self window]];
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidBecomeKeyNotification object:[self window]];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
@@ -583,13 +632,29 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
// even if the value has not changed.
|
||||
if ([self _valueIsValid:newValue] === NO)
|
||||
{
|
||||
[self setThemeState:CPThemeStateEditing];
|
||||
element.focus();
|
||||
return NO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
[self _resignFirstKeyResponder];
|
||||
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
|
||||
if ([self sendsActionOnEndEditing])
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
|
||||
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)_resignFirstKeyResponder
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateEditing];
|
||||
|
||||
// Cache the formatted string
|
||||
_stringValue = [self stringValue];
|
||||
|
||||
@@ -601,6 +666,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var element = [self _inputElement];
|
||||
|
||||
CPTextFieldInputResigning = YES;
|
||||
|
||||
if (CPTextFieldInputIsActive)
|
||||
@@ -627,16 +694,18 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
- (void)_windowDidResignKey:(CPNotification)aNotification
|
||||
{
|
||||
if (![[self window] isKeyWindow])
|
||||
[self _resignFirstKeyResponder];
|
||||
}
|
||||
|
||||
if ([self sendsActionOnEndEditing])
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
|
||||
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
|
||||
|
||||
return YES;
|
||||
- (void)_windowDidBecomeKey:(CPNotification)aNotification
|
||||
{
|
||||
if ([[self window] isKeyWindow] && [[self window] firstResponder] === self)
|
||||
[self _becomeFirstKeyResponder];
|
||||
}
|
||||
|
||||
- (BOOL)_valueIsValid:(CPString)aValue
|
||||
@@ -1133,7 +1202,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[self copy:sender];
|
||||
[self deleteBackward:sender];
|
||||
}
|
||||
else
|
||||
// If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
|
||||
else if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(keyUp:) userInfo:nil repeats:NO];
|
||||
}
|
||||
|
||||
@@ -1155,7 +1225,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[self setStringValue:newValue];
|
||||
[self setSelectedRange:CPMakeRange(selectedRange.location + pasteString.length, 0)];
|
||||
}
|
||||
else
|
||||
// If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
|
||||
else if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(keyUp:) userInfo:nil repeats:NO];
|
||||
}
|
||||
|
||||
|
||||
@@ -419,7 +419,8 @@ CPThemeStateVertical = CPThemeState("vertical");
|
||||
CPThemeStateDefault = CPThemeState("default");
|
||||
CPThemeStateCircular = CPThemeState("circular");
|
||||
CPThemeStateAutocompleting = CPThemeState("autocompleting");
|
||||
|
||||
CPThemeStateMainWindow = CPThemeState("mainWindow");
|
||||
CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
|
||||
@implementation _CPThemeAttribute : CPObject
|
||||
{
|
||||
|
||||
@@ -1008,8 +1008,9 @@ var CPScrollDestinationNone = 0,
|
||||
r.origin.y = offset.y;
|
||||
|
||||
// Make sure the frame fits.
|
||||
if (_CGRectGetHeight([contentView bounds]) < offset.y + height)
|
||||
[contentView setFrame:_CGRectMake(0, 0, _CGRectGetWidth([_tokenScrollView bounds]), offset.y + height)];
|
||||
var scrollHeight = offset.y + tokenHeight + CEIL(spaceBetweenTokens.height / 2.0);
|
||||
if (_CGRectGetHeight([contentView bounds]) < scrollHeight)
|
||||
[contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
|
||||
|
||||
offset.x += width + spaceBetweenTokens.width;
|
||||
|
||||
@@ -1033,6 +1034,7 @@ var CPScrollDestinationNone = 0,
|
||||
}
|
||||
|
||||
_inputFrame = fitAndFrame(textWidth, tokenHeight);
|
||||
|
||||
_inputFrame.size.height = lineHeight;
|
||||
|
||||
element.style.left = (_inputFrame.origin.x + editorInset.left) + "px";
|
||||
@@ -1042,7 +1044,7 @@ var CPScrollDestinationNone = 0,
|
||||
|
||||
// When editing, always scroll to the cursor.
|
||||
if (_selectedRange.length == 0)
|
||||
[[_tokenScrollView documentView] scrollRectToVisible:_inputFrame];
|
||||
[[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, _inputFrame.origin.y)];
|
||||
};
|
||||
|
||||
for (var i = 0, count = [tokens count]; i < count; i++)
|
||||
@@ -1074,13 +1076,21 @@ var CPScrollDestinationNone = 0,
|
||||
if (isEditing && _selectedRange.length)
|
||||
{
|
||||
_inputFrame = nil;
|
||||
[self _inputElement].style.left = "-10000px";
|
||||
[self _inputElement].focus();
|
||||
var inputElement = [self _inputElement];
|
||||
inputElement.style.display = "none";
|
||||
}
|
||||
else if (isEditing)
|
||||
{
|
||||
var inputElement = [self _inputElement];
|
||||
inputElement.style.display = "block";
|
||||
if (document.activeElement !== inputElement)
|
||||
inputElement.focus();
|
||||
}
|
||||
|
||||
// Trim off any excess height downwards.
|
||||
if (_CGRectGetHeight([contentView bounds]) > offset.y + tokenHeight)
|
||||
[contentView setFrame:_CGRectMake(0, 0, _CGRectGetWidth([_tokenScrollView bounds]), offset.y + tokenHeight)];
|
||||
// Trim off any excess height downwards (in case we shrank).
|
||||
var scrollHeight = offset.y + tokenHeight + CEIL(spaceBetweenTokens.height / 2.0);
|
||||
if (_CGRectGetHeight([contentView bounds]) > scrollHeight)
|
||||
[contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
|
||||
|
||||
if (_shouldScrollTo !== CPScrollDestinationNone)
|
||||
{
|
||||
@@ -1105,7 +1115,7 @@ var CPScrollDestinationNone = 0,
|
||||
if (!aToken)
|
||||
return;
|
||||
|
||||
return [[_tokenScrollView documentView] scrollRectToVisible:[aToken frame]];
|
||||
return [[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, [aToken frameOrigin].y)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -614,7 +614,7 @@ var CPCurrentToolTip,
|
||||
*/
|
||||
- (void)replaceSubview:(CPView)aSubview with:(CPView)aView
|
||||
{
|
||||
if (aSubview._superview != self)
|
||||
if (aSubview._superview !== self)
|
||||
return;
|
||||
|
||||
var index = [_subviews indexOfObjectIdenticalTo:aSubview];
|
||||
@@ -2092,6 +2092,11 @@ setBoundsOrigin:
|
||||
_DOMContentsElement.style.height = ROUND(_CGRectGetHeight(_frame)) + "px";
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
// The performance implications of this aren't clear, but without this subviews might not be redrawn when this
|
||||
// view moves.
|
||||
if (CPPlatformHasBug(CPCanvasParentDrawErrorsOnMovementBug))
|
||||
_DOMElement.style.webkitTransform = 'translateX(0)';
|
||||
|
||||
CPDOMDisplayServerAppendChild(_DOMElement, _DOMContentsElement);
|
||||
#endif
|
||||
_graphicsContext = [CPGraphicsContext graphicsContextWithGraphicsPort:graphicsPort flipped:YES];
|
||||
|
||||
@@ -67,6 +67,7 @@ var CPViewControllerCachedCibs;
|
||||
CPView _view @accessors(property=view);
|
||||
BOOL _isLoading;
|
||||
BOOL _isLazy;
|
||||
BOOL _isViewLoaded @accessors(getter=isViewLoaded);
|
||||
|
||||
id _representedObject @accessors(property=representedObject);
|
||||
CPString _title @accessors(property=title);
|
||||
@@ -206,17 +207,24 @@ var CPViewControllerCachedCibs;
|
||||
[cibOwner viewControllerDidLoadCib:self];
|
||||
|
||||
_isLoading = NO;
|
||||
[self viewDidLoad];
|
||||
[self _viewDidLoad];
|
||||
}
|
||||
else if (_isLazy)
|
||||
{
|
||||
_isLazy = NO;
|
||||
[self viewDidLoad];
|
||||
[self _viewDidLoad];
|
||||
}
|
||||
|
||||
return _view;
|
||||
}
|
||||
|
||||
- (void)_viewDidLoad
|
||||
{
|
||||
[self willChangeValueForKey:"isViewLoaded"];
|
||||
[self viewDidLoad];
|
||||
isViewLoaded = YES;
|
||||
[self didChangeValueForKey:"isViewLoaded"];
|
||||
}
|
||||
|
||||
/*!
|
||||
This method is called after the view controller has loaded its associated views into memory.
|
||||
@@ -242,7 +250,21 @@ var CPViewControllerCachedCibs;
|
||||
*/
|
||||
- (void)setView:(CPView)aView
|
||||
{
|
||||
var willChangeIsViewLoaded = (_isViewLoaded == NO && aView != nil) || (_isViewLoaded == YES && aView == nil);
|
||||
|
||||
if (willChangeIsViewLoaded)
|
||||
[self willChangeValueForKey:"isViewLoaded"];
|
||||
|
||||
_view = aView;
|
||||
_isViewLoaded = aView !== nil;
|
||||
|
||||
if (willChangeIsViewLoaded)
|
||||
[self didChangeValueForKey:"isViewLoaded"];
|
||||
}
|
||||
|
||||
- (BOOL)automaticallyNotifiesObserversOfIsViewLoaded
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -259,6 +259,16 @@ var CPWindowActionMessageKeys = [
|
||||
@param window the window to close
|
||||
@return \c YES allows the window to close. \c NO
|
||||
vetoes the close operation and leaves the window open.
|
||||
|
||||
@delegate -(BOOL)windowWillBeginSheet:(CPNotification)notification;
|
||||
Sent from the notification center before sheet is visible on
|
||||
the delegate's window.
|
||||
@param notification contains information about the event
|
||||
|
||||
@delegate -(BOOL)windowDidEndSheet:(CPNotification)notification;
|
||||
Sent from the notification center when an attached sheet on the
|
||||
delegate's window has been animated out and is no longer visible.
|
||||
@param notification contains information about the event
|
||||
*/
|
||||
@implementation CPWindow : CPResponder
|
||||
{
|
||||
@@ -335,7 +345,6 @@ var CPWindowActionMessageKeys = [
|
||||
CPDictionary _sheetContext;
|
||||
CPWindow _parentView;
|
||||
BOOL _isSheet;
|
||||
|
||||
_CPWindowFrameAnimation _frameAnimation;
|
||||
}
|
||||
|
||||
@@ -405,10 +414,13 @@ CPTexturedBackgroundWindowMask
|
||||
_isFullPlatformWindow = NO;
|
||||
_registeredDraggedTypes = [CPSet set];
|
||||
_registeredDraggedTypesArray = [];
|
||||
_isSheet = NO;
|
||||
_acceptsMouseMovedEvents = YES;
|
||||
_isMovable = YES;
|
||||
|
||||
_isSheet = NO;
|
||||
_sheetContext = nil;
|
||||
_parentView = nil;
|
||||
|
||||
// Set up our window number.
|
||||
_windowNumber = [CPApp._windows count];
|
||||
CPApp._windows[_windowNumber] = self;
|
||||
@@ -764,7 +776,21 @@ CPTexturedBackgroundWindowMask
|
||||
[_windowView setFrameSize:size];
|
||||
|
||||
if (_hasShadow)
|
||||
[_shadowView setFrameSize:_CGSizeMake(SHADOW_MARGIN_LEFT + size.width + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_BOTTOM + size.height + SHADOW_MARGIN_TOP + SHADOW_DISTANCE)];
|
||||
{
|
||||
// if the shadow would be taller/wider than the window height,
|
||||
// make it the same as the window height. this allows views to
|
||||
// become 0, 0 with no shadow on them and makes the sheet
|
||||
// animation look nicer
|
||||
var shadowSize = _CGSizeMake(size.width, size.height);
|
||||
|
||||
if (size.width >= (SHADOW_MARGIN_LEFT + SHADOW_MARGIN_RIGHT))
|
||||
shadowSize.width += SHADOW_MARGIN_LEFT + SHADOW_MARGIN_RIGHT;
|
||||
|
||||
if (size.height >= (SHADOW_MARGIN_BOTTOM + SHADOW_MARGIN_TOP + SHADOW_DISTANCE))
|
||||
shadowSize.height += SHADOW_MARGIN_BOTTOM + SHADOW_MARGIN_TOP + SHADOW_DISTANCE;
|
||||
|
||||
[_shadowView setFrameSize:shadowSize];
|
||||
}
|
||||
|
||||
if (!_isAnimating)
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidResizeNotification object:self];
|
||||
@@ -801,6 +827,10 @@ CPTexturedBackgroundWindowMask
|
||||
- (void)setFrameOrigin:(CGPoint)anOrigin
|
||||
{
|
||||
[self _setClippedFrame:_CGRectMake(anOrigin.x, anOrigin.y, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)) display:YES animate:NO];
|
||||
|
||||
// reposition sheet
|
||||
if ([self attachedSheet])
|
||||
[self _setAttachedSheetFrameOrigin];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -819,16 +849,20 @@ CPTexturedBackgroundWindowMask
|
||||
- (void)orderFront:(id)aSender
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
// -dw- if a sheet is clicked, the parent window should come up too
|
||||
if ([self isSheet])
|
||||
[_parentView orderFront:self];
|
||||
|
||||
[_platformWindow orderFront:self];
|
||||
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
|
||||
#endif
|
||||
|
||||
if (_firstResponder === self || !_firstResponder)
|
||||
[self makeFirstResponder:_initialFirstResponder];
|
||||
|
||||
if (!CPApp._keyWindow)
|
||||
[self makeKeyWindow];
|
||||
|
||||
if ([self isKeyWindow] && (_firstResponder === self || !_firstResponder))
|
||||
[self makeFirstResponder:_initialFirstResponder];
|
||||
|
||||
if (!CPApp._mainWindow)
|
||||
[self makeMainWindow];
|
||||
}
|
||||
@@ -849,6 +883,13 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)orderOut:(id)aSender
|
||||
{
|
||||
if ([self isSheet])
|
||||
{
|
||||
// -dw- as in Cocoa, orderOut: detaches the sheet and animates out
|
||||
[self._parentView _detachSheetWindow];
|
||||
return;
|
||||
}
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if ([self _sharesChromeWithPlatformWindow])
|
||||
[_platformWindow orderOut:self];
|
||||
@@ -1209,6 +1250,8 @@ CPTexturedBackgroundWindowMask
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidResignMainNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidMoveNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidResizeNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowWillBeginSheetNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidEndSheetNotification object:self];
|
||||
|
||||
_delegate = aDelegate;
|
||||
_delegateRespondsToWindowWillReturnUndoManagerSelector = [_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)];
|
||||
@@ -1254,6 +1297,20 @@ CPTexturedBackgroundWindowMask
|
||||
selector:@selector(windowDidResize:)
|
||||
name:CPWindowDidResizeNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowWillBeginSheet:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(windowWillBeginSheet:)
|
||||
name:CPWindowWillBeginSheetNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowDidEndSheet:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(windowDidEndSheet:)
|
||||
name:CPWindowDidEndSheetNotification
|
||||
object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1534,6 +1591,30 @@ CPTexturedBackgroundWindowMask
|
||||
var type = [anEvent type],
|
||||
point = [anEvent locationInWindow];
|
||||
|
||||
// If a sheet is attached events get filtered here.
|
||||
// It is not clear what events should be passed to the view, perhaps all?
|
||||
// CPLeftMouseDown is needed for window moving and resizing to work.
|
||||
// CPMouseMoved is needed for rollover effects on title bar buttons.
|
||||
var sheet = [self attachedSheet];
|
||||
if (sheet)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CPLeftMouseDown:
|
||||
[_windowView mouseDown:anEvent];
|
||||
|
||||
// -dw- if the window is clicked, the sheet should come to front, and become key,
|
||||
// and the window should be immediately behind
|
||||
[sheet makeKeyAndOrderFront:self];
|
||||
break;
|
||||
case CPMouseMoved:
|
||||
[_windowView mouseMoved:anEvent];
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CPFlagsChanged: return [[self firstResponder] flagsChanged:anEvent];
|
||||
@@ -1698,6 +1779,8 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[self _setupFirstResponder:nil];
|
||||
|
||||
[_windowView noteKeyWindowStateChanged];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPWindowDidBecomeKeyNotification
|
||||
object:self];
|
||||
@@ -1755,6 +1838,8 @@ CPTexturedBackgroundWindowMask
|
||||
if (CPApp._keyWindow === self)
|
||||
CPApp._keyWindow = nil;
|
||||
|
||||
[_windowView noteKeyWindowStateChanged];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPWindowDidResignKeyNotification
|
||||
object:self];
|
||||
@@ -2100,6 +2185,8 @@ CPTexturedBackgroundWindowMask
|
||||
[self _synchronizeMenuBarTitleWithWindowTitle];
|
||||
[self _synchronizeSaveMenuWithDocumentSaving];
|
||||
|
||||
[_windowView noteMainWindowStateChanged];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPWindowDidBecomeMainNotification
|
||||
object:self];
|
||||
@@ -2116,6 +2203,8 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
if (CPApp._mainWindow === self)
|
||||
CPApp._mainWindow = nil;
|
||||
|
||||
[_windowView noteMainWindowStateChanged];
|
||||
}
|
||||
|
||||
- (void)_updateMainAndKeyWindows
|
||||
@@ -2284,62 +2373,124 @@ CPTexturedBackgroundWindowMask
|
||||
[attachedSheet setFrame:sheetFrame display:YES animate:NO];
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
|
||||
/* @ignore
|
||||
Starting point for sheet session, called from CPApplication beginSheet:
|
||||
*/
|
||||
- (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate
|
||||
didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
|
||||
{
|
||||
if (_sheetContext)
|
||||
{
|
||||
[CPException raise:CPInternalInconsistencyException
|
||||
reason:@"The target window of beginSheet: already has a sheet, did you forget orderOut: ?"];
|
||||
return;
|
||||
}
|
||||
|
||||
var sheetFrame = [aSheet frame];
|
||||
|
||||
_sheetContext = {"sheet":aSheet, "modalDelegate":aModalDelegate, "endSelector":aDidEndSelector, "contextInfo":aContextInfo, "frame":CGRectMakeCopy(sheetFrame), "returnCode":-1, "opened": NO};
|
||||
_sheetContext = {"sheet": aSheet, "modalDelegate": aModalDelegate, "endSelector": aDidEndSelector,
|
||||
"contextInfo": aContextInfo, "frame": _CGRectMakeCopy(sheetFrame), "returnCode": -1,
|
||||
"opened": NO};
|
||||
|
||||
[self _attachSheetWindow:aSheet];
|
||||
[self _attachSheetWindow];
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (void)_attachSheetWindow:(CPWindow)aSheet
|
||||
/* @ignore
|
||||
Called to animate the sheet in. The timer seems to solve a bug where sheets would
|
||||
be partially animated under certain conditions.
|
||||
*/
|
||||
- (void)_attachSheetWindow
|
||||
{
|
||||
var sheetFrame = [aSheet frame],
|
||||
frame = [self frame],
|
||||
sheetContent = [aSheet contentView];
|
||||
_sheetContext["isAttached"] = YES;
|
||||
|
||||
[self _setUpMasksForView:sheetContent];
|
||||
|
||||
aSheet._isSheet = YES;
|
||||
aSheet._parentView = self;
|
||||
|
||||
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
|
||||
originy = frame.origin.y + [[self contentView] frame].origin.y,
|
||||
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
|
||||
endFrame = CGRectMake(originx, originy, sheetFrame.size.width, sheetFrame.size.height);
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
|
||||
[CPApp runModalForWindow:aSheet];
|
||||
|
||||
[aSheet orderFront:self];
|
||||
[aSheet setFrame:startFrame display:YES animate:NO];
|
||||
_sheetContext["opened"] = YES;
|
||||
|
||||
[aSheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut];
|
||||
|
||||
// Should run the main loop here until _isAnimating = FALSE
|
||||
[aSheet becomeKeyWindow];
|
||||
// it would be ideal to block here and spin an event loop, until attach is complete
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.0
|
||||
target:self
|
||||
selector:@selector(_sheetShouldAnimateIn:)
|
||||
userInfo:nil
|
||||
repeats:NO];
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
/* @ignore
|
||||
Called to end the sheet. Note that orderOut: is needed to animate the sheet out, as in Cocoa.
|
||||
The sheet isn't completely gone until _cleanupSheetWindow gets called.
|
||||
*/
|
||||
- (void)_endSheet
|
||||
{
|
||||
var delegate = _sheetContext["modalDelegate"],
|
||||
endSelector = _sheetContext["endSelector"];
|
||||
|
||||
// If the sheet has been ordered out, defer didEndSelector until after sheet animates out.
|
||||
// This must be done since we cannot block and wait for the animation to complete.
|
||||
if (delegate && endSelector)
|
||||
{
|
||||
if (_sheetContext["isAttached"])
|
||||
objj_msgSend(delegate, endSelector, _sheetContext["sheet"], _sheetContext["returnCode"],
|
||||
_sheetContext["contextInfo"]);
|
||||
else
|
||||
_sheetContext["deferDidEndSelector"] = YES;
|
||||
}
|
||||
}
|
||||
|
||||
/* @ignore
|
||||
Called to animate the sheet out. If called while animating in, schedules an animate
|
||||
out at completion
|
||||
*/
|
||||
- (void)_detachSheetWindow
|
||||
{
|
||||
var sheet = [self attachedSheet],
|
||||
startFrame = [sheet frame],
|
||||
endFrame = CGRectMakeCopy(startFrame);
|
||||
_sheetContext["isAttached"] = NO;
|
||||
|
||||
endFrame.size.height = 0;
|
||||
// it would be ideal to block here and spin the event loop, until attach is complete
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.0
|
||||
target:self
|
||||
selector:@selector(_sheetShouldAnimateOut:)
|
||||
userInfo:nil
|
||||
repeats:NO];
|
||||
}
|
||||
|
||||
_sheetContext["frame"] = startFrame;
|
||||
/* @ignore
|
||||
Called to cleanup sheet, when we are definitely done with it
|
||||
*/
|
||||
- (void)_cleanupSheetWindow
|
||||
{
|
||||
var sheet = _sheetContext["sheet"],
|
||||
lastFrame = _sheetContext["frame"],
|
||||
deferDidEnd = _sheetContext["deferDidEndSelector"];
|
||||
|
||||
var sheetContent = [sheet contentView];
|
||||
[self _setUpMasksForView:sheetContent];
|
||||
[sheet setFrame:lastFrame];
|
||||
[self _restoreMasksForView:[sheet contentView]];
|
||||
|
||||
_sheetContext["opened"] = NO;
|
||||
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn];
|
||||
// if the parent window is modal, the sheet started its own modal session
|
||||
if (sheet._isModal)
|
||||
[CPApp stopModal];
|
||||
|
||||
// restore the state of window before it was sheetified
|
||||
[sheet._windowView _enableSheet:NO];
|
||||
|
||||
// close it
|
||||
sheet._isSheet = NO;
|
||||
[sheet orderOut:self];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
|
||||
|
||||
if (deferDidEnd)
|
||||
{
|
||||
var delegate = _sheetContext["modalDelegate"],
|
||||
selector = _sheetContext["endSelector"],
|
||||
returnCode = _sheetContext["returnCode"],
|
||||
contextInfo = _sheetContext["contextInfo"];
|
||||
|
||||
// context must be destroyed, since didEnd might want to attach another sheet
|
||||
_sheetContext = nil;
|
||||
sheet._parentView = nil;
|
||||
|
||||
objj_msgSend(delegate, selector, sheet, returnCode, contextInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sheetContext = nil;
|
||||
sheet._parentView = nil;
|
||||
}
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
@@ -2349,34 +2500,117 @@ CPTexturedBackgroundWindowMask
|
||||
if (anim._window != sheet)
|
||||
return;
|
||||
|
||||
var sheetContent = [sheet contentView];
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.0
|
||||
target:self
|
||||
selector:@selector(_sheetAnimationDidEnd:)
|
||||
userInfo:nil
|
||||
repeats:NO];
|
||||
}
|
||||
|
||||
if (_sheetContext["opened"] === YES)
|
||||
/* @ignore */
|
||||
- (void)_sheetShouldAnimateIn:(CPTimer)timer
|
||||
{
|
||||
// can't open sheet while opening or closing animation is going on
|
||||
if (_sheetContext["isOpening"] ||
|
||||
_sheetContext["isClosing"])
|
||||
return;
|
||||
|
||||
var sheet = _sheetContext["sheet"],
|
||||
sheetFrame = [sheet frame],
|
||||
frame = [self frame];
|
||||
|
||||
[self _setUpMasksForView:[sheet contentView]];
|
||||
|
||||
sheet._isSheet = YES;
|
||||
sheet._parentView = self;
|
||||
|
||||
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
|
||||
originy = frame.origin.y + [[self contentView] frame].origin.y,
|
||||
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
|
||||
endFrame = CGRectMake(originx, originy, sheetFrame.size.width, sheetFrame.size.height);
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
|
||||
|
||||
// if sheet is attached to a modal window, the sheet runs
|
||||
// as if itself and the parent window are modal
|
||||
sheet._isModal = NO;
|
||||
if ([CPApp modalWindow] === self)
|
||||
{
|
||||
[self _restoreMasksForView:sheetContent];
|
||||
[CPApp runModalForWindow:sheet];
|
||||
sheet._isModal = YES;
|
||||
}
|
||||
|
||||
[sheet orderFront:self];
|
||||
[sheet setFrame:startFrame display:YES animate:NO];
|
||||
|
||||
_sheetContext["opened"] = YES;
|
||||
_sheetContext["shouldClose"] = NO;
|
||||
_sheetContext["isOpening"] = YES;
|
||||
|
||||
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut];
|
||||
|
||||
// NOTE: cocoa doesn't make window key until animation is done, but a
|
||||
// keypress while animating eventually gets to the window. Therefore,
|
||||
// there must be a runloop specifically designed for sheets?
|
||||
[sheet makeKeyWindow];
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (void)_sheetShouldAnimateOut:(CPTimer)timer
|
||||
{
|
||||
var sheet = _sheetContext["sheet"],
|
||||
startFrame = [sheet frame],
|
||||
endFrame = CGRectMakeCopy(startFrame);
|
||||
|
||||
if (_sheetContext["isOpening"])
|
||||
{
|
||||
// allow sheet to be closed while opening, it will close when animate in completes
|
||||
_sheetContext["shouldClose"] = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
[CPApp stopModal];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
|
||||
if (_sheetContext["isClosing"])
|
||||
return;
|
||||
|
||||
[sheet orderOut:self];
|
||||
_sheetContext["opened"] = NO;
|
||||
_sheetContext["frame"] = startFrame;
|
||||
_sheetContext["isClosing"] = YES;
|
||||
|
||||
var lastFrame = _sheetContext["frame"];
|
||||
[sheet setFrame:lastFrame];
|
||||
// the parent window can be orderedOut to disable the sheet animate out, as in Cocoa
|
||||
if ([self isVisible])
|
||||
{
|
||||
endFrame.size.height = 0;
|
||||
[self _setUpMasksForView:[sheet contentView]];
|
||||
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self _sheetAnimationDidEnd:nil];
|
||||
}
|
||||
}
|
||||
|
||||
[self _restoreMasksForView:sheetContent];
|
||||
/* @ignore */
|
||||
- (void)_sheetAnimationDidEnd:(CPTimer)timer
|
||||
{
|
||||
var sheet = _sheetContext["sheet"];
|
||||
|
||||
var delegate = _sheetContext["modalDelegate"],
|
||||
endSelector = _sheetContext["endSelector"],
|
||||
returnCode = _sheetContext["returnCode"],
|
||||
contextInfo = _sheetContext["contextInfo"];
|
||||
_sheetContext["isOpening"] = NO;
|
||||
_sheetContext["isClosing"] = NO;
|
||||
|
||||
_sheetContext = nil;
|
||||
sheet._parentView = nil;
|
||||
if (_sheetContext["opened"] === YES)
|
||||
{
|
||||
// sheet is open and completely visible
|
||||
[self _restoreMasksForView:[sheet contentView]];
|
||||
|
||||
if (delegate != nil && endSelector != nil)
|
||||
objj_msgSend(delegate, endSelector, sheet, returnCode, contextInfo);
|
||||
// we wanted to close the sheet while it animated in, do that now
|
||||
if (_sheetContext["shouldClose"] === YES)
|
||||
[self _detachSheetWindow];
|
||||
}
|
||||
else
|
||||
{
|
||||
// sheet is closed and not visible
|
||||
[self _cleanupSheetWindow];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_setUpMasksForView:(CPView)aView
|
||||
|
||||
@@ -54,4 +54,10 @@ var _CPStandardWindowViewBodyBackgroundColor = nil;
|
||||
return aContentRect;
|
||||
}
|
||||
|
||||
- (void)_enableSheet:(BOOL)enable
|
||||
{
|
||||
// do nothing, already a sheet
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -21,18 +21,18 @@
|
||||
*/
|
||||
|
||||
@import "CPTextField.j"
|
||||
@import "_CPTitleableWindowView.j"
|
||||
|
||||
var _CPHUDWindowViewBackgroundColor = nil,
|
||||
_CPHUDWindowViewThemeValues = nil,
|
||||
|
||||
CPHUDCloseButtonImage = nil;
|
||||
|
||||
var HUD_TITLEBAR_HEIGHT = 26.0;
|
||||
|
||||
@implementation _CPHUDWindowView : _CPWindowView
|
||||
@implementation _CPHUDWindowView : _CPTitleableWindowView
|
||||
{
|
||||
CPView _toolbarView;
|
||||
|
||||
CPTextField _titleField;
|
||||
CPButton _closeButton;
|
||||
}
|
||||
|
||||
@@ -60,28 +60,23 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
|
||||
|
||||
_CPHUDWindowViewCloseImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowClose.png"] size:CPSizeMake(18.0, 18.0)];
|
||||
_CPHUDWindowViewCloseActiveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCloseActive.png"] size:CPSizeMake(18.0, 18.0)];
|
||||
|
||||
_CPHUDWindowViewThemeValues = [
|
||||
[@"title-font", [CPFont systemFontOfSize:[CPFont systemFontSize] - 1]],
|
||||
[@"title-text-color", [CPColor colorWithWhite:255.0 / 255.0 alpha:0.75]],
|
||||
[@"title-text-color", [CPColor colorWithWhite:255.0 / 255.0 alpha:1], CPThemeStateKeyWindow],
|
||||
[@"title-text-shadow-color", [CPColor blackColor]],
|
||||
[@"title-text-shadow-offset", CGSizeMake(0.0, 1.0)],
|
||||
[@"title-alignment", CPCenterTextAlignment],
|
||||
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
|
||||
[@"title-line-break-mode", CPLineBreakByTruncatingTail],
|
||||
[@"title-vertical-alignment", CPCenterVerticalTextAlignment]
|
||||
];
|
||||
}
|
||||
|
||||
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||
+ (int)titleBarHeight
|
||||
{
|
||||
var contentRect = CGRectMakeCopy(aFrameRect),
|
||||
titleBarHeight = HUD_TITLEBAR_HEIGHT;
|
||||
|
||||
contentRect.origin.y += titleBarHeight;
|
||||
contentRect.size.height -= titleBarHeight;
|
||||
|
||||
return contentRect;
|
||||
}
|
||||
|
||||
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
|
||||
{
|
||||
var frameRect = CGRectMakeCopy(aContentRect),
|
||||
titleBarHeight = HUD_TITLEBAR_HEIGHT;
|
||||
|
||||
frameRect.origin.y -= titleBarHeight;
|
||||
frameRect.size.height += titleBarHeight;
|
||||
|
||||
return frameRect;
|
||||
return HUD_TITLEBAR_HEIGHT;
|
||||
}
|
||||
|
||||
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||
@@ -120,37 +115,18 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
|
||||
|
||||
if (self)
|
||||
{
|
||||
// Until windows become properly themable, just set these values here in the subclass.
|
||||
[self registerThemeValues:_CPHUDWindowViewThemeValues];
|
||||
|
||||
var bounds = [self bounds];
|
||||
|
||||
[self setBackgroundColor:_CPHUDWindowViewBackgroundColor];
|
||||
|
||||
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[_titleField setHitTests:NO];
|
||||
[_titleField setFont:[CPFont systemFontOfSize:[CPFont systemFontSize] - 1]];
|
||||
[_titleField setTextColor:[CPColor whiteColor]];
|
||||
[_titleField setTextShadowColor:[CPColor blackColor]];
|
||||
[_titleField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
|
||||
[_titleField setAutoresizingMask:CPViewWidthSizable];
|
||||
|
||||
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
|
||||
[_titleField setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
[_titleField setAlignment:CPCenterTextAlignment];
|
||||
|
||||
[_titleField setStringValue:@"Untitled"];
|
||||
[_titleField sizeToFit];
|
||||
[_titleField setAutoresizingMask:CPViewWidthSizable];
|
||||
[_titleField setStringValue:@""];
|
||||
|
||||
[_titleField setFrame:CGRectMake(20.0, 3.0, CGRectGetWidth([self bounds]) - 40.0, CGRectGetHeight([_titleField frame]))];
|
||||
|
||||
[self addSubview:_titleField];
|
||||
|
||||
if (_styleMask & CPClosableWindowMask)
|
||||
{
|
||||
var closeSize = [_CPHUDWindowViewCloseImage size];
|
||||
|
||||
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 5.0, closeSize.width, closeSize.height)];
|
||||
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 4.0, closeSize.width, closeSize.height)];
|
||||
|
||||
[_closeButton setBordered:NO];
|
||||
|
||||
@@ -161,6 +137,8 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
|
||||
}
|
||||
|
||||
[self setResizeIndicatorOffset:CGSizeMake(5.0, 5.0)];
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -172,11 +150,6 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
|
||||
[_closeButton setAction:@selector(performClose:)];
|
||||
}
|
||||
|
||||
- (void)setTitle:(CPString)aTitle
|
||||
{
|
||||
[_titleField setStringValue:aTitle];
|
||||
}
|
||||
|
||||
- (_CPToolbarView)toolbarView
|
||||
{
|
||||
return _toolbarView;
|
||||
@@ -194,7 +167,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
|
||||
|
||||
- (CGSize)toolbarOffset
|
||||
{
|
||||
return CGSizeMake(0.0, HUD_TITLEBAR_HEIGHT);
|
||||
return _CGSizeMake(0.0, [[self class] titleBarHeight]);
|
||||
}
|
||||
|
||||
- (void)tile
|
||||
@@ -203,14 +176,43 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
|
||||
|
||||
var theWindow = [self window],
|
||||
bounds = [self bounds],
|
||||
width = CGRectGetWidth(bounds);
|
||||
width = _CGRectGetWidth(bounds);
|
||||
|
||||
[_titleField setFrame:CGRectMake(20.0, 3.0, width - 40.0, CGRectGetHeight([_titleField frame]))];
|
||||
[_titleField setFrame:_CGRectMake(20.0, 0, width - 40.0, [self toolbarOffset].height)];
|
||||
|
||||
var maxY = [self toolbarMaxY];
|
||||
if ([_titleField isHidden])
|
||||
maxY -= ([self toolbarOffset]).height;
|
||||
|
||||
[[theWindow contentView] setFrameOrigin:CGPointMake(0.0, maxY, width, CGRectGetHeight(bounds) - maxY)];
|
||||
var contentRect = _CGRectMake(0.0, maxY, width, _CGRectGetHeight(bounds) - maxY);
|
||||
|
||||
[[theWindow contentView] setFrame:contentRect];
|
||||
}
|
||||
|
||||
- (void)_enableSheet:(BOOL)enable
|
||||
{
|
||||
[super _enableSheet:enable];
|
||||
|
||||
[_closeButton setHidden:enable];
|
||||
[_titleField setHidden:enable];
|
||||
|
||||
// resize the window
|
||||
var theWindow = [self window],
|
||||
frame = [theWindow frame],
|
||||
dy = ([self toolbarOffset]).height;
|
||||
|
||||
if (enable)
|
||||
dy = -dy;
|
||||
|
||||
var newHeight = _CGRectGetMaxY(frame) + dy,
|
||||
newWidth = _CGRectGetMaxX(frame);
|
||||
|
||||
frame.size.height += dy;
|
||||
|
||||
[self setFrameSize:_CGSizeMake(newWidth, newHeight)];
|
||||
[self tile];
|
||||
[theWindow setFrame:frame display:NO animate:NO];
|
||||
[theWindow setMovableByWindowBackground:!enable];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
@import "CPTextField.j"
|
||||
@import "_CPWindowView.j"
|
||||
@import "_CPTitleableWindowView.j"
|
||||
|
||||
|
||||
var GRADIENT_HEIGHT = 41.0;
|
||||
@@ -98,31 +98,44 @@ var _CPTexturedWindowHeadGradientColor = nil,
|
||||
|
||||
var _CPStandardWindowViewBodyBackgroundColor = nil,
|
||||
_CPStandardWindowViewDividerBackgroundColor = nil,
|
||||
_CPStandardWindowViewTitleBackgroundColor = nil,
|
||||
_CPStandardWindowViewCloseButtonImage = nil,
|
||||
_CPStandardWindowViewCloseButtonHighlightedImage = nil,
|
||||
_CPStandardWindowViewCloseButtonUnsavedImage = nil,
|
||||
_CPStandardWindowViewCloseButtonUnsavedHighlightedImage = nil,
|
||||
_CPStandardWindowViewMinimizeButtonImage = nil,
|
||||
_CPStandardWindowViewMinimizeButtonHighlightedImage = nil;
|
||||
_CPStandardWindowViewMinimizeButtonHighlightedImage = nil,
|
||||
_CPStandardWindowViewThemeValues = nil;
|
||||
|
||||
var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
STANDARD_TITLEBAR_HEIGHT = 25.0;
|
||||
var STANDARD_GRADIENT_HEIGHT = 41.0;
|
||||
|
||||
@implementation _CPStandardWindowView : _CPWindowView
|
||||
@implementation _CPStandardWindowView : _CPTitleableWindowView
|
||||
{
|
||||
_CPTexturedWindowHeadView _headView;
|
||||
CPView _dividerView;
|
||||
CPView _bodyView;
|
||||
CPView _toolbarView;
|
||||
|
||||
CPTextField _titleField;
|
||||
CPButton _closeButton;
|
||||
CPButton _minimizeButton;
|
||||
|
||||
BOOL _isDocumentEdited;
|
||||
}
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
_CPStandardWindowViewThemeValues = [
|
||||
[@"title-font", [CPFont boldSystemFontOfSize:CPFontCurrentSystemSize]],
|
||||
[@"title-text-color", [CPColor colorWithWhite:22.0 / 255.0 alpha:0.75]],
|
||||
[@"title-text-color", [CPColor colorWithWhite:22.0 / 255.0 alpha:1], CPThemeStateKeyWindow],
|
||||
[@"title-text-shadow-color", [CPColor whiteColor]],
|
||||
[@"title-text-shadow-offset", CGSizeMake(0.0, 1.0)],
|
||||
[@"title-alignment", CPCenterTextAlignment],
|
||||
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
|
||||
[@"title-line-break-mode", CPLineBreakByTruncatingTail],
|
||||
[@"title-vertical-alignment", CPCenterVerticalTextAlignment]
|
||||
];
|
||||
}
|
||||
|
||||
+ (CPColor)bodyBackgroundColor
|
||||
{
|
||||
if (!_CPStandardWindowViewBodyBackgroundColor)
|
||||
@@ -139,41 +152,6 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
return _CPStandardWindowViewDividerBackgroundColor;
|
||||
}
|
||||
|
||||
+ (CPColor)titleColor
|
||||
{
|
||||
if (!_CPStandardWindowViewTitleBackgroundColor)
|
||||
_CPStandardWindowViewTitleBackgroundColor = [CPColor colorWithCalibratedRed:44.0 / 255.0 green:44.0 / 255.0 blue:44.0 / 255.0 alpha:1.0];
|
||||
|
||||
return _CPStandardWindowViewTitleBackgroundColor;
|
||||
}
|
||||
|
||||
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||
{
|
||||
var contentRect = CGRectMakeCopy(aFrameRect),
|
||||
titleBarHeight = [self titleBarHeight] + 1.0;
|
||||
|
||||
contentRect.origin.y += titleBarHeight;
|
||||
contentRect.size.height -= titleBarHeight;
|
||||
|
||||
return contentRect;
|
||||
}
|
||||
|
||||
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
|
||||
{
|
||||
var frameRect = CGRectMakeCopy(aContentRect),
|
||||
titleBarHeight = [self titleBarHeight] + 1.0;
|
||||
|
||||
frameRect.origin.y -= titleBarHeight;
|
||||
frameRect.size.height += titleBarHeight;
|
||||
|
||||
return frameRect;
|
||||
}
|
||||
|
||||
+ (float)titleBarHeight
|
||||
{
|
||||
return STANDARD_TITLEBAR_HEIGHT;
|
||||
}
|
||||
|
||||
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||
{
|
||||
var contentRect = [[self class] contentRectForFrameRect:aFrameRect],
|
||||
@@ -212,6 +190,9 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
|
||||
if (self)
|
||||
{
|
||||
// Until windows become properly themable, just set these values here in the subclass.
|
||||
[self registerThemeValues:_CPStandardWindowViewThemeValues];
|
||||
|
||||
var theClass = [self class],
|
||||
bounds = [self bounds];
|
||||
|
||||
@@ -220,7 +201,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
[_headView setAutoresizingMask:CPViewWidthSizable];;
|
||||
[_headView setHitTests:NO];
|
||||
|
||||
[self addSubview:_headView];
|
||||
[self addSubview:_headView positioned:CPWindowBelow relativeTo:_titleField];
|
||||
|
||||
_dividerView = [[CPView alloc] initWithFrame:CGRectMake(0.0, CGRectGetMaxY([_headView frame]), CGRectGetWidth(bounds), 1.0)];
|
||||
|
||||
@@ -242,24 +223,6 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
|
||||
[self setResizeIndicatorOffset:CGSizeMake(2.0, 2.0)];
|
||||
|
||||
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[_titleField setFont:[CPFont boldSystemFontOfSize:CPFontCurrentSystemSize]];
|
||||
[_titleField setAutoresizingMask:CPViewWidthSizable];
|
||||
|
||||
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
|
||||
[_titleField setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
[_titleField setAlignment:CPCenterTextAlignment];
|
||||
[_titleField setTextShadowColor:[CPColor whiteColor]];
|
||||
[_titleField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
|
||||
|
||||
[_titleField setStringValue:@"Untitled"];
|
||||
[_titleField sizeToFit];
|
||||
[_titleField setAutoresizingMask:CPViewWidthSizable];
|
||||
[_titleField setStringValue:@""];
|
||||
|
||||
[self addSubview:_titleField];
|
||||
|
||||
if (_styleMask & CPClosableWindowMask)
|
||||
{
|
||||
if (!_CPStandardWindowViewCloseButtonImage)
|
||||
@@ -272,7 +235,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
_CPStandardWindowViewCloseButtonUnsavedHighlightedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButtonUnsavedHighlighted.png"] size:CGSizeMake(16.0, 16.0)];
|
||||
}
|
||||
|
||||
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 7.0, 16.0, 16.0)];
|
||||
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 6.0, 16.0, 16.0)];
|
||||
|
||||
[_closeButton setBordered:NO];
|
||||
[self _updateCloseButton];
|
||||
@@ -326,14 +289,20 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
|
||||
var theWindow = [self window],
|
||||
bounds = [self bounds],
|
||||
width = CGRectGetWidth(bounds);
|
||||
width = _CGRectGetWidth(bounds);
|
||||
|
||||
[_headView setFrameSize:CGSizeMake(width, [self toolbarMaxY])];
|
||||
[_dividerView setFrame:CGRectMake(0.0, CGRectGetMaxY([_headView frame]), width, 1.0)];
|
||||
[_headView setFrameSize:_CGSizeMake(width, [self toolbarMaxY])];
|
||||
[_dividerView setFrame:_CGRectMake(0.0, _CGRectGetMaxY([_headView frame]), width, 1.0)];
|
||||
|
||||
var dividerMaxY = CGRectGetMaxY([_dividerView frame]);
|
||||
var dividerMaxY = 0,
|
||||
dividerMinY = 0;
|
||||
if (![_dividerView isHidden])
|
||||
{
|
||||
dividerMinY = _CGRectGetMinY([_dividerView frame]);
|
||||
dividerMaxY = _CGRectGetMaxY([_dividerView frame]);
|
||||
}
|
||||
|
||||
[_bodyView setFrame:CGRectMake(0.0, dividerMaxY, width, CGRectGetHeight(bounds) - dividerMaxY)];
|
||||
[_bodyView setFrame:_CGRectMake(0.0, dividerMaxY, width, _CGRectGetHeight(bounds) - dividerMaxY)];
|
||||
|
||||
var leftOffset = 8;
|
||||
|
||||
@@ -342,10 +311,13 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
if (_minimizeButton)
|
||||
leftOffset += 19.0;
|
||||
|
||||
[_titleField setFrame:CGRectMake(leftOffset, 5.0, width - leftOffset * 2.0, CGRectGetHeight([_titleField frame]))];
|
||||
[_titleField setFrame:_CGRectMake(leftOffset, 0, width - leftOffset * 2.0, [[self class] titleBarHeight])];
|
||||
|
||||
[[theWindow contentView] setFrameOrigin:CGPointMake(0.0, CGRectGetMaxY([_dividerView frame]))];
|
||||
var contentRect = _CGRectMake(0.0, dividerMaxY, width, _CGRectGetHeight([_bodyView frame]));
|
||||
|
||||
[[theWindow contentView] setFrame:contentRect];
|
||||
}
|
||||
|
||||
/*
|
||||
- (void)setAnimatingToolbar:(BOOL)isAnimatingToolbar
|
||||
{
|
||||
@@ -394,17 +366,46 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
|
||||
[self _updateCloseButton];
|
||||
}
|
||||
|
||||
- (void)setTitle:(CPString)aTitle
|
||||
{
|
||||
[_titleField setStringValue:aTitle];
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
{
|
||||
if (CGRectContainsPoint([_headView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
|
||||
return [self trackMoveWithEvent:anEvent];
|
||||
if (![_headView isHidden])
|
||||
if (CGRectContainsPoint([_headView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
|
||||
return [self trackMoveWithEvent:anEvent];
|
||||
|
||||
[super mouseDown:anEvent];
|
||||
}
|
||||
|
||||
- (void)_enableSheet:(BOOL)enable
|
||||
{
|
||||
[super _enableSheet:enable];
|
||||
|
||||
[_headView setHidden:enable];
|
||||
[_dividerView setHidden:enable];
|
||||
[_closeButton setHidden:enable];
|
||||
[_minimizeButton setHidden:enable];
|
||||
[_titleField setHidden:enable];
|
||||
|
||||
if (enable)
|
||||
[_bodyView setBackgroundColor:[_CPDocModalWindowView bodyBackgroundColor]];
|
||||
else
|
||||
[_bodyView setBackgroundColor:[[self class] bodyBackgroundColor]];
|
||||
|
||||
// resize the window
|
||||
var theWindow = [self window],
|
||||
frame = [theWindow frame];
|
||||
|
||||
var dy = _CGRectGetHeight([_headView frame]) + _CGRectGetHeight([_dividerView frame]);
|
||||
if (enable)
|
||||
dy = -dy;
|
||||
|
||||
var newHeight = _CGRectGetMaxY(frame) + dy,
|
||||
newWidth = _CGRectGetMaxX(frame);
|
||||
|
||||
frame.size.height += dy;
|
||||
|
||||
[self setFrameSize:_CGSizeMake(newWidth, newHeight)];
|
||||
[self tile];
|
||||
[theWindow setFrame:frame display:NO animate:NO];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* _CPTitleableWindowView.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Alexander Ljungberg.
|
||||
* Copyright 2012, SlevenBits Ltd.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "_CPWindowView.j"
|
||||
|
||||
var STANDARD_TITLEBAR_HEIGHT = 25.0;
|
||||
|
||||
@implementation _CPTitleableWindowView : _CPWindowView
|
||||
{
|
||||
CPTextField _titleField;
|
||||
}
|
||||
|
||||
+ (int)titleBarHeight
|
||||
{
|
||||
return STANDARD_TITLEBAR_HEIGHT;
|
||||
}
|
||||
|
||||
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||
{
|
||||
var contentRect = CGRectMakeCopy(aFrameRect),
|
||||
titleBarHeight = [[self class] titleBarHeight];
|
||||
|
||||
contentRect.origin.y += titleBarHeight;
|
||||
contentRect.size.height -= titleBarHeight;
|
||||
|
||||
return contentRect;
|
||||
}
|
||||
|
||||
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
|
||||
{
|
||||
var frameRect = CGRectMakeCopy(aContentRect),
|
||||
titleBarHeight = [[self class] titleBarHeight];
|
||||
|
||||
frameRect.origin.y -= titleBarHeight;
|
||||
frameRect.size.height += titleBarHeight;
|
||||
|
||||
return frameRect;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
|
||||
{
|
||||
self = [super initWithFrame:aFrame styleMask:aStyleMask];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[_titleField setHitTests:NO];
|
||||
[_titleField setStringValue:@"Untitled"];
|
||||
[_titleField sizeToFit];
|
||||
[_titleField setAutoresizingMask:CPViewWidthSizable];
|
||||
[_titleField setStringValue:@""];
|
||||
|
||||
[_titleField setFrame:CGRectMake(20.0, 3.0, CGRectGetWidth([self bounds]) - 40.0, CGRectGetHeight([_titleField frame]))];
|
||||
|
||||
[self addSubview:_titleField];
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setTitle:(CPString)aTitle
|
||||
{
|
||||
[_titleField setStringValue:aTitle];
|
||||
}
|
||||
|
||||
- (void)tile
|
||||
{
|
||||
[super tile];
|
||||
|
||||
var theWindow = [self window],
|
||||
bounds = [self bounds],
|
||||
width = CGRectGetWidth(bounds);
|
||||
|
||||
// The vertical alignment of the title is set by the theme, so just give it all available space. By default
|
||||
// the title will vertically centre within.
|
||||
[_titleField setFrame:_CGRectMake(20.0, 0, width - 40.0, [[self class] titleBarHeight])];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
[_titleField setTextColor:[self currentValueForThemeAttribute:@"title-text-color"]];
|
||||
[_titleField setFont:[self currentValueForThemeAttribute:@"title-font"]];
|
||||
[_titleField setAlignment:[self currentValueForThemeAttribute:@"title-alignment"]];
|
||||
[_titleField setVerticalAlignment:[self currentValueForThemeAttribute:@"title-vertical-alignment"]];
|
||||
[_titleField setLineBreakMode:[self currentValueForThemeAttribute:@"title-line-break-mode"]];
|
||||
[_titleField setTextShadowColor:[self currentValueForThemeAttribute:@"title-text-shadow-color"]];
|
||||
[_titleField setTextShadowOffset:[self currentValueForThemeAttribute:@"title-text-shadow-offset"]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -41,6 +41,8 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
CGPoint _mouseDraggedPoint;
|
||||
|
||||
CGRect _cachedScreenFrame;
|
||||
|
||||
CPView _sheetShadowView;
|
||||
}
|
||||
|
||||
+ (void)initialize
|
||||
@@ -61,6 +63,17 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
return CGRectMakeCopy(aContentRect);
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
{
|
||||
return "window";
|
||||
}
|
||||
|
||||
+ (id)themeAttributes
|
||||
{
|
||||
return [CPDictionary dictionaryWithObjects:[[CPColor blackColor], [CPFont systemFontOfSize:CPFontCurrentSystemSize], [CPNull null], _CGSizeMakeZero(), CPCenterTextAlignment, CPLineBreakByTruncatingTail, CPTopVerticalTextAlignment]
|
||||
forKeys:[@"title-text-color", @"title-font", @"title-text-shadow-color", @"title-text-shadow-offset", @"title-alignment", @"title-line-break-mode", @"title-vertical-alignment"]];
|
||||
}
|
||||
|
||||
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||
{
|
||||
return [[self class] contentRectForFrameRect:aFrameRect];
|
||||
@@ -195,7 +208,6 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]],
|
||||
origin = [self _pointWithinScreenFrame:CGPointMake(_CGRectGetMinX(frame) + (location.x - _mouseDraggedPoint.x),
|
||||
_CGRectGetMinY(frame) + (location.y - _mouseDraggedPoint.y))];
|
||||
|
||||
[theWindow setFrameOrigin:origin];
|
||||
|
||||
_mouseDraggedPoint = [self _pointWithinScreenFrame:location];
|
||||
@@ -204,6 +216,17 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
[CPApp setTarget:self selector:@selector(trackMoveWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
}
|
||||
|
||||
- (void)setFrameSize:(CGSize)newSize
|
||||
{
|
||||
[super setFrameSize:newSize];
|
||||
|
||||
// reposition sheet if the parent window resizes or moves
|
||||
var theWindow = [self window];
|
||||
|
||||
if ([theWindow attachedSheet])
|
||||
[theWindow _setAttachedSheetFrameOrigin];
|
||||
}
|
||||
|
||||
- (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator
|
||||
{
|
||||
if (shouldShowResizeIndicator)
|
||||
@@ -347,6 +370,23 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
- (void)noteKeyWindowStateChanged
|
||||
{
|
||||
if ([[self window] isKeyWindow])
|
||||
[self setThemeState:CPThemeStateKeyWindow];
|
||||
else
|
||||
[self unsetThemeState:CPThemeStateKeyWindow];
|
||||
}
|
||||
|
||||
- (void)noteMainWindowStateChanged
|
||||
{
|
||||
if ([[self window] isMainWindow])
|
||||
[self setThemeState:CPThemeStateMainWindow];
|
||||
else
|
||||
[self unsetThemeState:CPThemeStateMainWindow];
|
||||
}
|
||||
|
||||
/*
|
||||
- (void)setAnimatingToolbar:(BOOL)isAnimatingToolbar
|
||||
{
|
||||
@@ -367,4 +407,21 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
[self addSubview:_resizeIndicator];
|
||||
}
|
||||
|
||||
- (void)_enableSheet:(BOOL)enable
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
var bundle = [CPBundle bundleForClass:[CPWindow class]];
|
||||
_sheetShadowView = [[CPView alloc] initWithFrame:_CGRectMake(0, 0, _CGRectGetWidth([self bounds]), 8)];
|
||||
[_sheetShadowView setAutoresizingMask:CPViewWidthSizable];
|
||||
[_sheetShadowView setBackgroundColor:[CPColor colorWithPatternImage:[[CPImage alloc]
|
||||
initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowAttachedSheetShadow.png"] size:_CGSizeMake(9, 8)]]];
|
||||
[self addSubview:_sheetShadowView];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_sheetShadowView removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -181,8 +181,7 @@
|
||||
|
||||
if (!_window)
|
||||
{
|
||||
var reason = [CPString stringWithFormat:@"Window for %@ could not be loaded from Cib or no window specified. \
|
||||
Override loadWindow to load the window manually.", self];
|
||||
var reason = [CPString stringWithFormat:@"Window for %@ could not be loaded from Cib or no window specified. Override loadWindow to load the window manually.", self];
|
||||
|
||||
[CPException raise:CPInternalInconsistencyException reason:reason];
|
||||
}
|
||||
@@ -336,18 +335,21 @@
|
||||
if (!_viewControllerContainerView && !aView)
|
||||
return;
|
||||
|
||||
var viewControllerView = [[self viewController] view],
|
||||
var viewController = [self viewController],
|
||||
viewControllerView = [viewController isViewLoaded] ? [viewController view] : nil,
|
||||
contentView = [[self window] contentView];
|
||||
|
||||
if (aView)
|
||||
{
|
||||
[aView setFrame:[contentView frame]];
|
||||
[aView setAutoresizingMask:[contentView autoresizingMask]];
|
||||
|
||||
if (viewControllerView)
|
||||
{
|
||||
[viewControllerView removeFromSuperview];
|
||||
[aView addSubview:viewControllerView];
|
||||
}
|
||||
|
||||
[[self window] setContentView:aView];
|
||||
}
|
||||
else if (viewControllerView)
|
||||
@@ -379,11 +381,12 @@
|
||||
return;
|
||||
|
||||
var containerView = [self viewControllerContainerView],
|
||||
newView = [aViewController view];
|
||||
newView = [aViewController isViewLoaded] ? [aViewController view] : nil;
|
||||
|
||||
if (containerView)
|
||||
{
|
||||
var oldView = [_viewController view];
|
||||
var oldView = [_viewController isViewLoaded] ? [_viewController view] : nil;
|
||||
|
||||
if (oldView)
|
||||
{
|
||||
[newView setFrame:[oldView frame]];
|
||||
@@ -408,6 +411,7 @@
|
||||
{
|
||||
var view = [[CPView alloc] init],
|
||||
contentView = [[self window] contentView];
|
||||
|
||||
[view setFrame:[contentView frame]];
|
||||
[view setAutoresizingMask:[contentView autoresizingMask]];
|
||||
[[self window] setContentView:view]
|
||||
|
||||
@@ -25,8 +25,6 @@ var DOMFixedWidthSpanElement = nil,
|
||||
DOMMetricsDivElement = nil,
|
||||
DOMMetricsTextSpanElement = nil,
|
||||
DOMMetricsImgElement = nil,
|
||||
DOMIFrameElement = nil,
|
||||
DOMIFrameDocument = nil,
|
||||
DefaultFont = nil;
|
||||
|
||||
@implementation CPPlatformString : CPBasePlatformString
|
||||
@@ -48,50 +46,27 @@ var DOMFixedWidthSpanElement = nil,
|
||||
|
||||
+ (void)createDOMElements
|
||||
{
|
||||
var style;
|
||||
var style,
|
||||
bodyElement = [CPPlatform mainBodyElement];
|
||||
|
||||
DOMIFrameElement = document.createElement("iframe");
|
||||
// necessary for Safari caching bug:
|
||||
DOMIFrameElement.name = "iframe_" + FLOOR(RAND() * 10000);
|
||||
DOMIFrameElement.className = "cpdontremove";
|
||||
|
||||
style = DOMIFrameElement.style;
|
||||
style.position = "absolute";
|
||||
style.left = "-100px";
|
||||
style.top = "-100px";
|
||||
style.width = "1px";
|
||||
style.height = "1px";
|
||||
style.borderWidth = "0px";
|
||||
style.overflow = "hidden";
|
||||
style.zIndex = 100000000000;
|
||||
|
||||
var bodyElement = [CPPlatform mainBodyElement];
|
||||
|
||||
bodyElement.appendChild(DOMIFrameElement);
|
||||
|
||||
DOMIFrameDocument = (DOMIFrameElement.contentDocument || DOMIFrameElement.contentWindow.document);
|
||||
DOMIFrameDocument.write('<!DOCTYPE html><head></head><body></body></html>');
|
||||
DOMIFrameDocument.close();
|
||||
|
||||
// IE needs this wide <div> to prevent unwanted text wrapping:
|
||||
var DOMDivElement = DOMIFrameDocument.createElement("div");
|
||||
DOMDivElement.style.position = "absolute";
|
||||
DOMDivElement.style.width = "100000px";
|
||||
|
||||
DOMIFrameDocument.body.appendChild(DOMDivElement);
|
||||
|
||||
DOMFlexibleWidthSpanElement = DOMIFrameDocument.createElement("span");
|
||||
DOMFlexibleWidthSpanElement = document.createElement("span");
|
||||
DOMFlexibleWidthSpanElement.className = "cpdontremove";
|
||||
style = DOMFlexibleWidthSpanElement.style;
|
||||
style.position = "absolute";
|
||||
style.left = "-100000px";
|
||||
style.zIndex = -100000;
|
||||
style.visibility = "visible";
|
||||
style.padding = "0px";
|
||||
style.margin = "0px";
|
||||
style.whiteSpace = "pre";
|
||||
|
||||
DOMFixedWidthSpanElement = DOMIFrameDocument.createElement("span");
|
||||
DOMFixedWidthSpanElement = document.createElement("span");
|
||||
DOMFixedWidthSpanElement.className = "cpdontremove";
|
||||
style = DOMFixedWidthSpanElement.style;
|
||||
style.display = "block";
|
||||
style.position = "absolute";
|
||||
style.left = "-100000px";
|
||||
style.zIndex = -10000;
|
||||
style.visibility = "visible";
|
||||
style.padding = "0px";
|
||||
style.margin = "0px";
|
||||
@@ -112,27 +87,31 @@ var DOMFixedWidthSpanElement = nil,
|
||||
style.whiteSpace = "pre";
|
||||
}
|
||||
|
||||
DOMDivElement.appendChild(DOMFlexibleWidthSpanElement);
|
||||
DOMDivElement.appendChild(DOMFixedWidthSpanElement);
|
||||
bodyElement.appendChild(DOMFlexibleWidthSpanElement);
|
||||
bodyElement.appendChild(DOMFixedWidthSpanElement);
|
||||
}
|
||||
|
||||
+ (void)createDOMMetricsElements
|
||||
{
|
||||
if (!DOMIFrameElement)
|
||||
[self createDOMElements];
|
||||
var style,
|
||||
bodyElement = [CPPlatform mainBodyElement];
|
||||
|
||||
var style;
|
||||
|
||||
DOMMetricsDivElement = DOMIFrameDocument.createElement("div");
|
||||
DOMMetricsDivElement = document.createElement("div");
|
||||
DOMMetricsDivElement.className = "cpdontremove";
|
||||
DOMMetricsDivElement.style.position = "absolute";
|
||||
DOMMetricsDivElement.style.left = "-10000px";
|
||||
DOMMetricsDivElement.style.zIndex = -10000;
|
||||
DOMMetricsDivElement.style.width = "100000px";
|
||||
|
||||
DOMIFrameDocument.body.appendChild(DOMMetricsDivElement);
|
||||
bodyElement.appendChild(DOMMetricsDivElement);
|
||||
|
||||
DOMMetricsTextSpanElement = DOMIFrameDocument.createElement("span");
|
||||
DOMMetricsTextSpanElement = document.createElement("span");
|
||||
DOMMetricsTextSpanElement.className = "cpdontremove";
|
||||
DOMMetricsTextSpanElement.innerHTML = "x";
|
||||
style = DOMMetricsTextSpanElement.style;
|
||||
style.position = "absolute";
|
||||
style.left = "-10000px";
|
||||
style.zIndex = -10000;
|
||||
style.visibility = "visible";
|
||||
style.padding = "0px";
|
||||
style.margin = "0px";
|
||||
@@ -140,12 +119,16 @@ var DOMFixedWidthSpanElement = nil,
|
||||
|
||||
var imgPath = [[CPBundle bundleForClass:[CPView class]] pathForResource:@"empty.png"];
|
||||
|
||||
DOMMetricsImgElement = DOMIFrameDocument.createElement("img");
|
||||
DOMMetricsImgElement = document.createElement("img");
|
||||
DOMMetricsImgElement.className = "cpdontremove";
|
||||
DOMMetricsImgElement.setAttribute("src", imgPath);
|
||||
DOMMetricsImgElement.setAttribute("width", "1");
|
||||
DOMMetricsImgElement.setAttribute("height", "1");
|
||||
DOMMetricsImgElement.setAttribute("alt", "");
|
||||
style = DOMMetricsImgElement.style;
|
||||
style.position = "absolute";
|
||||
style.left = "-10000px";
|
||||
style.zIndex = -10000;
|
||||
style.visibility = "visible";
|
||||
style.padding = "0px";
|
||||
style.margin = "0px";
|
||||
@@ -158,7 +141,7 @@ var DOMFixedWidthSpanElement = nil,
|
||||
|
||||
+ (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth
|
||||
{
|
||||
if (!DOMIFrameElement)
|
||||
if (!DOMFixedWidthSpanElement)
|
||||
[self createDOMElements];
|
||||
|
||||
var span;
|
||||
|
||||
|
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 455 B |
|
Before Width: | Height: | Size: 486 B After Width: | Height: | Size: 442 B |
|
Before Width: | Height: | Size: 617 B After Width: | Height: | Size: 580 B |
|
Before Width: | Height: | Size: 578 B After Width: | Height: | Size: 541 B |
|
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 409 B |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 339 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 338 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 144 B |
|
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 144 B |
|
Before Width: | Height: | Size: 125 B After Width: | Height: | Size: 84 B |
|
Before Width: | Height: | Size: 112 B After Width: | Height: | Size: 72 B |
|
Before Width: | Height: | Size: 116 B After Width: | Height: | Size: 72 B |
|
Before Width: | Height: | Size: 182 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 190 B After Width: | Height: | Size: 138 B |
|
Before Width: | Height: | Size: 115 B After Width: | Height: | Size: 77 B |
|
Before Width: | Height: | Size: 126 B After Width: | Height: | Size: 81 B |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 108 B |
|
Before Width: | Height: | Size: 184 B After Width: | Height: | Size: 143 B |
|
Before Width: | Height: | Size: 215 B After Width: | Height: | Size: 172 B |
|
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 194 B |
|
Before Width: | Height: | Size: 169 B After Width: | Height: | Size: 108 B |
|
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 126 B |
|
Before Width: | Height: | Size: 205 B After Width: | Height: | Size: 131 B |
|
Before Width: | Height: | Size: 191 B After Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 242 B After Width: | Height: | Size: 195 B |
|
Before Width: | Height: | Size: 186 B After Width: | Height: | Size: 147 B |
|
Before Width: | Height: | Size: 216 B After Width: | Height: | Size: 172 B |
|
Before Width: | Height: | Size: 229 B After Width: | Height: | Size: 189 B |
|
Before Width: | Height: | Size: 186 B After Width: | Height: | Size: 114 B |
|
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 111 B |
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 218 B |
|
Before Width: | Height: | Size: 164 B After Width: | Height: | Size: 123 B |
|
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 213 B |
|
Before Width: | Height: | Size: 246 B After Width: | Height: | Size: 205 B |
|
Before Width: | Height: | Size: 178 B After Width: | Height: | Size: 120 B |
|
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 205 B |
|
Before Width: | Height: | Size: 222 B After Width: | Height: | Size: 142 B |
|
Before Width: | Height: | Size: 169 B After Width: | Height: | Size: 88 B |
|
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 137 B |
|
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 140 B |
|
Before Width: | Height: | Size: 141 B After Width: | Height: | Size: 89 B |
|
Before Width: | Height: | Size: 222 B After Width: | Height: | Size: 140 B |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 956 B After Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 976 B After Width: | Height: | Size: 239 B |
|
Before Width: | Height: | Size: 958 B After Width: | Height: | Size: 325 B |
|
Before Width: | Height: | Size: 938 B After Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 123 B After Width: | Height: | Size: 86 B |
|
Before Width: | Height: | Size: 265 B After Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 234 B |
|
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 82 B |
|
Before Width: | Height: | Size: 126 B After Width: | Height: | Size: 80 B |
|
Before Width: | Height: | Size: 125 B After Width: | Height: | Size: 88 B |
|
Before Width: | Height: | Size: 243 B After Width: | Height: | Size: 206 B |
|
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 233 B |
|
Before Width: | Height: | Size: 125 B After Width: | Height: | Size: 84 B |
|
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 144 B |
|
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 144 B |
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 74 B |
|
Before Width: | Height: | Size: 116 B After Width: | Height: | Size: 72 B |
|
Before Width: | Height: | Size: 123 B After Width: | Height: | Size: 79 B |
|
Before Width: | Height: | Size: 182 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 190 B After Width: | Height: | Size: 138 B |
|
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 86 B |
|
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 79 B |
|
Before Width: | Height: | Size: 158 B After Width: | Height: | Size: 114 B |
|
Before Width: | Height: | Size: 111 B After Width: | Height: | Size: 70 B |
|
Before Width: | Height: | Size: 157 B After Width: | Height: | Size: 113 B |
|
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 112 B |
|
Before Width: | Height: | Size: 245 B After Width: | Height: | Size: 208 B |