Merge remote-tracking branch 'cappuccino/master'

This commit is contained in:
daboe01
2018-04-28 16:35:05 +02:00
69 changed files with 1891 additions and 233 deletions
+1
View File
@@ -17,3 +17,4 @@ Tests/Manual/**/*.xcodeproj
*.sublime-project
*.sublime-workspace
*.tm_properties
*.idea
+1 -1
View File
@@ -216,7 +216,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
}
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminate_
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminate_;
if ([_delegate respondsToSelector:@selector(applicationShouldTerminateMessage:)])
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminateMessage_
+1 -1
View File
@@ -563,7 +563,7 @@
*/
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
{
[self _selectionWillChange]
[self _selectionWillChange];
var r = [self __setSelectionIndexes:indexes avoidEmpty:NO];
[self _selectionDidChange];
return r;
+228 -4
View File
@@ -103,7 +103,8 @@ var cachedBlackColor,
@"alternate-selected-control-color": [CPNull null],
@"secondary-selected-control-color": [CPNull null],
@"selected-text-background-color": [CPNull null],
@"selected-text-inactive-background-color": [CPNull null]
@"selected-text-inactive-background-color": [CPNull null],
@"css-based": NO
};
}
@@ -876,9 +877,221 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
@end
#pragma mark -
#pragma mark CSS Theming
// The code below adds support for CSS theming with 100% compatibility with current theming system.
// The idea is to extend CPColor (and CPImage) with CSS components and adapt low level UI components to
// support this new kind of CPColor/CPImage. See CPImageView, CPView and _CPImageAndTextView.
//
// To create a CPColor that uses CSS, simply use the new class method :
// + (CPColor)colorWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary
// where beforeDictionary & afterDictionary are related to ::before & ::after pseudo-elements.
// If you don't need them, just use the simplified class method :
// + (CPColor)colorWithCSSDictionary:(CPDictionary)aDictionary
//
// Example :
// buttonCssColor = [CPColor colorWithCSSDictionary:@{
// @"background-color": A3ColorBackgroundWhite,
// @"border-color": A3ColorActiveBorder,
// @"border-style": @"solid",
// @"border-width": @"1px",
// @"border-radius": @"3px",
// @"box-sizing": @"border-box"
// }
// beforeDictionary:@{
// @"background-color": @"rgb(225,225,225)",
// @"bottom": @"3px",
// @"content": @"''",
// @"position": @"absolute",
// @"right": @"21px",
// @"top": @"3px",
// @"width": @"1px"
// }
// afterDictionary:@{
// @"content": @"''",
// @"bottom": @"3px",
// @"right": @"6px",
// @"top": @"1px",
// @"position": @"absolute",
// @"height": @"14px",
// @"width": @"9px",
// @"margin": @"2px 0px 2px 0px",
// @"background-image": @"url(%%packed.png)",
// @"background-position": @"0px -64px",
// @"background-repeat": @"no-repeat",
// @"background-size": @"100px 400px"
// }];
//
// Remark : Please note the special URL of the background image used in this example : url(%%packed.png)
// During theme loading, "%%" will be replaced by the path to the theme blend resources folder.
// Typically, a CSS theme will use some (rare) images all packed together in a single image resource (see packed.png in Aristo3 theme)
//
// Also, please note that if you don't use one of the CSS components, you can either set it to nil (best solution) or to an empty dictionary, like :
// aCssColor = [CPColor colorWithCSSDictionary:@{} beforeDictionary:nil afterDictionary:@{ ... }];
//
// You can use -(BOOL)isCSSBased to determine how to cope with it in your code.
// -(BOOL)hasCSSDictionary, -(BOOL)hasCSSBeforeDictionary and -(BOOL)hasCSSAfterDictionary are convience methods you can use.
//
// Remark : -(void)restorePreviousCSSState and -(DOMElement)applyCSSColorForView are meant to be used by low level UI widgets (like CPView) to implement
// CSS theme support.
@implementation CPColor (CSSTheming)
{
CPDictionary _cssDictionary @accessors(property=cssDictionary);
CPDictionary _cssBeforeDictionary @accessors(property=cssBeforeDictionary);
CPDictionary _cssAfterDictionary @accessors(property=cssAfterDictionary);
}
+ (CPColor)colorWithCSSDictionary:(CPDictionary)aDictionary
{
return [[CPColor alloc] _initWithCSSDictionary:aDictionary beforeDictionary:nil afterDictionary:nil];
}
+ (CPColor)colorWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary
{
return [[CPColor alloc] _initWithCSSDictionary:aDictionary beforeDictionary:beforeDictionary afterDictionary:afterDictionary];
}
- (id)_initWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary
{
self = [super init];
if (self)
{
_cssDictionary = aDictionary;
_cssBeforeDictionary = beforeDictionary;
_cssAfterDictionary = afterDictionary;
_components = [0.0, 0.0, 0.0, 1.0];
_theme = [CPTheme defaultTheme];
_themeState = CPThemeStateNormal;
[self _loadThemeAttributes];
}
return self;
}
- (BOOL)isCSSBased
{
return !!(_cssDictionary || _cssBeforeDictionary || _cssAfterDictionary);
}
- (BOOL)hasCSSDictionary
{
return ([_cssDictionary count] > 0);
}
- (BOOL)hasCSSBeforeDictionary
{
return ([_cssBeforeDictionary count] > 0);
}
- (BOOL)hasCSSAfterDictionary
{
return ([_cssAfterDictionary count] > 0);
}
- (void)restorePreviousCSSState:(CPArrayRef)aPreviousStateRef forDOMElement:(DOMElement)aDOMElement
{
#if PLATFORM(DOM)
var aPreviousState = @deref(aPreviousStateRef);
for (var i = 0, count = aPreviousState.length; i < count; i++)
aDOMElement.style[aPreviousState[i][0]] = aPreviousState[i][1];
@deref(aPreviousStateRef) = @[];
#endif
}
- (DOMElement)applyCSSColorForView:(CPView)aView onDOMElement:(DOMElement)aDOMElement styleNode:(DOMElement)aStyleNode previousState:(CPArrayRef)aPreviousStateRef
{
#if PLATFORM(DOM)
var aPreviousState = @deref(aPreviousStateRef);
[_cssDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
[aPreviousState addObject:@[aKey, aDOMElement.style[aKey]]];
aDOMElement.style[aKey] = anObject;
}];
if ([self hasCSSBeforeDictionary] || [self hasCSSAfterDictionary])
{
// We need to create a unique class name
var styleClassName = @".CP" + [aView UID],
styleContent = @"";
if ([self hasCSSBeforeDictionary])
{
styleContent += styleClassName + @"::before { ";
[_cssBeforeDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
styleContent += aKey + ": " + anObject + "; ";
}];
styleContent += "} ";
}
if ([self hasCSSAfterDictionary])
{
styleContent += styleClassName + @"::after { ";
[_cssAfterDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
styleContent += aKey + ": " + anObject + "; ";
}];
styleContent += "} ";
}
var styleDescription = document.createTextNode(styleContent);
if (!aStyleNode)
{
aStyleNode = document.createElement("style");
aView._DOMElement.insertBefore(aStyleNode, aView._DOMElement.firstChild);
aStyleNode.appendChild(styleDescription);
}
else
{
aStyleNode.replaceChild(styleDescription, aStyleNode.firstChild);
}
[aView setDOMClassName:@"CP"+[aView UID]];
}
else
{
// no before/after so remove aStyleNode if existing
if (aStyleNode)
{
aView._DOMElement.removeChild(aStyleNode);
aStyleNode = nil;
}
}
// Return actualised values
@deref(aPreviousStateRef) = aPreviousState;
return aStyleNode;
#endif
}
@end
#pragma mark -
/// @cond IGNORE
var CPColorComponentsKey = @"CPColorComponentsKey",
CPColorPatternImageKey = @"CPColorPatternImageKey";
var CPColorComponentsKey = @"CPColorComponentsKey",
CPColorPatternImageKey = @"CPColorPatternImageKey",
CPColorCssDictionaryKey = @"CPColorCssDictionaryKey",
CPColorCssBeforeDictionaryKey = @"CPColorCssBeforeDictionaryKey",
CPColorCssAfterDictionaryKey = @"CPColorCssAfterDictionaryKey";
/// @endcond
@implementation CPColor (CPCoding)
@@ -891,6 +1104,10 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
{
if ([aCoder containsValueForKey:CPColorPatternImageKey])
self = [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
else if ([aCoder containsValueForKey:CPColorCssDictionaryKey])
self = [self _initWithCSSDictionary:[aCoder decodeObjectForKey:CPColorCssDictionaryKey]
beforeDictionary:[aCoder decodeObjectForKey:CPColorCssBeforeDictionaryKey]
afterDictionary:[aCoder decodeObjectForKey:CPColorCssAfterDictionaryKey]];
else
self = [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
@@ -907,6 +1124,12 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
{
if (_patternImage)
[aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey];
else if (_cssDictionary)
{
[aCoder encodeObject:_cssDictionary forKey:CPColorCssDictionaryKey];
[aCoder encodeObject:_cssBeforeDictionary forKey:CPColorCssBeforeDictionaryKey];
[aCoder encodeObject:_cssAfterDictionary forKey:CPColorCssAfterDictionaryKey];
}
else
[aCoder encodeObject:_components forKey:CPColorComponentsKey];
@@ -1247,7 +1470,8 @@ var patternColorsFromPattern = function(pattern, attributes, imageFactory)
bottomHeight,
centerWidthHeight,
centerIsNil,
numParts;
numParts,
isVertical;
// positions are mandatory
if (pattern.indexOf("{position}") < 0)
+1 -1
View File
@@ -247,7 +247,7 @@
_blackWheelImage = new Image();
_blackWheelImage.src = path;
_blackWheelImage.style.opacity = "0";
_blackWheelImage.style.filter = "alpha(opacity=0)"
_blackWheelImage.style.filter = "alpha(opacity=0)";
_blackWheelImage.style.position = "absolute";
_DOMElement.appendChild(_wheelImage);
+3 -3
View File
@@ -352,8 +352,8 @@ CPEraDatePickerElementFlag = 0x0100;
if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
{
// constrain timeInterval also
var aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;}
var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;}
var aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;};
var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;};
[_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef];
}
@@ -694,7 +694,7 @@ var CPDatePickerModeKey = @"CPDatePickerModeKey",
[aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
[aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey];
[aCoder encodeObject:_minDate forKey:CPMinDateKey];
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey]
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey];
[aCoder encodeObject:_dateValue forKey:CPDateValueKey];;
[aCoder encodeObject:_textFont forKey:CPTextFontKey];
[aCoder encodeObject:_locale forKey:CPLocaleKey];
+10 -10
View File
@@ -85,7 +85,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
{
if (self = [super initWithFrame:aFrame])
{
_datePicker = aDatePicker
_datePicker = aDatePicker;
[self _init];
}
@@ -435,7 +435,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
break;
default:
return CPShortWeekDayNameArrayEn
return CPShortWeekDayNameArrayEn;
break;
}
}
@@ -464,7 +464,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
break;
default:
return CPShortMonthNameArrayEn
return CPShortMonthNameArrayEn;
break;
}
@@ -526,11 +526,11 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
var dayLabel = _dayLabels[i];
[dayLabel setStringValue:dayNames[i]];
[dayLabel sizeToFit]
[dayLabel sizeToFit];
[dayLabel setFrameOrigin:CGPointMake(sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2, 23)];
if (i == 0)
firstDayTileX = sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2
firstDayTileX = sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2;
}
// Title
@@ -769,7 +769,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
tileDate = [[tile date] copy],
selected = NO;
[tileDate _resetToMidnight]
[tileDate _resetToMidnight];
if (aStartDate)
selected = tileDate >= aStartDate && tileDate <= endDate;
@@ -845,7 +845,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
// Very usefull to avoid to have a line of two pixels instead one
if (!isBorderPair)
y += 0.5
y += 0.5;
CGContextMoveToPoint(context, 0, y);
CGContextAddLineToPoint(context, [self bounds].size.width, y);
@@ -857,7 +857,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
// Very usefull to avoid to have a line of two pixels instead one
if (!isBorderPair)
x += 0.5
x += 0.5;
CGContextMoveToPoint(context, x, 0);
CGContextAddLineToPoint(context, x, [self bounds].size.height);
@@ -869,7 +869,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
// Very usefull to avoid to have a line of two pixels instead one
if (!isBorderPair)
y += 0.5
y += 0.5;
CGContextMoveToPoint(context, 0, y);
CGContextAddLineToPoint(context, [self bounds].size.width, y);
@@ -897,7 +897,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
_clickDate = [dateTile copy];
_dragDate = nil;
_indexDayTile = -1;
_eventDragged = nil
_eventDragged = nil;
_datePicker._invokedByUserEvent = YES;
+1 -1
View File
@@ -142,7 +142,7 @@ var RADIANS = Math.PI / 180;
if ([_datePicker _isAmericanFormat])
{
if (dateValue.getHours() > 11)
[_PMAMTextField setStringValue:@"PM"]
[_PMAMTextField setStringValue:@"PM"];
else
[_PMAMTextField setStringValue:@"AM"];
+1 -1
View File
@@ -80,7 +80,7 @@ var CPZeroKeyCode = 48,
{
if (self = [super initWithFrame:aFrame])
{
_datePicker = aDatePicker
_datePicker = aDatePicker;
[self _init];
}
return self;
+2 -2
View File
@@ -66,7 +66,7 @@ var _CPEventPeriodicEventPeriod = 0,
CPWindow _window;
Number _windowNumber;
CPString _characters;
CPString _charactersIgnoringModifiers
CPString _charactersIgnoringModifiers;
BOOL _isARepeat;
unsigned _keyCode;
DOMEvent _DOMEvent;
@@ -642,7 +642,7 @@ var _CPEventPeriodicEventPeriod = 0,
- (CPTrackingArea)trackingArea
{
if ((_type !== CPMouseEntered) && (_type !== CPMouseExited) && (_type !== CPCursorUpdate))
[CPException raise:CPInternalInconsistencyException format:@"You can't call trackingArea for events of type %#x", _type]
[CPException raise:CPInternalInconsistencyException format:@"You can't call trackingArea for events of type %#x", _type];
return _trackingArea;
}
+1 -1
View File
@@ -163,7 +163,7 @@ following:
if (normalizedFaces === _CPFontSystemFontFace)
return;
[self _invalidateSystemFontCache]
[self _invalidateSystemFontCache];
_CPFontSystemFontFace = aFace;
}
+219 -2
View File
@@ -246,7 +246,7 @@ function CPAppKitImage(aFilename, aSize)
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d");
canvas.width = _image.width,
canvas.width = _image.width;
canvas.height = _image.height;
ctx.drawImage(_image, 0, 0);
@@ -509,6 +509,212 @@ function CPAppKitImage(aFilename, aSize)
@end
#pragma mark -
#pragma mark CSS Theming
// The code below adds support for CSS theming with 100% compatibility with current theming system.
// The idea is to extend CPImage (and CPColor) with CSS components and adapt low level UI components to
// support this new kind of CPColor/CPImage. See CPImageView, CPView and _CPImageAndTextView.
//
// To create a CPImage that uses CSS, simply use the new class method :
// + (CPImage)imageWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary size:(CGSize)aSize
// where beforeDictionary & afterDictionary are related to ::before & ::after pseudo-elements.
// If you don't need them, just use the simplified class method :
// + (CPImage)imageWithCSSDictionary:(CPDictionary)aDictionary size:(CGSize)aSize
//
// Examples :
// regularImageNormal = [CPImage imageWithCSSDictionary:@{
// @"border-color": A3ColorActiveBorder,
// @"border-style": @"solid",
// @"border-width": @"1px",
// @"border-radius": @"50%",
// @"box-sizing": @"border-box",
// @"background-color": A3ColorBackgroundWhite,
// @"transition-duration": @"0.35s",
// @"transition-property": @"all",
// @"transition-timing-function": @"ease"
// }
// size:CGSizeMake(16,16)];
//
// imageSearch = [CPImage imageWithCSSDictionary:@{
// @"background-image": @"url(%%packed.png)",
// @"background-position": @"-16px -32px",
// @"background-repeat": @"no-repeat",
// @"background-size": @"100px 400px"
// }
// size:CGSizeMake(16,16)];
//
// Remark : Please note the special URL of the background image used in this example : url(%%packed.png)
// During theme loading, "%%" will be replaced by the path to the theme blend resources folder.
// Typically, a CSS theme will use some (rare) images all packed together in a single image resource (see packed.png in Aristo3 theme)
//
// Also, please note that if you don't use one of the CSS components, you can either set it to nil (best solution) or to an empty dictionary, like :
// aCssImage = [CPImage imageWithCSSDictionary:@{} beforeDictionary:nil afterDictionary:@{ ... }];
//
// You can use -(BOOL)isCSSBased to determine how to cope with it in your code.
// -(BOOL)hasCSSDictionary, -(BOOL)hasCSSBeforeDictionary and -(BOOL)hasCSSAfterDictionary are convience methods you can use.
//
// Remark : -(DOMElement)applyCSSImageForView is meant to be used by low level UI widgets (like CPImageView and _CPImageAndTextView) to implement CSS theme support.
//
// In some circumstances, you may have to clear a CSS image. You can do this easily by replacing your current image with the special dummy empty CSS image :
// [CPImage dummyCSSImageOfSize:CGSizeMake(someWidth, someHeight)]
@implementation CPImage (CSSTheming)
{
CPDictionary _cssDictionary @accessors(property=cssDictionary);
CPDictionary _cssBeforeDictionary @accessors(property=cssBeforeDictionary);
CPDictionary _cssAfterDictionary @accessors(property=cssAfterDictionary);
}
+ (CPImage)imageWithCSSDictionary:(CPDictionary)aDictionary size:(CGSize)aSize
{
return [[CPImage alloc] initWithCSSDictionary:aDictionary beforeDictionary:nil afterDictionary:nil size:aSize];
}
+ (CPImage)imageWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary size:(CGSize)aSize
{
return [[CPImage alloc] initWithCSSDictionary:aDictionary beforeDictionary:beforeDictionary afterDictionary:afterDictionary size:aSize];
}
+ (CPImage)dummyCSSImageOfSize:(CGSize)aSize
{
// This is used to clear a previous CSS image
return [[CPImage alloc] initWithCSSDictionary:@{} beforeDictionary:nil afterDictionary:nil size:aSize];
}
- (id)initWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary size:(CGSize)aSize
{
self = [super init];
if (self)
{
_size = CGSizeMakeCopy(aSize);
_filename = @"CSS image";
_loadStatus = CPImageLoadStatusCompleted;
_cssDictionary = aDictionary;
_cssBeforeDictionary = beforeDictionary;
_cssAfterDictionary = afterDictionary;
}
return self;
}
- (BOOL)isCSSBased
{
return !!(_cssDictionary || _cssBeforeDictionary || _cssAfterDictionary);
}
- (BOOL)hasCSSDictionary
{
return ([_cssDictionary count] > 0);
}
- (BOOL)hasCSSBeforeDictionary
{
return ([_cssBeforeDictionary count] > 0);
}
- (BOOL)hasCSSAfterDictionary
{
return ([_cssAfterDictionary count] > 0);
}
- (DOMElement)applyCSSImageForView:(CPView)aView onDOMElement:(DOMElement)aDOMElement styleNode:(DOMElement)aStyleNode previousState:(CPArrayRef)aPreviousStateRef
{
#if PLATFORM(DOM)
// First, restore previous CSS styling before applying the new one
var aPreviousState = @deref(aPreviousStateRef);
for (var i = 0, count = aPreviousState.length; i < count; i++)
aDOMElement.style[aPreviousState[i][0]] = aPreviousState[i][1];
aPreviousState = @[];
// Then apply new CSS styling
[_cssDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
[aPreviousState addObject:@[aKey, aDOMElement.style[aKey]]];
aDOMElement.style[aKey] = anObject;
}];
if (_cssBeforeDictionary || _cssAfterDictionary)
{
// We need to create a unique class name
var styleClassName = @".CP" + [aView UID],
styleContent = @"";
if (_cssBeforeDictionary)
{
styleContent += styleClassName + @"::before { ";
[_cssBeforeDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
styleContent += aKey + ": " + anObject + "; ";
}];
styleContent += "} ";
}
if (_cssAfterDictionary)
{
styleContent += styleClassName + @"::after { ";
[_cssAfterDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
styleContent += aKey + ": " + anObject + "; ";
}];
styleContent += "} ";
}
var styleDescription = document.createTextNode(styleContent);
if (!aStyleNode)
{
aStyleNode = document.createElement("style");
aView._DOMElement.insertBefore(aStyleNode, aView._DOMElement.firstChild);
aStyleNode.appendChild(styleDescription);
}
else
{
aStyleNode.replaceChild(styleDescription, aStyleNode.firstChild);
}
[aView setDOMClassName:@"CP"+[aView UID]];
}
else
{
// no before/after so remove aStyleNode if existing
if (aStyleNode)
{
aView._DOMElement.removeChild(aStyleNode);
aStyleNode = nil;
}
}
// Return actualised values
@deref(aPreviousStateRef) = aPreviousState;
return aStyleNode;
#endif
}
@end
var CPImageCSSDictionaryKey = @"CPImageCSSDictionaryKey",
CPImageCSSBeforeDictionaryKey = @"CPImageCSSBeforeDictionaryKey",
CPImageCSSAfterDictionaryKey = @"CPImageCSSAfterDictionaryKey";
#pragma mark -
@implementation CPImage (CPCoding)
/*!
@@ -518,7 +724,10 @@ function CPAppKitImage(aFilename, aSize)
*/
- (id)initWithCoder:(CPCoder)aCoder
{
return [self initWithContentsOfFile:[aCoder decodeObjectForKey:@"CPFilename"] size:[aCoder decodeSizeForKey:@"CPSize"]];
if ([aCoder containsValueForKey:CPImageCSSDictionaryKey])
return [self initWithCSSDictionary:[aCoder decodeObjectForKey:CPImageCSSDictionaryKey] beforeDictionary:[aCoder decodeObjectForKey:CPImageCSSBeforeDictionaryKey] afterDictionary:[aCoder decodeObjectForKey:CPImageCSSAfterDictionaryKey] size:[aCoder decodeSizeForKey:@"CPSize"]];
else
return [self initWithContentsOfFile:[aCoder decodeObjectForKey:@"CPFilename"] size:[aCoder decodeSizeForKey:@"CPSize"]];
}
/*!
@@ -529,6 +738,14 @@ function CPAppKitImage(aFilename, aSize)
{
[aCoder encodeObject:_filename forKey:@"CPFilename"];
[aCoder encodeSize:_size forKey:@"CPSize"];
// CSS Styling
if ([self isCSSBased])
{
[aCoder encodeObject:_cssDictionary forKey:CPImageCSSDictionaryKey];
[aCoder encodeObject:_cssBeforeDictionary forKey:CPImageCSSBeforeDictionaryKey];
[aCoder encodeObject:_cssAfterDictionary forKey:CPImageCSSAfterDictionaryKey];
}
}
@end
+33 -6
View File
@@ -98,10 +98,32 @@ var CPImageViewEmptyPlaceholderImage = nil;
- (void)_createDOMImageElement
{
#if PLATFORM(DOM)
if (_DOMImageElement)
return;
var image = [self objectValue],
isCSSBasedImage = [image isCSSBased],
isIMGImageElement = _DOMImageElement && (_DOMImageElement.nodeName == "IMG");
_DOMImageElement = document.createElement("img");
// First, check if we need to destroy a current DOM image element. This is the case if :
// - we have one but not the right one (that is a DIV but needing an IMG, and vice versa)
if (_DOMImageElement)
{
if ((isIMGImageElement && isCSSBasedImage) || (!isIMGImageElement && !isCSSBasedImage))
{
// OK, destroy it
_DOMElement.removeChild(_DOMImageElement);
_DOMImageElement = nil;
// CSS styling cleaning
_cssStylePreviousState = @[];
_cssStyleNode = nil;
}
else
return;
}
_DOMImageElement = document.createElement(isCSSBasedImage ? "div" : "img");
_DOMImageElement.style.position = "absolute";
_DOMImageElement.style.left = "0px";
_DOMImageElement.style.top = "0px";
@@ -150,10 +172,15 @@ var CPImageViewEmptyPlaceholderImage = nil;
var newImage = [self objectValue];
#if PLATFORM(DOM)
if (!_DOMImageElement)
[self _createDOMImageElement];
[self _createDOMImageElement];
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
if ([newImage isCSSBased])
_cssStyleNode = [newImage applyCSSImageForView:self
onDOMElement:_DOMImageElement
styleNode:_cssStyleNode
previousState:@ref(_cssStylePreviousState)];
else
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
#endif
var size = [newImage size];
+1 -1
View File
@@ -857,7 +857,7 @@ var CPBindingOperationAnd = 0,
- (id)initWithName:(CPString)aName
{
if (self = [super init])
_name = aName
_name = aName;
return self;
}
+2 -2
View File
@@ -292,7 +292,7 @@ CPRatingLevelIndicatorStyle = 3;
[self setNeedsLayout];
}
- (void)setWarningValue:(double)warningValue;
- (void)setWarningValue:(double)warningValue
{
if (_warningValue === warningValue)
return;
@@ -301,7 +301,7 @@ CPRatingLevelIndicatorStyle = 3;
[self setNeedsLayout];
}
- (void)setCriticalValue:(double)criticalValue;
- (void)setCriticalValue:(double)criticalValue
{
if (_criticalValue === criticalValue)
return;
+2 -2
View File
@@ -505,7 +505,7 @@ CPOffState
if (_submenu)
{
[_submenu setSupermenu:_menu];
[_submenu setTitle:[self title]]
[_submenu setTitle:[self title]];
[self setTarget:_menu];
[self setAction:@selector(submenuAction:)];
@@ -843,7 +843,7 @@ CPControlKeyMask
[item setTarget:_target];
[item setAction:_action];
[item setEnabled:_isEnabled];
[item setHidden:_isHidden]
[item setHidden:_isHidden];
[item setTag:_tag];
[item setState:_state];
[item setImage:_image];
+2 -2
View File
@@ -1923,7 +1923,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
while (index !== CPNotFound)
{
[items addObject:[_outlineView itemAtRow:index]]
[items addObject:[_outlineView itemAtRow:index]];
index = [theIndexes indexGreaterThanIndex:index];
}
@@ -1957,7 +1957,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(CPInteger)theRow offset:(CGPoint)theOffset
{
if (theDropOperation === CPTableViewDropAbove)
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset]
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset];
return [_outlineView itemAtRow:theRow];
}
+4 -4
View File
@@ -463,13 +463,13 @@ var CPProgressIndicatorSpinningStyleColors = [];
var midX = CGRectGetMidX(rect),
midY = CGRectGetMidY(rect),
endAngle = Math.PI * 2 * (([self doubleValue] - [self minValue]) / ([self maxValue] - [self minValue])) - Math.PI / 2,
radius = MIN(rect.size.width / 2, rect.size.height / 2)
radius = MIN(rect.size.width / 2, rect.size.height / 2);
CGContextBeginPath(context);
CGContextSetLineWidth(context, borderSize);
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"]);
CGContextMoveToPoint(context, midX, midY);
CGContextAddArc(context, midX, midY, radius, 3 * Math.PI / 2, endAngle, YES)
CGContextAddArc(context, midX, midY, radius, 3 * Math.PI / 2, endAngle, YES);
CGContextAddLineToPoint(context, midX, midY);
CGContextClosePath(context);
CGContextFillPath(context);
@@ -478,7 +478,7 @@ var CPProgressIndicatorSpinningStyleColors = [];
else if ([self doubleValue] == [self maxValue])
{
CGContextBeginPath(context);
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"]);
CGContextAddEllipseInRect(context, rect);
CGContextClosePath(context);
CGContextFillPath(context);
@@ -209,8 +209,7 @@
- (void)_reconfigureSubviews
{
var ruleItems,
criteria,
var criteria,
repObject,
menuItem,
ruleView,
+1 -1
View File
@@ -1253,7 +1253,7 @@ Notifies the delegate when the scroll view has finished scrolling.
}
if (_timerScrollersHide)
[_timerScrollersHide invalidate]
[_timerScrollersHide invalidate];
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
}
+2 -2
View File
@@ -386,9 +386,9 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
*/
- (void)setRecentSearches:(CPArray)searches
{
var max = MIN([self maximumRecents], [searches count]),
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
var max = MIN([self maximumRecents], [searches count]);
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
_recentSearches = searches;
[self _autosaveRecentSearchList];
}
+8 -8
View File
@@ -67,7 +67,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
CPSegmentedControl _tabs;
_CPTabViewBox _box;
CPView _placeHolderView;
CPView _placeholderView @accessors;
CPTabViewItem _selectedTabViewItem;
@@ -106,7 +106,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
[self addSubview:_box];
[self addSubview:_tabs];
_placeHolderView = nil;
_placeholderView = nil;
}
- (CPArray)items
@@ -617,7 +617,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
- (CPBinder)binderForBinding:(CPString)aBinding
{
var cls = [[self class] _binderClassForBinding:aBinding]
var cls = [[self class] _binderClassForBinding:aBinding];
return [cls getBinding:aBinding forObject:self];
}
@@ -652,17 +652,17 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
- (void)_displayPlaceholder:(CPString)aPlaceholder
{
if (_placeHolderView == nil)
if (_placeholderView == nil)
{
_placeHolderView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
_placeholderView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
var textField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[textField setTag:1000];
[textField setTextColor:[CPColor whiteColor]];
[textField setFont:[CPFont boldFontWithName:@"Geneva" size:18 italic:YES]];
[_placeHolderView addSubview:textField];
[_placeholderView addSubview:textField];
}
var textField = [_placeHolderView viewWithTag:1000];
var textField = [_placeholderView viewWithTag:1000];
[textField setStringValue:aPlaceholder];
[textField sizeToFit];
@@ -672,7 +672,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
[textField setFrameOrigin:origin];
[self _displayItemView:_placeHolderView];
[self _displayItemView:_placeholderView];
}
#pragma mark -
+2 -2
View File
@@ -287,7 +287,7 @@ CPTableColumnUserResizingMask = 1 << 1;
if (width < [self minWidth])
[self setMinWidth:width];
else if (width > [self maxWidth])
[self setMaxWidth:width]
[self setMaxWidth:width];
if (_width !== width)
[self setWidth:width];
@@ -499,7 +499,7 @@ CPTableColumnUserResizingMask = 1 << 1;
*/
- (void)setHidden:(BOOL)shouldBeHidden
{
shouldBeHidden = !!shouldBeHidden
shouldBeHidden = !!shouldBeHidden;
if (_isHidden === shouldBeHidden)
return;
+2 -3
View File
@@ -3760,7 +3760,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
{
if (!dataViewsForRow)
{
dataViewsForRow = {}
dataViewsForRow = {};
_dataViewsForRows[row] = dataViewsForRow;
}
@@ -4907,7 +4907,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
row = _retargetedDropRow;
if (row === nil)
var row = [self _proposedRowAtPoint:location];
row = [self _proposedRowAtPoint:location];
return [self _sendDataSourceAcceptDrop:sender row:row dropOperation:operation];
}
@@ -6118,7 +6118,6 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
CPTableViewGridStyleMaskKey = @"CPTableViewGridStyleMaskKey",
CPTableViewUsesAlternatingBackgroundKey = @"CPTableViewUsesAlternatingBackgroundKey",
CPTableViewAlternatingRowColorsKey = @"CPTableViewAlternatingRowColorsKey",
CPTableViewHeaderViewKey = @"CPTableViewHeaderViewKey",
CPTableViewCornerViewKey = @"CPTableViewCornerViewKey",
CPTableViewAutosaveNameKey = @"CPTableViewAutosaveNameKey",
CPTableViewArchivedReusableViewsKey = @"CPTableViewArchivedReusableViewsKey";
+4 -4
View File
@@ -331,7 +331,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[CPTextFieldInputOwner keyUp:cappEvent];
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
};
CPTextFieldDOMPasswordInputElement.oninput = CPTextFieldInputFunction;
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurHandler;
@@ -1040,7 +1040,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
CPTextFieldCachedSelectStartFunction = nil
CPTextFieldCachedSelectStartFunction = nil;
CPTextFieldCachedDragFunction = nil;
}
@@ -1243,7 +1243,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return;
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBeginEditing_)
[_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]]
[_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]];
[super textDidBeginEditing:note];
}
@@ -1790,7 +1790,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
_implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_
_implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_;
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_;
+1 -1
View File
@@ -412,7 +412,7 @@ var _availableTraits= [@"Normal", @"Italic", @"Bold", @"Bold Italic"],
return [_availableFonts count];
if (aBrowser === _traitBrowser)
return [_availableTraits count]
return [_availableTraits count];
return [_availableSizes count]
}
+1 -1
View File
@@ -1179,7 +1179,7 @@ var _objectsInRange = function(aList, aRange)
for (var i = 0; i < count; i++)
{
_glyphsFrames[i] = CGRectMake(origin.x, origin.y, someAdvancements[i].width, height);
_glyphsFrames[i]._descent = someAdvancements[i].descent
_glyphsFrames[i]._descent = someAdvancements[i].descent;
_glyphsOffsets[i] = height - someAdvancements[i].height;
origin.x += someAdvancements[i].width;
}
+1 -1
View File
@@ -80,7 +80,7 @@ CPLineMovesUp = 4;
@implementation CPTextContainer : CPObject
{
float _lineFragmentPadding @accessors(property=lineFragmentPadding);
CGSize _size @accessors(property=containerSize)
CGSize _size @accessors(property=containerSize);
CPLayoutManager _layoutManager @accessors(property=layoutManager);
CPTextView _textView @accessors(property=textView);
BOOL _inResizing;
+10 -8
View File
@@ -95,7 +95,7 @@ CPSelectByWord = 1;
CPSelectByParagraph = 2;
var kDelegateRespondsTo_textShouldBeginEditing = 1 << 0,
kDelegateRespondsTo_textShouldEndEditing = 1 << 1
kDelegateRespondsTo_textShouldEndEditing = 1 << 1,
kDelegateRespondsTo_textView_doCommandBySelector = 1 << 2,
kDelegateRespondsTo_textView_willChangeSelectionFromCharacterRange_toCharacterRange = 1 << 3,
kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString = 1 << 4,
@@ -241,7 +241,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
_selectedTextAttributes = [CPMutableDictionary new];
_caret = [[_CPCaret alloc] initWithTextView:self];
[_caret setRect:CGRectMake(0, 0, 1, 11)]
[_caret setRect:CGRectMake(0, 0, 1, 11)];
var pboardTypes = [CPStringPboardType, CPColorDragType];
@@ -1586,7 +1586,7 @@ Sets the selection to a range of characters in response to user action.
- (void)moveWordLeft:(id)sender
{
if ([self isSelectable])
[self _moveSelectionIntoDirection:-1 granularity:CPSelectByWord]
[self _moveSelectionIntoDirection:-1 granularity:CPSelectByWord];
}
- (void)moveRight:(id)sender
@@ -1614,6 +1614,7 @@ Sets the selection to a range of characters in response to user action.
[self didChangeText];
[_layoutManager _validateLayoutAndGlyphs];
[self sizeToFit];
[self scrollRangeToVisible:CPMakeRange(changedRange.location, 0)];
_stickyXLocation = _caret._rect.origin.x;
}
@@ -2249,7 +2250,8 @@ Sets the selection to a range of characters in response to user action.
[[self class] _binderClassForBinding:CPValueBinding],
theBinding = [binderClass getBinding:CPAttributedStringBinding forObject:self] || [binderClass getBinding:CPValueBinding forObject:self];
[theBinding reverseSetValueFor:@"objectValue"];
if (theBinding && [self isEditable])
[theBinding reverseSetValueFor:@"objectValue"];
}
@end
@@ -2390,7 +2392,7 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey",
{
DOMElement _selectionBoxDOM;
CGRect _rect;
CPColor _color
CPColor _color;
CPTextView _textView;
}
@@ -2540,7 +2542,7 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey",
var rect = [_textView._layoutManager boundingRectForGlyphRange:CPMakeRange(aLoc, 1) inTextContainer:_textView._textContainer];
if (aLoc >= [_textView._layoutManager numberOfCharacters])
rect.origin.x = CGRectGetMaxX(rect)
rect.origin.x = CGRectGetMaxX(rect);
[self setRect:rect];
}
@@ -2749,7 +2751,7 @@ var _CPCopyPlaceholder = '-';
}, 20);
return false;
}
};
if (CPBrowserIsEngine(CPGeckoBrowserEngine))
{
@@ -2765,7 +2767,7 @@ var _CPCopyPlaceholder = '-';
e.clipboardData.setData('text/plain', stringForPasting);
return false;
}
};
_CPNativeInputField.oncut = function(e)
{
+3 -3
View File
@@ -173,7 +173,7 @@ var CPSystemTypesetterFactory,
rect = CGRectMake(lineOrigin.x, lineOrigin.y, _lineWidth, _lineHeight),
containerSize = aContainer._size;
[_layoutManager _appendNewLineFragmentInTextContainer:_currentTextContainer forGlyphRange:lineRange]
[_layoutManager _appendNewLineFragmentInTextContainer:_currentTextContainer forGlyphRange:lineRange];
var fragment = [_layoutManager._lineFragments lastObject];
fragment._isLast = !sameLine;
@@ -293,8 +293,8 @@ var CPSystemTypesetterFactory,
if (!currentFont)
currentFont = [_textStorage font] || [CPFont systemFontOfSize:12.0];
ascent = [currentFont ascender]
descent = [currentFont descender]
ascent = [currentFont ascender];
descent = [currentFont descender];
leading = (ascent - descent) * 0.2; // FAKE leading
currentFontLineHeight = ascent - descent + leading;
+3 -3
View File
@@ -657,7 +657,7 @@ var kRgsymRtf = {
}
- (CPAttributedString)parseRTF:(CPString)rtf
{
rtf = rtf.replace(/\\\n/g, "\\par\n")
rtf = rtf.replace(/\\\n/g, "\\par\n");
if (rtf.length == 0)
return '';
@@ -718,7 +718,7 @@ var kRgsymRtf = {
_freename = "";
}
[self _flushCurrentRun]
[self _flushCurrentRun];
break;
case "\\":
@@ -751,7 +751,7 @@ var kRgsymRtf = {
if (hexTable && hexTable[hex.toUpperCase()] !== undefined)
temp = parseInt(hexTable[hex.toUpperCase()], 16);
[self _appendPlainString: String.fromCharCode(temp)]
[self _appendPlainString: String.fromCharCode(temp)];
hex = '';
}
}
+69 -1
View File
@@ -24,9 +24,12 @@
@import <Foundation/CPMutableArray.j>
@import <Foundation/CPString.j>
@import <Foundation/CPKeyedUnarchiver.j>
@import <Foundation/CPBundle.j>
@class CPView
@class _CPThemeAttribute
@class CPImage
@class CPColor
var CPThemesByName = { },
CPThemeDefaultTheme = nil,
@@ -313,6 +316,71 @@ var CPThemeNameKey = @"CPThemeNameKey",
@end
#pragma mark -
#pragma mark CSS Theming
// The code below adds support for CSS theming with 100% compatibility with current theming system.
// The idea is to extend CPColor and CPImage with CSS components and adapt low level UI components to
// support this new kind of CPColor/CPImage. See CPImageView, CPView and _CPImageAndTextView.
//
// To be considered and treated as CSS based, a theme must set to YES the attribute "css-based" for CPView
// in the theDescriptor (default value is NO), like in the example below :
//
// + (CPView)themedView
// {
// var view = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
//
// [self registerThemeValues:[[@"css-based", YES]] forView:view];
//
// return view;
// }
//
// You can use the method -(BOOL)isCSSBased on a theme to determine how to cope with it in your own code.
//
// The method -(void)setCSSResourcesPath is meant to be used only by CPThemeBlend during theme loading in order to
// replace the special path "%%" in CSS components (like in url(%%packed.png) ) with the path to the theme blend resources folder.
@implementation CPTheme (CSSTheming)
- (void)setCSSResourcesPath:(CPString)pathToResources
{
[_attributes enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
[anObject enumerateKeysAndObjectsUsingBlock:function(aKey2, anObject2, stop2)
{
// anObject2 is now a _CPThemeAttribute
[[anObject2 values] enumerateKeysAndObjectsUsingBlock:function(aKey3, anObject3, stop3)
{
if (anObject3.isa && ([anObject3 isKindOfClass:CPImage] || [anObject3 isKindOfClass:CPColor]) && [anObject3 cssDictionary])
{
// We have a CSS defined image or color
[self _fixPathInCSSDictionary:[anObject3 cssDictionary] withPathToResources:pathToResources];
[self _fixPathInCSSDictionary:[anObject3 cssBeforeDictionary] withPathToResources:pathToResources];
[self _fixPathInCSSDictionary:[anObject3 cssAfterDictionary] withPathToResources:pathToResources];
}
}];
}];
}];
}
- (void)_fixPathInCSSDictionary:(CPDictionary)aDictionary withPathToResources:(CPString)pathToResources
{
[aDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
[aDictionary setObject:[anObject stringByReplacingOccurrencesOfString:@"%%" withString:pathToResources] forKey:aKey];
}];
}
- (BOOL)isCSSBased
{
return !![self valueForAttributeWithName:@"css-based" forClass:[CPView class]];
}
@end
#pragma mark -
/*!
* ThemeStates are immutable objects representing a particular ThemeState. Applications should never be creating
* ThemeStates directly but should instead use the CPThemeState function.
@@ -769,7 +837,7 @@ var ParentAttributeForCoder = nil;
if ([aCoder containsValueForKey:@"state"])
state = [aCoder decodeObjectForKey:@"state"];
else
state = CPThemeStateNormalString
state = CPThemeStateNormalString;
[_values setObject:[aCoder decodeObjectForKey:"value"] forKey:state];
}
+11
View File
@@ -95,6 +95,17 @@
[unarchiver finishDecoding];
}
// CSS Theming
for (var i = 0, nb = [_themes count], allThemes = [self themeNames], aThemeName, aTheme; i < nb; i++)
{
aThemeName = allThemes[i];
aTheme = [CPTheme themeNamed:aThemeName];
if ([aTheme isCSSBased])
[aTheme setCSSResourcesPath:[aBundle resourcePath]];
}
[_loadDelegate blendDidFinishLoading:self];
}
+2 -2
View File
@@ -549,7 +549,7 @@ CPTokenFieldDeleteButtonType = 1;
CPTokenFieldCachedSelectStartFunction = nil;
CPTokenFieldCachedDragFunction = nil;
document.body.ondrag = CPTokenFieldCachedDragFunction
document.body.ondrag = CPTokenFieldCachedDragFunction;
document.body.onselectstart = CPTokenFieldCachedSelectStartFunction
}
@@ -1247,7 +1247,7 @@ CPTokenFieldDeleteButtonType = 1;
var scrollToToken = _shouldScrollTo;
if (scrollToToken === CPScrollDestinationLeft)
scrollToToken = tokens[_selectedRange.location]
scrollToToken = tokens[_selectedRange.location];
else if (scrollToToken === CPScrollDestinationRight)
scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)];
[self _scrollTokenViewToVisible:scrollToToken];
+2 -2
View File
@@ -153,7 +153,7 @@ var CPToolbarsByIdentifier = nil,
if (!toolbarsSharingIdentifier)
{
toolbarsSharingIdentifier = []
toolbarsSharingIdentifier = [];
[CPToolbarsByIdentifier setObject:toolbarsSharingIdentifier forKey:identifier];
}
@@ -588,7 +588,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
[aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
[aCoder encodeBool:_allowsUserCustomization forKey:CPToolbarAllowsUserCustomizationKey];
[aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
[aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey]
[aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey];
[aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
[aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
+54 -5
View File
@@ -129,7 +129,8 @@ var DOMElementPrototype = nil,
BackgroundVerticalThreePartImage = 1,
BackgroundHorizontalThreePartImage = 2,
BackgroundNinePartImage = 3,
BackgroundTransparentColor = 4;
BackgroundTransparentColor = 4,
BackgroundCSSStyling = 5;
#endif
var CPViewFlags = { },
@@ -195,6 +196,10 @@ var CPViewHighDPIDrawingEnabled = YES;
CPArray _DOMImageSizes;
unsigned _backgroundType;
// CSS styling
CPArray _cssStylePreviousState;
DOMElement _cssStyleNode;
#endif
CGRect _dirtyRect;
@@ -320,6 +325,18 @@ var CPViewHighDPIDrawingEnabled = YES;
return nil;
}
+ (CPString)defaultThemeClass
{
return @"view";
}
+ (CPDictionary)themeAttributes
{
return @{
@"css-based": NO
};
}
- (void)_setupViewFlags
{
var theClass = [self class],
@@ -399,6 +416,8 @@ var CPViewHighDPIDrawingEnabled = YES;
_DOMImageParts = [];
_DOMImageSizes = [];
_cssStylePreviousState = @[];
#endif
_animator = nil;
@@ -449,7 +468,7 @@ var CPViewHighDPIDrawingEnabled = YES;
return;
if (!_toolTipFunctionIn)
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; }
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; };
if (!_toolTipFunctionOut)
_toolTipFunctionOut = function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
@@ -1954,15 +1973,25 @@ var CPViewHighDPIDrawingEnabled = YES;
_backgroundColor = aColor;
#if PLATFORM(DOM)
if (_backgroundType === BackgroundCSSStyling)
[_backgroundColor restorePreviousCSSState:@ref(_cssStylePreviousState) forDOMElement:_DOMElement];
var patternImage = [_backgroundColor patternImage],
colorExists = _backgroundColor && ([_backgroundColor patternImage] || [_backgroundColor alphaComponent] > 0.0),
colorHasAlpha = colorExists && [_backgroundColor alphaComponent] < 1.0,
supportsRGBA = CPFeatureIsCompatible(CPCSSRGBAFeature),
colorNeedsDOMElement = colorHasAlpha && !supportsRGBA,
amount = 0,
slices;
slices,
// For CSS theming
isCSSBasedColor = [_backgroundColor isCSSBased];
if ([patternImage isThreePartImage])
if (isCSSBasedColor)
{
_backgroundType = BackgroundCSSStyling;
amount = -_DOMImageParts.length;
}
else if ([patternImage isThreePartImage])
{
_backgroundType = [patternImage isVertical] ? BackgroundVerticalThreePartImage : BackgroundHorizontalThreePartImage;
amount = 3;
@@ -2025,7 +2054,14 @@ var CPViewHighDPIDrawingEnabled = YES;
_DOMElement.removeChild(_DOMImageParts.pop());
}
if (_backgroundType === BackgroundTrivialColor || _backgroundType === BackgroundTransparentColor)
if (_backgroundType === BackgroundCSSStyling)
{
_cssStyleNode = [_backgroundColor applyCSSColorForView:self
onDOMElement:_DOMElement
styleNode:_cssStyleNode
previousState:@ref(_cssStylePreviousState)];
}
else if (_backgroundType === BackgroundTrivialColor || _backgroundType === BackgroundTransparentColor)
{
var colorCSS = colorExists ? [_backgroundColor cssString] : "";
@@ -3434,6 +3470,17 @@ setBoundsOrigin:
@end
@implementation CPView (CSSTheming)
- (void)setDOMClassName:(CPString)aClassName
{
#if PLATFORM(DOM)
_DOMElement.className = aClassName;
#endif
}
@end
@implementation CPView (Appearance)
@@ -3749,6 +3796,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
// DOM SETUP
#if PLATFORM(DOM)
_cssStylePreviousState = @[];
_DOMImageParts = [];
_DOMImageSizes = [];
+22 -5
View File
@@ -1903,7 +1903,7 @@ CPTexturedBackgroundWindowMask
// Make sure the browser doesn't try to do its own tab handling.
// This is important or the browser might blur the shared text field or token field input field,
// even that we just moved it to a new first responder.
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
#endif
return;
}
@@ -1917,7 +1917,7 @@ CPTexturedBackgroundWindowMask
// Make sure the browser doesn't try to do its own tab handling.
// This is important or the browser might blur the shared text field or token field input field,
// even that we just moved it to a new first responder.
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
#endif
}
@@ -1983,7 +1983,7 @@ CPTexturedBackgroundWindowMask
var theWindow = [anEvent window],
selector = type == CPRightMouseDown ? @selector(rightMouseDown:) : @selector(mouseDown:);
if ([theWindow isKeyWindow] || ([theWindow becomesKeyOnlyIfNeeded] && ![_leftMouseDownView needsPanelToBecomeKey]))
if (([theWindow _isFrontmostWindow] && [theWindow isKeyWindow]) || ([theWindow becomesKeyOnlyIfNeeded] && ![_leftMouseDownView needsPanelToBecomeKey]))
return [_leftMouseDownView performSelector:selector withObject:anEvent];
else
{
@@ -2009,13 +2009,13 @@ CPTexturedBackgroundWindowMask
if (type == CPRightMouseDragged)
{
selector = @selector(rightMouseDragged:)
selector = @selector(rightMouseDragged:);
if (![_leftMouseDownView respondsToSelector:selector])
selector = nil;
}
if (!selector)
selector = @selector(mouseDragged:)
selector = @selector(mouseDragged:);
return [_leftMouseDownView performSelector:selector withObject:anEvent];
@@ -2114,6 +2114,23 @@ CPTexturedBackgroundWindowMask
return [CPApp keyWindow] == self;
}
/* @ignore */
- (BOOL)_isFrontmostWindow
{
if ([self isFullBridge])
return YES;
var orderedWindows = [CPApp orderedWindows];
if ([orderedWindows count] == 0)
return YES;
if ([orderedWindows objectAtIndex:0] === self)
return YES;
return NO;
}
/*!
Makes the window the key window and brings it to the front of the screen list.
@param aSender the object requesting this
+1 -1
View File
@@ -183,7 +183,7 @@
if (_styleMask & CPClosableWindowMask)
{
[_closeButton setFrameOrigin:[self valueForThemeAttribute:@"close-image-origin"]];
[_closeButton setFrameSize:[self valueForThemeAttribute:@"close-image-size"]]
[_closeButton setFrameSize:[self valueForThemeAttribute:@"close-image-size"]];
[_closeButton setImage:[self valueForThemeAttribute:@"close-image"]];
[_closeButton setAlternateImage:[self valueForThemeAttribute:@"close-active-image"]];
}
+1 -1
View File
@@ -364,7 +364,7 @@
{
[viewControllerView removeFromSuperview];
[viewControllerView setFrame:[contentView frame]];
[viewControllerView setAutoresizingMask:[contentView autoresizingMask]]
[viewControllerView setAutoresizingMask:[contentView autoresizingMask]];
[[self window] setContentView:viewControllerView];
}
else
+1 -1
View File
@@ -214,7 +214,7 @@ var transformSizeToHeight = function(start, current)
var CSSStringFromCGAffineTransform = function(anAffineTransform)
{
return "matrix(" + anAffineTransform.a + ", " + anAffineTransform.b + ", " + anAffineTransform.c + ", " + anAffineTransform.d + ", " + anAffineTransform.tx + (CPBrowserIsEngine(CPGeckoBrowserEngine) ? "px, " : ", ") + anAffineTransform.ty + (CPBrowserIsEngine(CPGeckoBrowserEngine) ? "px)" : ")");
return [CPString stringWithFormat:@"matrix(%d,%d,%d,%d,%d,%d)", anAffineTransform.a, anAffineTransform.b, anAffineTransform.c, anAffineTransform.d, anAffineTransform.tx, anAffineTransform.ty];
};
var frameOriginToCSSTransformMatrix = function(start, current)
+2 -2
View File
@@ -557,14 +557,14 @@ CGContextConcatCTM = function(aContext, anAffineTransform)
b = VT.b;
c = VT.c;
d = VT.d;
scale_rotate(a, b, c, d)
scale_rotate(a, b, c, d);
S.a *= sx;
S.d *= sy;
a = U.a;
b = U.b;
c = U.c;
d = U.d;
rotate_scale(a, b, c, d)
rotate_scale(a, b, c, d);
sx = S.a * sx;
sy = S.d * sy;
}
+1 -1
View File
@@ -242,7 +242,7 @@ function CGContextDrawPath(aContext, aMode)
vml.push("\">");
if (gState.gradient)
vml.push(gState.gradient)
vml.push(gState.gradient);
else if (fill)
{
+1 -4
View File
@@ -132,9 +132,6 @@ function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle,
}
else
{
var arcStartX = x + aRadius * COS(aStartAngle),
arcStartY = y + aRadius * SIN(aStartAngle);
aPath.start = CGPointMake(arcStartX, arcStartY);
}
@@ -274,7 +271,7 @@ function CGPathAddQuadCurveToPoint(aPath, aTransform, cpx, cpy, x, y)
end = CGPointApplyAffineTransform(end, aTransform);
}
aPath.elements[aPath.count++] = { type:kCGPathElementAddQuadCurveToPoint, cpx:cp.x, cpy:cp.y, x:end.x, y:end.y }
aPath.elements[aPath.count++] = { type:kCGPathElementAddQuadCurveToPoint, cpx:cp.x, cpy:cp.y, x:end.x, y:end.y };
aPath.current = end;
}
+2 -2
View File
@@ -469,7 +469,7 @@ Return true if the event may be a copy and paste event, but the target is not an
// By default we'll stop the native handling of the event since we're handling it ourselves. However, we need to
// stop it before we send the event so that the event can overrule our choice. CPTextField for instance wants the
// default handling when focused (which is to insert into the field).
[platformWindow _propagateCurrentDOMEvent:NO]
[platformWindow _propagateCurrentDOMEvent:NO];
[CPApp sendEvent:anEvent];
@@ -492,7 +492,7 @@ Return true if the event may be a copy and paste event, but the target is not an
SUPPRESS_CAPPUCCINO_CUT_FOR_EVENT(anEvent);
[platformWindow _propagateCurrentDOMEvent:NO]
[platformWindow _propagateCurrentDOMEvent:NO];
// Let the app react through copy: and cut: actions.
[CPApp sendEvent:anEvent];
+50 -25
View File
@@ -205,6 +205,9 @@ var resizeTimer = nil;
var PreventScroll = true;
var blurTimer = nil;
var touchStartingPointX,
touchStartingPointY;
_CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotification";
@@ -666,7 +669,8 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
}
else if (type === "dragend")
{
var dropEffect = aDOMEvent.dataTransfer.dropEffect;
var dropEffect = aDOMEvent.dataTransfer.dropEffect,
dragOperation;
if (dropEffect === "move")
dragOperation = CPDragOperationMove;
@@ -944,8 +948,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
if (!theWindow)
return;
var windowNumber = [theWindow windowNumber];
windowNumber = [theWindow windowNumber];
location = [theWindow convertBridgeToBase:location];
var event = [CPEvent mouseEventWithType:CPScrollWheel location:location modifierFlags:modifierFlags
@@ -1152,10 +1155,26 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
- (void)touchEvent:(DOMEvent)aDOMEvent
{
var newEvent = {},
touch = aDOMEvent.touches.length ? aDOMEvent.touches[0] : aDOMEvent.changedTouches[0];
newEvent.timestamp = [CPEvent currentTimestamp];
newEvent.target = aDOMEvent.target;
newEvent.shiftKey = newEvent.ctrlKey = newEvent.altKey = newEvent.metaKey = false;
newEvent.clientX = touch.clientX;
/*
Normally the document can't scroll in Cappuccino: our body element has top:0 and bottom:0 with absolute positioning. So it should always be exactly the height of the viewport. The below handles a special case. iOS scrolls the document when the virtual keyboard is present and it needs to move a text input upwards visually to avoid covering the input with the keyboard. For most purposes we can ignore this, except here. In theory I think we could always apply this (scrollTop should always be 0 on every other device and situation) but let's be defensive and only apply it for touch events to minimise the risk of surprises.
*/
newEvent.clientY = _DOMWindow.document.body.scrollTop + touch.clientY;
newEvent.preventDefault = function() { if (aDOMEvent.preventDefault) aDOMEvent.preventDefault() };
newEvent.stopPropagation = function() { if (aDOMEvent.stopPropagation) aDOMEvent.stopPropagation() };
// single finger event-> simulate a simple mouse-click
if (aDOMEvent.touches && (aDOMEvent.touches.length == 1 || (aDOMEvent.touches.length == 0 && aDOMEvent.changedTouches.length == 1)))
{
var newEvent = {};
switch (aDOMEvent.type)
{
case CPDOMEventTouchStart: newEvent.type = CPDOMEventMouseDown;
@@ -1168,36 +1187,42 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
break;
}
var touch = aDOMEvent.touches.length ? aDOMEvent.touches[0] : aDOMEvent.changedTouches[0];
newEvent.clientX = touch.clientX;
/*
Normally the document can't scroll in Cappuccino: our body element has top:0 and bottom:0 with absolute positioning. So it should always be exactly the height of the viewport. The below handles a special case. iOS scrolls the document when the virtual keyboard is present and it needs to move a text input upwards visually to avoid covering the input with the keyboard. For most purposes we can ignore this, except here. In theory I think we could always apply this (scrollTop should always be 0 on every other device and situation) but let's be defensive and only apply it for touch events to minimise the risk of surprises.
*/
newEvent.clientY = _DOMWindow.document.body.scrollTop + touch.clientY;
newEvent.timestamp = [CPEvent currentTimestamp];
newEvent.target = aDOMEvent.target;
newEvent.shiftKey = newEvent.ctrlKey = newEvent.altKey = newEvent.metaKey = false;
newEvent.preventDefault = function() { if (aDOMEvent.preventDefault) aDOMEvent.preventDefault() };
newEvent.stopPropagation = function() { if (aDOMEvent.stopPropagation) aDOMEvent.stopPropagation() };
[self mouseEvent:newEvent];
return;
}
else
{
// two fingers->simulate scrolling events
if (aDOMEvent.touches && aDOMEvent.touches.length == 2)
{
switch (aDOMEvent.type)
{
case CPDOMEventTouchStart:
touchStartingPointX = touch.pageX;
touchStartingPointY = touch.pageY;
break;
case CPDOMEventTouchMove:
newEvent._hasPreciseScrollingDeltas = YES;
newEvent.deltaX = touchStartingPointX - touch.pageX;
newEvent.deltaY = touchStartingPointY - touch.pageY;
newEvent.type = CPDOMEventScrollWheel;
[self scrollEvent:newEvent];
touchStartingPointX = touch.pageX;
touchStartingPointY = touch.pageY;
return;
}
}
// handle other touch cases specifically
if (aDOMEvent.preventDefault)
aDOMEvent.preventDefault();
if (aDOMEvent.stopPropagation)
aDOMEvent.stopPropagation();
}
// handle touch cases specifically
}
- (void)mouseEvent:(DOMEvent)aDOMEvent
@@ -1422,7 +1447,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
var insertionIndex = 0;
if (middle !== undefined)
insertionIndex = _windowLevels[middle] > aLevel ? middle : middle + 1
insertionIndex = _windowLevels[middle] > aLevel ? middle : middle + 1;
[_windowLevels insertObject:aLevel atIndex:insertionIndex];
layer._DOMElement.style.zIndex = aLevel + 1; // adding one avoids negative zIndices. These have been causing issues in Chrome
@@ -1821,7 +1846,7 @@ var _CPEventFromNativeMouseEvent = function(aNativeEvent, anEventType, aPoint, m
var CLICK_SPACE_DELTA = 5.0,
CLICK_TIME_DELTA = (typeof document != "undefined" && document.addEventListener) ? 0.55 : 1.0;
var CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation)
CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation)
{
if (!aComparisonEvent)
return 1;
+104 -70
View File
@@ -331,9 +331,9 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
{
var textStyle = _DOMTextElement.style;
textFrame.origin.y = parseInt(textStyle.top.substr(0, textStyle.top.length - 2), 10),
textFrame.origin.x = parseInt(textStyle.left.substr(0, textStyle.left.length - 2), 10),
textFrame.size.width = parseInt(textStyle.width.substr(0, textStyle.width.length - 2), 10),
textFrame.origin.y = parseInt(textStyle.top.substr(0, textStyle.top.length - 2), 10);
textFrame.origin.x = parseInt(textStyle.left.substr(0, textStyle.left.length - 2), 10);
textFrame.size.width = parseInt(textStyle.width.substr(0, textStyle.width.length - 2), 10);
textFrame.size.height = parseInt(textStyle.height.substr(0, textStyle.height.length - 2), 10);
textFrame.size.width += _textShadowOffset.width;
@@ -437,55 +437,67 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
var textStyle = hasDOMTextElement ? _DOMTextElement.style : nil;
// Create or destroy the DOM Text Shadow element as necessary.
// If _textShadowColor's alphaComponent is 0, don't bother drawing anything (issue #1412).
// This improves performance as we get rid of an invisible element, and makes IE <9.0 capable
// of correctly 'rendering' shadows with [CPColor clearColor].
var needsDOMTextShadowElement = hasDOMTextElement && [_textShadowColor alphaComponent] > 0.0,
hasDOMTextShadowElement = !!_DOMTextShadowElement;
if (needsDOMTextShadowElement !== hasDOMTextShadowElement)
// If theme is CSS based and if shadow color is a CSS dictionary, we don't need a separate DOM element,
// we simply put shadow styling on the regular text element
if (hasDOMTextElement && [[self actualTheme] isCSSBased] && [_textShadowColor cssDictionary])
{
if (hasDOMTextShadowElement)
[[_textShadowColor cssDictionary] enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
{
_DOMTextElement.style[aKey] = anObject;
}];
}
else
{
// Create or destroy the DOM Text Shadow element as necessary.
// If _textShadowColor's alphaComponent is 0, don't bother drawing anything (issue #1412).
// This improves performance as we get rid of an invisible element, and makes IE <9.0 capable
// of correctly 'rendering' shadows with [CPColor clearColor].
var needsDOMTextShadowElement = hasDOMTextElement && [_textShadowColor alphaComponent] > 0.0,
hasDOMTextShadowElement = !!_DOMTextShadowElement;
if (needsDOMTextShadowElement !== hasDOMTextShadowElement)
{
_DOMElement.removeChild(_DOMTextShadowElement);
_DOMTextShadowElement = nil;
hasDOMTextShadowElement = NO;
}
else
{
_DOMTextShadowElement = document.createElement("div");
var shadowStyle = _DOMTextShadowElement.style,
font = (_font || [CPFont systemFontOfSize:CPFontCurrentSystemSize]);
shadowStyle.font = [font cssString];
shadowStyle.position = "absolute";
shadowStyle.whiteSpace = textStyle.whiteSpace;
shadowStyle.wordWrap = textStyle.wordWrap;
shadowStyle.color = [_textShadowColor cssString];
shadowStyle.lineHeight = [font defaultLineHeightForFont] + "px";
shadowStyle.zIndex = 150;
shadowStyle.textOverflow = textStyle.textOverflow;
if (document.attachEvent)
if (hasDOMTextShadowElement)
{
shadowStyle.overflow = textStyle.overflow;
_DOMElement.removeChild(_DOMTextShadowElement);
_DOMTextShadowElement = nil;
hasDOMTextShadowElement = NO;
}
else
{
shadowStyle.overflowX = textStyle.overflowX;
shadowStyle.overflowY = textStyle.overflowY;
_DOMTextShadowElement = document.createElement("div");
var shadowStyle = _DOMTextShadowElement.style,
font = (_font || [CPFont systemFontOfSize:CPFontCurrentSystemSize]);
shadowStyle.font = [font cssString];
shadowStyle.position = "absolute";
shadowStyle.whiteSpace = textStyle.whiteSpace;
shadowStyle.wordWrap = textStyle.wordWrap;
shadowStyle.color = [_textShadowColor cssString];
shadowStyle.lineHeight = [font defaultLineHeightForFont] + "px";
shadowStyle.zIndex = 150;
shadowStyle.textOverflow = textStyle.textOverflow;
if (document.attachEvent)
{
shadowStyle.overflow = textStyle.overflow;
}
else
{
shadowStyle.overflowX = textStyle.overflowX;
shadowStyle.overflowY = textStyle.overflowY;
}
_DOMElement.appendChild(_DOMTextShadowElement);
hasDOMTextShadowElement = YES;
_flags |= _CPImageAndTextViewTextChangedFlag; //sigh...
}
_DOMElement.appendChild(_DOMTextShadowElement);
hasDOMTextShadowElement = YES;
_flags |= _CPImageAndTextViewTextChangedFlag; //sigh...
}
}
@@ -591,41 +603,55 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
}
var needsDOMImageElement = _image !== nil && _imagePosition !== CPNoImage,
hasDOMImageElement = !!_DOMImageElement;
hasDOMImageElement = !!_DOMImageElement,
// For CSS theming
isCSSBasedImage = [_image isCSSBased],
isIMGImageElement = hasDOMImageElement && (_DOMImageElement.nodeName == "IMG");
// Create or destroy DOM Image element
if (needsDOMImageElement !== hasDOMImageElement)
// First, check if we need to destroy a current DOM image element. This is the case if :
// - we have one but don't need it anymore
// - we have one but not the right one (that is a DIV but needing an IMG, and vice versa)
if (hasDOMImageElement)
{
if (hasDOMImageElement)
if (!needsDOMImageElement || (isIMGImageElement && isCSSBasedImage) || (!isIMGImageElement && !isCSSBasedImage))
{
// OK, destroy it
_DOMElement.removeChild(_DOMImageElement);
_DOMImageElement = nil;
hasDOMImageElement = NO;
}
else
// CSS styling cleaning
_cssStylePreviousState = @[];
_cssStyleNode = nil;
}
}
// Now, if we need a DOM image element and if we don't have one, create a new one
if (needsDOMImageElement && !hasDOMImageElement)
{
_DOMImageElement = document.createElement(isCSSBasedImage ? "div" : "img");
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement = document.createElement("img");
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
var imageStyle = _DOMImageElement.style;
imageStyle.top = "0px";
imageStyle.left = "0px";
imageStyle.position = "absolute";
imageStyle.zIndex = 100;
_DOMElement.appendChild(_DOMImageElement);
hasDOMImageElement = YES;
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
var imageStyle = _DOMImageElement.style;
imageStyle.top = "0px";
imageStyle.left = "0px";
imageStyle.position = "absolute";
imageStyle.zIndex = 100;
_DOMElement.appendChild(_DOMImageElement);
hasDOMImageElement = YES;
}
var size = [self bounds].size,
@@ -637,7 +663,15 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
var imageStyle = _DOMImageElement.style;
if (_flags & _CPImageAndTextViewImageChangedFlag)
_DOMImageElement.src = [_image filename];
{
if (isCSSBasedImage)
_cssStyleNode = [_image applyCSSImageForView:self
onDOMElement:_DOMImageElement
styleNode:_cssStyleNode
previousState:@ref(_cssStylePreviousState)];
else
_DOMImageElement.src = [_image filename];
}
var centerX = size.width / 2.0,
centerY = size.height / 2.0,
+27 -1
View File
@@ -20,6 +20,7 @@
*/
@import <Foundation/Foundation.j>
@import "CPResponder.j"
@import "CPTheme.j"
@@ -477,4 +478,29 @@ var NULL_THEME = {};
}
}
@end
#pragma mark -
#pragma mark CSS styling additions
- (CPTheme)actualTheme
{
return _theme ? _theme : [CPTheme defaultTheme];
}
// These methods implement inherited theme attributes thru class hierarchy.
- (id)actualValueForThemeAttribute:(CPString)aName
{
return [self actualValueForThemeAttribute:aName inState:CPThemeStateNormal];
}
- (id)actualValueForThemeAttribute:(CPString)aName inState:(ThemeState)aState
{
for (var currentClass = [self class], foundAttribute = nil, currentTheme = [self actualTheme]; (currentClass && (currentClass !== CPResponder) && !foundAttribute); currentClass = [currentClass superclass])
foundAttribute = [currentTheme attributeWithName:aName forClass:currentClass];
return (foundAttribute ? [foundAttribute valueForState:aState] : nil);
}
@end
+1 -1
View File
@@ -574,7 +574,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
_isOpening = NO;
[_delegate _popoverWindowDidShow];
}
};
#if PLATFORM(DOM)
_DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), _transitionCompleteFunction, YES);
+1 -1
View File
@@ -181,7 +181,7 @@ var _CPToolTipHeight = 24.0,
textFrameSize.height += 4;
_content = [CPTextField labelWithTitle:aString];
[_content setFont:[CPFont systemFontOfSize:_CPToolTipFontSize]]
[_content setFont:[CPFont systemFontOfSize:_CPToolTipFontSize]];
[_content setLineBreakMode:CPLineBreakByCharWrapping];
[_content setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_content setFrameOrigin:CGPointMake(0.0, 0.0)];
+1 -1
View File
@@ -393,7 +393,7 @@
while (index !== CPNotFound)
{
_remove(_proxyObject, _removeSEL, index)
_remove(_proxyObject, _removeSEL, index);
index = [theIndexes indexLessThanIndex:index];
}
}
+4 -4
View File
@@ -638,7 +638,7 @@ var defaultDateFormatterBehavior = CPDateFormatterBehavior10_4,
if ([self _isEnglishFormat])
format += @"h:mm:ss a";
else
format += @"H:mm:ss"
format += @"H:mm:ss";
break;
@@ -1218,7 +1218,7 @@ var defaultDateFormatterBehavior = CPDateFormatterBehavior10_4,
if ([self _isEnglishFormat])
format += @" h:mm:ss a";
else
format += @" H:mm:ss"
format += @" H:mm:ss";
break;
case CPDateFormatterLongStyle:
@@ -1534,7 +1534,7 @@ var defaultDateFormatterBehavior = CPDateFormatterBehavior10_4,
var month;
if (length <= 2)
month = parseInt(dateComponent)
month = parseInt(dateComponent);
if (length == 3)
{
@@ -1847,7 +1847,7 @@ var defaultDateFormatterBehavior = CPDateFormatterBehavior10_4,
tmpDate.setFullYear(dateArray[0]);
tmpDate.setMonth(0);
tmpDate.setDate(dayOfYear)
tmpDate.setDate(dayOfYear);
dateArray[1] = tmpDate.getMonth() + 1;
dateArray[2] = tmpDate.getDate();
+1 -1
View File
@@ -276,7 +276,7 @@ var CPDictionaryMaxDescriptionRecursion = 10;
while (argCount-- > 2)
{
var key = arguments[argCount--],
value = arguments[argCount]
value = arguments[argCount];
if (value === nil)
[CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil object from objects[" + ((argCount / 2) - 1) + @"]"];
+6 -6
View File
@@ -512,8 +512,8 @@
if (options & CPEnumerationReverse)
{
index = _ranges.length - 1,
stop = -1,
index = _ranges.length - 1;
stop = -1;
increment = -1;
}
else
@@ -593,8 +593,8 @@
if (anOptions & CPEnumerationReverse)
{
index = _ranges.length - 1,
stop = -1,
index = _ranges.length - 1;
stop = -1;
increment = -1;
}
else
@@ -652,8 +652,8 @@
if (anOptions & CPEnumerationReverse)
{
index = _ranges.length - 1,
stop = -1,
index = _ranges.length - 1;
stop = -1;
increment = -1;
}
else
+3 -3
View File
@@ -300,7 +300,7 @@ var runLoop = [CPRunLoop mainRunLoop];
if (coalesceMask & CPNotificationCoalescingOnName && coalesceMask & CPNotificationCoalescingOnSender)
{
if ([notification object] == sender && [notification name] == name)
[notificationsToRemove addObject:notification]
[notificationsToRemove addObject:notification];
continue;
}
@@ -308,7 +308,7 @@ var runLoop = [CPRunLoop mainRunLoop];
if (coalesceMask & CPNotificationCoalescingOnName)
{
if ([notification name] == name)
[notificationsToRemove addObject:notification]
[notificationsToRemove addObject:notification];
continue;
}
@@ -316,7 +316,7 @@ var runLoop = [CPRunLoop mainRunLoop];
if (coalesceMask & CPNotificationCoalescingOnSender)
{
if ([notification object] == sender)
[notificationsToRemove addObject:notification]
[notificationsToRemove addObject:notification];
continue;
}
+1 -1
View File
@@ -287,7 +287,7 @@
- (id)initWithString:(CPString)format args:(CPArray)args
{
self = [super initWithString:format]
self = [super initWithString:format];
if (self)
{
+1 -1
View File
@@ -48,7 +48,7 @@
return class_createInstance(self);
}
+ (BOOL)respondsToSelector:(SEL)selector
+ (BOOL)respondsToSelector:(SEL)aSelector
{
return !!class_getInstanceMethod(isa, aSelector);
}
+1 -1
View File
@@ -59,7 +59,7 @@ CPUserNotificationActivationTypeActionButtonClicked = 2;
@group CPUserNotificationActivationType
The user replied to the notification.
*/
CPUserNotificationActivationTypeReplied = 3,
CPUserNotificationActivationTypeReplied = 3;
/*!
@global CPUserNotificationActivationType
@@ -0,0 +1,42 @@
/*
* AppController.j
* WindowFrontTest
*
* Created by You on January 15, 2018.
* Copyright 2018, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@implementation AppController : CPObject
{
@outlet CPWindow theWindow;
@outlet CPWindow window1;
@outlet CPWindow window2;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
// This is called when the application is done loading.
}
- (void)awakeFromCib
{
// This is called when the cib is done loading.
// You can implement this method on any object instantiated from a Cib.
// It's a useful hook for setting up current UI values, and other things.
// In this case, we want the window from Cib to become our full browser window
[theWindow setFullPlatformWindow:YES];
[window1 performSelector:@selector(makeKeyAndOrderFront:) withObject:self afterDelay:0.1];
}
- (IBAction)bringWindow2Front:(id)sender
{
[window2 orderFront:self];
}
@end
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Main cib file base name</key>
<string>MainMenu.cib</string>
<key>CPBundleName</key>
<string>WindowFrontTest</string>
<key>CPBundleVersion</key>
<string>1.0</string>
<key>CPHumanReadableCopyright</key>
<string>Copyright © 2018, Your Company All rights reserved.</string>
</dict>
</plist>
@@ -0,0 +1,172 @@
/*
* Jakefile
* WindowFrontTest
*
* Created by You on January 15, 2018.
* Copyright 2018, Your Company All rights reserved.
*/
var ENV = require("system").env,
FILE = require("file"),
JAKE = require("jake"),
task = JAKE.task,
FileList = JAKE.FileList,
app = require("cappuccino/jake").app,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
OS = require("os"),
projectName = "WindowFrontTest";
app (projectName, function(task)
{
ENV["OBJJ_INCLUDE_PATHS"] = "Frameworks";
if (configuration === "Debug")
ENV["OBJJ_INCLUDE_PATHS"] = FILE.join(ENV["OBJJ_INCLUDE_PATHS"], configuration);
task.setBuildIntermediatesPath(FILE.join("Build", "WindowFrontTest.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("WindowFrontTest");
task.setIdentifier("com.yourcompany.WindowFrontTest");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("WindowFrontTest");
task.setSources(new FileList("**/*.j").exclude(FILE.join("Build", "**")).exclude(FILE.join("Frameworks", "Source", "**")));
task.setResources(new FileList("Resources/**"));
task.setIndexFilePath("index.html");
task.setInfoPlistPath("Info.plist");
if (configuration === "Debug")
task.setCompilerFlags("-DDEBUG -g");
else
task.setCompilerFlags("-O2");
});
task ("default", [projectName], function()
{
printResults(configuration);
});
task ("build", ["default"], function()
{
updateApplicationSize();
});
task ("debug", function()
{
configuration = ENV["CONFIGURATION"] = "Debug";
JAKE.subjake(["."], "build", ENV);
});
task ("release", function()
{
configuration = ENV["CONFIGURATION"] = "Release";
JAKE.subjake(["."], "build", ENV);
});
task ("run", ["debug"], function()
{
OS.system(["open", FILE.join("Build", "Debug", projectName, "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", projectName, "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", projectName));
OS.system(["press", "-f", FILE.join("Build", "Release", projectName), FILE.join("Build", "Deployment", projectName)]);
printResults("Deployment")
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, projectName));
print("----------------------------");
}
function updateApplicationSize()
{
print("Calculating application file sizes...");
var contents = FILE.read(FILE.join("Build", configuration, projectName, "Info.plist"), { charset:"UTF-8" }),
format = CFPropertyList.sniffedFormatOfString(contents),
plist = CFPropertyList.propertyListFromString(contents),
totalBytes = {executable:0, data:0, mhtml:0};
// Get the size of all framework executables and sprite data
var frameworksDir = "Frameworks";
if (configuration === "Debug")
frameworksDir = FILE.join(frameworksDir, "Debug");
var frameworks = FILE.list(frameworksDir);
frameworks.forEach(function(framework)
{
if (framework !== "Source")
addBundleFileSizes(FILE.join(frameworksDir, framework), totalBytes);
});
// Read in the default theme name, and attempt to get its size
var themeName = plist.valueForKey("CPDefaultTheme") || "Aristo2",
themePath = nil;
if (themeName === "Aristo" || themeName === "Aristo2")
themePath = FILE.join(frameworksDir, "AppKit", "Resources", themeName + ".blend");
else
themePath = FILE.join("Frameworks", "Resources", themeName + ".blend");
if (FILE.isDirectory(themePath))
addBundleFileSizes(themePath, totalBytes);
// Add sizes for the app
addBundleFileSizes(FILE.join("Build", configuration, projectName), totalBytes);
print("Executables: " + totalBytes.executable + ", sprite data: " + totalBytes.data + ", total: " + (totalBytes.executable + totalBytes.data));
var dict = new CFMutableDictionary();
dict.setValueForKey("executable", totalBytes.executable);
dict.setValueForKey("data", totalBytes.data);
dict.setValueForKey("mhtml", totalBytes.mhtml);
plist.setValueForKey("CPApplicationSize", dict);
FILE.write(FILE.join("Build", configuration, projectName, "Info.plist"), CFPropertyList.stringFromPropertyList(plist, format), { charset:"UTF-8" });
}
function addBundleFileSizes(bundlePath, totalBytes)
{
var bundleName = FILE.basename(bundlePath),
environment = bundleName === "Foundation" ? "Objj" : "Browser",
bundlePath = FILE.join(bundlePath, environment + ".environment");
if (FILE.isDirectory(bundlePath))
{
var filename = bundleName + ".sj",
filePath = new FILE.Path(FILE.join(bundlePath, filename));
if (filePath.exists())
totalBytes.executable += filePath.size();
filePath = new FILE.Path(FILE.join(bundlePath, "dataURLs.txt"));
if (filePath.exists())
totalBytes.data += filePath.size();
filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLData.txt"));
if (filePath.exists())
totalBytes.mhtml += filePath.size();
filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLPaths.txt"));
if (filePath.exists())
totalBytes.mhtml += filePath.size();
}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,345 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment version="1050" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="450" id="451"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29" userLabel="MainMenu">
<items>
<menuItem title="NewApplication" id="56">
<menu key="submenu" title="NewApplication" systemMenu="apple" id="57">
<items>
<menuItem title="About NewApplication" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="236">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
<menuItem isSeparatorItem="YES" id="143">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit NewApplication" keyEquivalent="q" id="136">
<connections>
<action selector="terminate:" target="-3" id="449"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="83">
<menu key="submenu" title="File" id="81">
<items>
<menuItem title="New" keyEquivalent="n" id="82">
<connections>
<action selector="newDocument:" target="-1" id="373"/>
</connections>
</menuItem>
<menuItem title="Open…" keyEquivalent="o" id="72">
<connections>
<action selector="openDocument:" target="-1" id="374"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="124">
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
<items>
<menuItem title="Clear Menu" id="126">
<connections>
<action selector="clearRecentDocuments:" target="-1" id="127"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="79">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Close" keyEquivalent="w" id="73">
<connections>
<action selector="performClose:" target="-1" id="193"/>
</connections>
</menuItem>
<menuItem title="Save" keyEquivalent="s" id="75">
<connections>
<action selector="saveDocument:" target="-1" id="362"/>
</connections>
</menuItem>
<menuItem title="Save As…" keyEquivalent="S" id="80">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="saveDocumentAs:" target="-1" id="363"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="112">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207">
<connections>
<action selector="undo:" target="-1" id="223"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="215">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="redo:" target="-1" id="231"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="206">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Cut" keyEquivalent="x" id="199">
<connections>
<action selector="cut:" target="-1" id="228"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="197">
<connections>
<action selector="copy:" target="-1" id="224"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="203">
<connections>
<action selector="paste:" target="-1" id="226"/>
</connections>
</menuItem>
<menuItem title="Delete" id="202">
<connections>
<action selector="delete:" target="-1" id="235"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="198">
<connections>
<action selector="selectAll:" target="-1" id="232"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="214">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Find" id="218">
<menu key="submenu" title="Find" id="220">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
<connections>
<action selector="performFindPanelAction:" target="-1" id="241"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208"/>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="216">
<menu key="submenu" title="Spelling and Grammar" id="200">
<items>
<menuItem title="Show Spelling…" keyEquivalent=":" id="204">
<connections>
<action selector="showGuessPanel:" target="-1" id="230"/>
</connections>
</menuItem>
<menuItem title="Check Spelling" keyEquivalent=";" id="201">
<connections>
<action selector="checkSpelling:" target="-1" id="225"/>
</connections>
</menuItem>
<menuItem title="Check Spelling While Typing" id="219">
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="346">
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="347"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="348">
<menu key="submenu" title="Substitutions" id="349">
<items>
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
</connections>
</menuItem>
<menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196">
<connections>
<action selector="startSpeaking:" target="-1" id="233"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="195">
<connections>
<action selector="stopSpeaking:" target="-1" id="227"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="295">
<menu key="submenu" title="View" id="296">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="297">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="-1" id="366"/>
</connections>
</menuItem>
<menuItem title="Customize Toolbar…" id="298">
<connections>
<action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="19">
<menu key="submenu" title="Window" systemMenu="window" id="24">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="23">
<connections>
<action selector="performMiniaturize:" target="-1" id="37"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="239">
<connections>
<action selector="performZoom:" target="-1" id="240"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="92">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="103">
<menu key="submenu" title="Help" id="106">
<items>
<menuItem title="NewApplication Help" keyEquivalent="?" id="111">
<connections>
<action selector="showHelp:" target="-1" id="360"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</window>
<customObject id="450" customClass="AppController">
<connections>
<outlet property="theWindow" destination="371" id="459"/>
<outlet property="window1" destination="kRP-VT-tv9" id="2TI-fY-uNl"/>
<outlet property="window2" destination="4si-18-Oew" id="iNb-Xs-G9x"/>
</connections>
</customObject>
<window title="Window 1" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="kRP-VT-tv9">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="157" y="1040" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="dDt-6B-FIn">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button verticalHuggingPriority="750" misplaced="YES" id="4M7-1t-wjx">
<rect key="frame" x="145" y="117" width="190" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Bring Window 2 To Front" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="3g3-Ut-vYm">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="bringWindow2Front:" target="450" id="a8c-Tq-bGf"/>
</connections>
</button>
</subviews>
</view>
<point key="canvasLocation" x="-132" y="-287"/>
</window>
<window title="Window 2" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="4si-18-Oew">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="246" y="896" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="jh8-f4-iLs">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" misplaced="YES" allowsCharacterPickerTouchBarItem="YES" id="CYV-eL-j9l">
<rect key="frame" x="58" y="114" width="365" height="42"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="This is window 2--let us hope a click on window 1 will bring it to front!" id="42x-Ge-M2N">
<font key="font" size="15" name="Arial-BoldMT"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
<point key="canvasLocation" x="431" y="-287"/>
</window>
</objects>
</document>
@@ -0,0 +1,204 @@
<!DOCTYPE html>
<html lang="en">
<!--
index-debug.html
WindowFrontTest
Created by You on January 15, 2018.
Copyright 2018, Your Company All rights reserved.
-->
<head>
<meta charset="utf-8">
<!--[if lte IE 8]>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1">
<![endif]-->
<!--[if gte IE 9]>
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<![endif]-->
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon" href="Resources/icon.png">
<link rel="apple-touch-startup-image" href="Resources/default.png">
<title>WindowFrontTest</title>
<!-- Custom javascript goes here -->
<!-- End custom javascript -->
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks"];
// The below will tell the compiler to generate debug symbols, type signatures and not inline objj_msgSend functions.
// This will affect only Objective-J code that is compiled when loading the application. It will not affect precompiled
// code like the Cappuccino frameworks.
//
// Debug symbols will give each Objective-J method a Javascript function name. Without a name it will be very hard to find
// the methods in the debugger.
// Type Signatures will give type information to the Objective-J runtime for instance variables and methods.
// Inline objj_msgSend will give a speed increase but decorators will not work. Check below on debug options for
// more information on decorators.
//
// Uncomment or comment on the line below to change the flags
OBJJ_COMPILER_FLAGS = ["IncludeDebugSymbols", "IncludeTypeSignatures"/*, "InlineMsgSend"*/];
var progressBar = null;
OBJJ_PROGRESS_CALLBACK = function(percent, appSize, path)
{
percent = percent * 100;
if (!progressBar)
progressBar = document.getElementById("progress-bar");
if (progressBar)
progressBar.style.width = Math.min(percent, 100) + "%";
}
var loadingHTML =
'<div id="loading">' +
' <div id="loading-text">Loading...</div>' +
' <div id="progress-indicator">' +
' <span id="progress-bar" style="width:0%"></span>' +
' </div>' +
'</div>';
</script>
<script type="text/javascript" src="Frameworks/Debug/Objective-J/Objective-J.js" charset="UTF-8"></script>
<script type="text/javascript">
objj_msgSend_reset();
// DEBUG OPTIONS:
// Decorators will only work when the code is compiled without the compiler option 'InlineMsgSend'. Check above.
// Uncomment to enable printing of backtraces on exceptions:
//objj_msgSend_decorate(objj_backtrace_decorator);
// Uncomment to supress exceptions that take place inside a message
//objj_msgSend_decorate(objj_supress_exceptions_decorator)
// Uncomment to enable runtime type checking:
//objj_msgSend_decorate(objj_typecheck_decorator);
// Uncomment (along with both above) to print backtraces on type check errors:
//objj_typecheck_prints_backtrace = true;
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
//CPLogUnregister(CPLogDefault);
// Uncomment to enable a specific logger:
//CPLogRegister(CPLogConsole);
//CPLogRegister(CPLogPopup);
// Tag view DOM elements with a "data-cappuccino-view" attribute that contains
// the class name of the view that created them. Comment this or set to false to disable.
appkit_tag_dom_elements = true;
</script>
<style type="text/css">
html, body, h1, p {
margin: 0;
padding: 0;
}
/* We need a body wrapper because Cappuccino is unhappy if we change the body element */
#cappuccino-body {
/* Position it absolutely so it will fill the height without content */
position: absolute;
top: 0;
bottom: 0;
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: 0;
}
#cappuccino-body .container {
display: table;
margin: 0 auto;
height: 100%;
}
#cappuccino-body .content {
display: table-cell;
height: 100%;
vertical-align: top;
}
#loading {
position: relative;
top: 35%;
}
#loading-text {
height: 1.5em;
color: #555;
font: normal bold 36px/36px Arial, sans-serif;
}
#progress-indicator {
padding: 0px;
height: 16px;
border: 5px solid #555;
border-radius: 18px;
background-color: white;
}
#progress-bar {
position: relative;
top: -1px;
left: -1px;
display: block;
height: 18px;
/* Compensate for moving the bar left 1px to overlap the indicator border */
border-right: 1px solid #555;
background-color: #555;
}
#noscript {
position: relative;
top: 35%;
padding: 1em 1.5em;
border: 5px solid #555;
border-radius: 16px;
background-color: white;
color: #555;
text-align: center;
font: bold 24px Arial, sans-serif;
}
#noscript a {
color: #98c0ff;
text-decoration: none;
}
</style>
</head>
<body>
<div id="cappuccino-body">
<div class="container">
<div class="content">
<script type="text/javascript">
document.write(loadingHTML);
</script>
</div>
</div>
<noscript style="position:absolute; top:0; left:0; width:100%; height:100%">
<div class="container">
<div class="content">
<div id="noscript">
<p style="font-size:120%; margin-bottom:.75em">JavaScript is required for this site.</p>
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
</div>
</div>
</div>
</noscript>
</div>
</body>
</html>
@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="en">
<!--
index.html
WindowFrontTest
Created by You on January 15, 2018.
Copyright 2018, Your Company All rights reserved.
-->
<head>
<meta charset="utf-8">
<!--[if lte IE 8]>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1">
<![endif]-->
<!--[if gte IE 9]>
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<![endif]-->
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon" href="Resources/icon.png">
<link rel="apple-touch-startup-image" href="Resources/default.png">
<title>WindowFrontTest</title>
<!-- Custom javascript goes here -->
<!-- End custom javascript -->
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
// The below will tell the compiler to not generate debug symbols but will generate type signatures and inline objj_msgSend functions.
// This will affect only Objective-J code that is compiled when loading the application. It will not affect precompiled
// code like the Cappuccino frameworks.
// Uncomment or comment on the line below to change the flags
OBJJ_COMPILER_FLAGS = [/*"IncludeDebugSymbols"*/, "IncludeTypeSignatures", "InlineMsgSend"];
var progressBar = null;
OBJJ_PROGRESS_CALLBACK = function(percent, appSize, path)
{
percent = percent * 100;
if (!progressBar)
progressBar = document.getElementById("progress-bar");
if (progressBar)
progressBar.style.width = Math.min(percent, 100) + "%";
}
var loadingHTML =
'<div id="loading">' +
' <div id="loading-text">Loading...</div>' +
' <div id="progress-indicator">' +
' <span id="progress-bar" style="width:0%"></span>' +
' </div>' +
'</div>';
</script>
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
<style type="text/css">
html, body, h1, p {
margin: 0;
padding: 0;
}
/* We need a body wrapper because Cappuccino is unhappy if we change the body element */
#cappuccino-body {
/* Position it absolutely so it will fill the height without content */
position: absolute;
top: 0;
bottom: 0;
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: 0;
}
#cappuccino-body .container {
display: table;
margin: 0 auto;
height: 100%;
}
#cappuccino-body .content {
display: table-cell;
height: 100%;
vertical-align: top;
}
#loading {
position: relative;
top: 35%;
}
#loading-text {
height: 1.5em;
color: #555;
font: normal bold 36px/36px Arial, sans-serif;
}
#progress-indicator {
padding: 0px;
height: 16px;
border: 5px solid #555;
border-radius: 18px;
background-color: white;
}
#progress-bar {
position: relative;
top: -1px;
left: -1px;
display: block;
height: 18px;
/* Compensate for moving the bar left 1px to overlap the indicator border */
border-right: 1px solid #555;
background-color: #555;
}
#noscript {
position: relative;
top: 35%;
padding: 1em 1.5em;
border: 5px solid #555;
border-radius: 16px;
background-color: white;
color: #555;
text-align: center;
font: bold 24px Arial, sans-serif;
}
#noscript a {
color: #98c0ff;
text-decoration: none;
}
</style>
</head>
<body>
<div id="cappuccino-body">
<div class="container">
<div class="content">
<script type="text/javascript">
document.write(loadingHTML);
</script>
</div>
</div>
<noscript style="position:absolute; top:0; left:0; width:100%; height:100%">
<div class="container">
<div class="content">
<div id="noscript">
<p style="font-size:120%; margin-bottom:.75em">JavaScript is required for this site.</p>
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
</div>
</div>
</div>
</noscript>
</div>
</body>
</html>
@@ -0,0 +1,18 @@
/*
* AppController.j
* WindowFrontTest
*
* Created by You on January 15, 2018.
* Copyright 2018, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}
+3 -3
View File
@@ -46,14 +46,14 @@ function printUsage()
print(" -l Same as --symlink --build, symlinks $CAPP_BUILD Frameworks into your project");
print(" -t, --template NAME Specify the template name to use (see `capp gen --list-templates`)");
print(" -f, --frameworks Copy/symlink *only* the Frameworks directory to a new or existing project");
print(" -F, --framework NAME Additional framework to copy/symlink (default: Objective-J, Foundation, AppKit)")
print(" -T, --theme NAME Additional Theme to copy/symlink into Resource (default: nothing)")
print(" -F, --framework NAME Additional framework to copy/symlink (default: Objective-J, Foundation, AppKit)");
print(" -T, --theme NAME Additional Theme to copy/symlink into Resource (default: nothing)");
print(" --force Overwrite Frameworks directory if it already exists");
print(" --symlink Symlink the source Frameworks directory to the project, don't copy");
print(" --build Copy/symlink the Frameworks directory files from your $CAPP_BUILD directory");
print(" --noconfig Use the default configuration when replacing template variables");
print("");
print(" Without -l or --build, frameworks from your narwhal installation are copied/symlinked")
print(" Without -l or --build, frameworks from your narwhal installation are copied/symlinked");
print("");
print(" gen --list-templates List the template names available for use with `capp gen -t/--template`");
print(" gen --list-frameworks List the framework names available for use with `capp gen -F/--framework`");
+2 -2
View File
@@ -39,8 +39,8 @@ var FILE = require("file"),
SharedConverter = nil;
NibFormatUndetermined = 0,
NibFormatMac = 1,
NibFormatUndetermined = 0;
NibFormatMac = 1;
NibFormatIPhone = 2;
ConverterModeLegacy = 0;
+1 -1
View File
@@ -88,7 +88,7 @@ var FILE = require("file"),
if (resourceInfo && resourceInfo.path)
{
// Include subdirectories in the name
match = /^.+\/Resources\/(.+)$/.exec(resourceInfo.path)
match = /^.+\/Resources\/(.+)$/.exec(resourceInfo.path);
_resourceName = match[1];
}
}
+1 -1
View File
@@ -842,7 +842,7 @@ var FILE = require("file"),
// By default when we try to load the bundle it will use the CommonJS environment,
// but we want the Browser environment. So we override mostEligibleEnvironment().
themeBundle.mostEligibleEnvironment = function() { return "Browser"; }
themeBundle.mostEligibleEnvironment = function() { return "Browser"; };
themeBundle.load();
var keyedThemes = themeBundle.valueForInfoDictionaryKey("CPKeyedThemes");