mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-20 01:13:29 +00:00
Merge branch 'aparajita-fonts' into 0.9.1
This commit is contained in:
@@ -5,3 +5,7 @@ Demos
|
||||
./Aristo
|
||||
WebSite
|
||||
.push-package
|
||||
*.xcodeproj/*.pbxuser
|
||||
*.xcodeproj/*.perspectivev3
|
||||
xcuserdata/
|
||||
!*.xcodeproj/project.pbxproj
|
||||
|
||||
+186
-29
@@ -25,20 +25,49 @@
|
||||
|
||||
@import "CPView.j"
|
||||
|
||||
CPFontDefaultSystemFontFace = @"Arial, sans-serif";
|
||||
CPFontDefaultSystemFontSize = 12;
|
||||
|
||||
var _CPFonts = {},
|
||||
_CPFontSystemFontFace = @"Arial, sans-serif",
|
||||
_CPWrapRegExp = new RegExp("\\s*,\\s*", "g");
|
||||
var _CPFonts = {},
|
||||
_CPFontSystemFontFace = CPFontDefaultSystemFontFace,
|
||||
_CPFontSystemFontSize = 12,
|
||||
_CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "),
|
||||
_CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
|
||||
|
||||
|
||||
#define _CPCreateCSSString(aName, aSize, isBold) (isBold ? @"bold " : @"") + ROUND(aSize) + @"px " + ((aName === _CPFontSystemFontFace) ? aName : (@"\"" + aName.replace(_CPWrapRegExp, '", "') + @"\", " + _CPFontSystemFontFace))
|
||||
#define _CPCachedFont(aName, aSize, isBold) _CPFonts[_CPCreateCSSString(aName, aSize, isBold)]
|
||||
#define _CPFontNormalizedNames(aName) _CPFontNormalizedNameArray(aName).join(", ")
|
||||
#define _CPCachedFont(aName, aSize, isBold, isItalic) _CPFonts[_CPFontCreateCSSString(_CPFontNormalizedNames(aName), aSize, isBold, isItalic)]
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPFont
|
||||
|
||||
The CPFont class allows control of the fonts used for displaying text anywhere on the screen. The primary method for getting a particular font is through one of the class methods that take a name and/or size as arguments, and return the appropriate CPFont.
|
||||
The CPFont class allows control of the fonts used for displaying text anywhere on the screen.
|
||||
The primary method for getting a particular font is through one of the class methods that take
|
||||
a name and/or size as arguments, and return the appropriate CPFont.
|
||||
|
||||
By default the system font face/size is Arial 12px, with a fallback to sans-serif. You may
|
||||
configure this at runtime in two ways:
|
||||
|
||||
- By sending [CPFont @link CPFont::setSystemFontFace: setSystemFontFace:@endlink] and/or [CPFont @link CPFont::setSystemFontSize: setSystemFontSize:@endlink].
|
||||
- By configuring Info.plist for your application or for AppKit. You can set the font face
|
||||
by adding a CPSystemFontFace string item to the Info.plist, and you can set the font size
|
||||
by adding a CPSystemFontSize integer item to the Info.plist.
|
||||
|
||||
Note that in either case, you can specify a comma-delimited list of fonts as the font face.
|
||||
The browser will use the first available font in the list. CPFont always ensures that Arial
|
||||
and sans-serif are always in the generated CSS string, so there is no need to add them to
|
||||
the end of your font list.
|
||||
|
||||
If you are using nib2cib, you should use the second method (using Info.plist),
|
||||
and be sure to run nib2cib again any time you modify the CPSystemFontFace or CPSystemFontSize items.
|
||||
For example, you might add this to your application's Info.plist to set the system font to Lucida Grande,
|
||||
with an automatic fallback to Arial or sans-serif:
|
||||
|
||||
@code
|
||||
<key>CPSystemFontFace</key>
|
||||
<string>Lucida Grande</string>
|
||||
@endcode
|
||||
*/
|
||||
@implementation CPFont : CPObject
|
||||
{
|
||||
@@ -47,78 +76,153 @@ var _CPFonts = {},
|
||||
float _ascender;
|
||||
float _descender;
|
||||
float _lineHeight;
|
||||
BOOL _isBold;
|
||||
BOOL _isBold @accessors(readonly, getter=isBold);
|
||||
BOOL _isItalic @accessors(readonly, getter=isItalic);
|
||||
|
||||
CPString _cssString;
|
||||
}
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
var systemFont = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:"CPSystemFontFace"];
|
||||
var systemFontFace = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPSystemFontFace"];
|
||||
|
||||
if (systemFont)
|
||||
_CPFontSystemFontFace = systemFont;
|
||||
if (!systemFontFace)
|
||||
systemFontFace = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:@"CPSystemFontFace"];
|
||||
|
||||
if (systemFontFace)
|
||||
[self setSystemFontFace:systemFontFace];
|
||||
|
||||
var systemFontSize = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPSystemFontSize"];
|
||||
|
||||
if (!systemFontSize)
|
||||
systemFontSize = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:@"CPSystemFontSize"];
|
||||
|
||||
if (systemFontSize)
|
||||
_CPFontSystemFontSize = systemFontSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the default system font face, which may consist of several comma-separated family names.
|
||||
*/
|
||||
+ (CPString)systemFontFace
|
||||
{
|
||||
return _CPFontSystemFontFace;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the default system font face, which may consist of several comma-separated family names.
|
||||
*/
|
||||
+ (CPString)setSystemFontFace:(CPString)aFace
|
||||
{
|
||||
_CPFontSystemFontFace = _CPFontNormalizedNames(aFace);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the default system font size.
|
||||
*/
|
||||
+ (float)systemFontSize
|
||||
{
|
||||
return _CPFontSystemFontSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the default system font size.
|
||||
*/
|
||||
+ (float)setSystemFontSize:(float)size
|
||||
{
|
||||
if (size > 0)
|
||||
_CPFontSystemFontSize = size;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a font with the specified name and size.
|
||||
@param aName the name of the font
|
||||
@param aSize the size of the font (in points)
|
||||
@param aSize the size of the font (in px)
|
||||
@return the requested font
|
||||
*/
|
||||
+ (CPFont)fontWithName:(CPString)aName size:(float)aSize
|
||||
{
|
||||
return _CPCachedFont(aName, aSize, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO];
|
||||
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:NO];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a font with the specified name, size and style.
|
||||
@param aName the name of the font
|
||||
@param aSize the size of the font (in px)
|
||||
@param italic whether the font should be italicized
|
||||
@return the requested font
|
||||
*/
|
||||
+ (CPFont)fontWithName:(CPString)aName size:(float)aSize italic:(BOOL)italic
|
||||
{
|
||||
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:italic];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a bold font with the specified name and size.
|
||||
@param aName the name of the font
|
||||
@param aSize the size of the font (in points)
|
||||
@param aSize the size of the font (in px)
|
||||
@return the requested bold font
|
||||
*/
|
||||
+ (CPFont)boldFontWithName:(CPString)aName size:(float)aSize
|
||||
{
|
||||
return _CPCachedFont(aName, aSize, YES) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES];
|
||||
return _CPCachedFont(aName, aSize, YES, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:NO];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a bold font with the specified name, size and style.
|
||||
@param aName the name of the font
|
||||
@param aSize the size of the font (in px)
|
||||
@param italic whether the font should be italicized
|
||||
@return the requested font
|
||||
*/
|
||||
+ (CPFont)boldFontWithName:(CPString)aName size:(float)aSize italic:(BOOL)italic
|
||||
{
|
||||
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:italic];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the system font scaled to the specified size
|
||||
@param aSize the size of the font (in points)
|
||||
@param aSize the size of the font (in px)
|
||||
@return the requested system font
|
||||
*/
|
||||
+ (CPFont)systemFontOfSize:(CPSize)aSize
|
||||
{
|
||||
return _CPCachedFont(_CPFontSystemFontFace, aSize, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:NO];
|
||||
return _CPCachedFont(_CPFontSystemFontFace, aSize, NO, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:NO italic:NO];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the bold system font scaled to the specified size
|
||||
@param aSize the size of the font (in points)
|
||||
@param aSize the size of the font (in px)
|
||||
@return the requested bold system font
|
||||
*/
|
||||
+ (CPFont)boldSystemFontOfSize:(CPSize)aSize
|
||||
{
|
||||
return _CPCachedFont(_CPFontSystemFontFace, aSize, YES) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:YES];
|
||||
return _CPCachedFont(_CPFontSystemFontFace, aSize, YES, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:YES italic:NO];
|
||||
}
|
||||
|
||||
/* FIXME Font Descriptor
|
||||
@ignore
|
||||
*/
|
||||
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold
|
||||
{
|
||||
return [self _initWithName:aName size:aSize bold:isBold italic:NO];
|
||||
}
|
||||
|
||||
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold italic:(BOOL)isItalic
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_name = aName;
|
||||
_name = _CPFontNormalizedNames(aName);
|
||||
_size = aSize;
|
||||
_ascender = 0;
|
||||
_descender = 0;
|
||||
_lineHeight = 0;
|
||||
_isBold = isBold;
|
||||
_isItalic = isItalic;
|
||||
|
||||
_cssString = _CPCreateCSSString(_name, _size, _isBold);
|
||||
_cssString = _CPFontCreateCSSString(_name, _size, _isBold, _isItalic);
|
||||
|
||||
_CPFonts[_cssString] = self;
|
||||
}
|
||||
@@ -139,7 +243,7 @@ var _CPFonts = {},
|
||||
|
||||
/*!
|
||||
Returns the bottom y coordinate (in CSS px), offset from the baseline, of the receiver's longest descender.
|
||||
Thus, if the longest descender extends 2 points below the baseline, descender will return –2.
|
||||
Thus, if the longest descender extends 2 px below the baseline, descender will return –2.
|
||||
*/
|
||||
- (float)descender
|
||||
{
|
||||
@@ -188,12 +292,17 @@ var _CPFonts = {},
|
||||
|
||||
- (BOOL)isEqual:(id)anObject
|
||||
{
|
||||
return [anObject isKindOfClass:[CPFont class]] && [anObject cssString] === [self cssString];
|
||||
return [anObject isKindOfClass:[CPFont class]] && [anObject cssString] === _cssString;
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return [CPString stringWithFormat:@"%@ %@ %f pt.", [super description], [self familyName], [self size]];
|
||||
return [CPString stringWithFormat:@"%@ %@", [super description], [self cssString]];
|
||||
}
|
||||
|
||||
- (id)copy
|
||||
{
|
||||
return [[CPFont alloc] _initWithName:_name size:_size bold:_isBold italic:_isItalic];
|
||||
}
|
||||
|
||||
- (void)_getMetrics
|
||||
@@ -207,9 +316,10 @@ var _CPFonts = {},
|
||||
|
||||
@end
|
||||
|
||||
var CPFontNameKey = @"CPFontNameKey",
|
||||
CPFontSizeKey = @"CPFontSizeKey",
|
||||
CPFontIsBoldKey = @"CPFontIsBoldKey";
|
||||
var CPFontNameKey = @"CPFontNameKey",
|
||||
CPFontSizeKey = @"CPFontSizeKey",
|
||||
CPFontIsBoldKey = @"CPFontIsBoldKey",
|
||||
CPFontIsItalicKey = @"CPFontIsItalicKey";
|
||||
|
||||
@implementation CPFont (CPCoding)
|
||||
|
||||
@@ -220,9 +330,12 @@ var CPFontNameKey = @"CPFontNameKey",
|
||||
*/
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
return [self _initWithName:[aCoder decodeObjectForKey:CPFontNameKey]
|
||||
size:[aCoder decodeFloatForKey:CPFontSizeKey]
|
||||
bold:[aCoder decodeBoolForKey:CPFontIsBoldKey]];
|
||||
var fontName = [aCoder decodeObjectForKey:CPFontNameKey],
|
||||
size = [aCoder decodeFloatForKey:CPFontSizeKey],
|
||||
isBold = [aCoder decodeBoolForKey:CPFontIsBoldKey],
|
||||
isItalic = [aCoder decodeBoolForKey:CPFontIsItalicKey];
|
||||
|
||||
return [self _initWithName:fontName size:size bold:isBold italic:isItalic];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -234,6 +347,50 @@ var CPFontNameKey = @"CPFontNameKey",
|
||||
[aCoder encodeObject:_name forKey:CPFontNameKey];
|
||||
[aCoder encodeFloat:_size forKey:CPFontSizeKey];
|
||||
[aCoder encodeBool:_isBold forKey:CPFontIsBoldKey];
|
||||
[aCoder encodeBool:_isItalic forKey:CPFontIsItalicKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// aName must be normalized
|
||||
var _CPFontCreateCSSString = function(aName, aSize, isBold, isItalic)
|
||||
{
|
||||
var properties = (isItalic ? "italic " : "") + (isBold ? "bold " : "") + aSize + "px ";
|
||||
|
||||
return properties + _CPFontConcatNameWithFallback(aName);
|
||||
};
|
||||
|
||||
var _CPFontConcatNameWithFallback = function(aName)
|
||||
{
|
||||
var names = _CPFontNormalizedNameArray(aName),
|
||||
fallbackFaces = _CPFontFallbackFaces.slice(0);
|
||||
|
||||
// Remove the fallback names used in the names passed in
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
{
|
||||
for (var j = 0; j < fallbackFaces.length; ++j)
|
||||
{
|
||||
if (names[i].toLowerCase() === fallbackFaces[j].toLowerCase())
|
||||
{
|
||||
fallbackFaces.splice(j, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (names[i].indexOf(" ") > 0)
|
||||
names[i] = '"' + names[i] + '"';
|
||||
}
|
||||
|
||||
return names.concat(fallbackFaces).join(", ");
|
||||
};
|
||||
|
||||
var _CPFontNormalizedNameArray = function(aName)
|
||||
{
|
||||
var names = aName.split(",");
|
||||
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
names[i] = names[i].replace(_CPFontStripRegExp, "");
|
||||
|
||||
return names;
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
CPNumber _selectedIndex;
|
||||
|
||||
CPTabViewType _type;
|
||||
CPFont _font;
|
||||
|
||||
id _delegate;
|
||||
unsigned _delegateSelectors;
|
||||
@@ -267,6 +268,27 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
return [_items objectAtIndex:_selectedIndex];
|
||||
}
|
||||
|
||||
// Modifying the font
|
||||
/*!
|
||||
Returns the font for tab label text.
|
||||
*/
|
||||
- (CPFont)font
|
||||
{
|
||||
return _font;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the font for tab label text to font.
|
||||
*/
|
||||
- (void)setFont:(CPFont)font
|
||||
{
|
||||
if ([_font isEqual:font])
|
||||
return;
|
||||
|
||||
_font = font;
|
||||
[_tabs setFont:_font];
|
||||
}
|
||||
|
||||
//
|
||||
/*!
|
||||
Sets the tab view type.
|
||||
@@ -415,6 +437,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
var CPTabViewItemsKey = "CPTabViewItemsKey",
|
||||
CPTabViewSelectedItemKey = "CPTabViewSelectedItemKey",
|
||||
CPTabViewTypeKey = "CPTabViewTypeKey",
|
||||
CPTabViewFontKey = "CPTabViewFontKey",
|
||||
CPTabViewDelegateKey = "CPTabViewDelegateKey";
|
||||
|
||||
@implementation CPTabView (CPCoding)
|
||||
@@ -425,12 +448,16 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
|
||||
{
|
||||
[self _init];
|
||||
|
||||
_font = [aCoder decodeObjectForKey:CPTabViewFontKey];
|
||||
[_tabs setFont:_font];
|
||||
|
||||
_items = [aCoder decodeObjectForKey:CPTabViewItemsKey];
|
||||
|
||||
[self _updateItems];
|
||||
[self _repositionTabs];
|
||||
|
||||
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
|
||||
|
||||
if (selected)
|
||||
[self selectTabViewItem:selected];
|
||||
|
||||
@@ -450,6 +477,7 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
|
||||
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey];
|
||||
|
||||
[aCoder encodeInt:_type forKey:CPTabViewTypeKey];
|
||||
[aCoder encodeObject:_font forKey:CPTabViewFontKey];
|
||||
|
||||
[aCoder encodeConditionalObject:_delegate forKey:CPTabViewDelegateKey];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
var OS = require("os");
|
||||
|
||||
exports.fontinfo = function(name, size)
|
||||
{
|
||||
var p = OS.popen(["fontinfo", "-n", name, size || 12]);
|
||||
|
||||
if (p.wait() === 0)
|
||||
return JSON.parse(p.stdout.read());
|
||||
else
|
||||
return null;
|
||||
}
|
||||
@@ -166,16 +166,11 @@ var stream;
|
||||
|
||||
GLOBAL(CPLogColorize) = function(aString, aLevel)
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
// Try to determine if a colorizing stanza is already open, they can't be nested
|
||||
if (/^.*\x00\w+\([^\x00]*$/.test(aString))
|
||||
return aString;
|
||||
else
|
||||
return "\0" + (levelColorMap[aLevel] || "info") + "(" + aString + "\0)";
|
||||
}
|
||||
else
|
||||
// Try to determine if a colorizing stanza is already open, they can't be nested
|
||||
if (/^.*\x00\w+\([^\x00]*$/.test(aString))
|
||||
return aString;
|
||||
else
|
||||
return "\0" + (levelColorMap[aLevel] || "info") + "(" + aString + "\0)";
|
||||
}
|
||||
|
||||
GLOBAL(CPLogPrint) = function(aString, aLevel, aTitle, aFormatter)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
CPFont _systemFont;
|
||||
CPFont _boldSystemFont;
|
||||
|
||||
|
||||
CPFont _customFont;
|
||||
CPFont _boldCustomFont;
|
||||
}
|
||||
@@ -13,29 +13,33 @@
|
||||
{
|
||||
_systemFont = [CPFont systemFontOfSize:15];
|
||||
_boldSystemFont = [CPFont boldSystemFontOfSize:15];
|
||||
|
||||
|
||||
_customFont = [CPFont fontWithName:@"Marker Felt, Lucida Grande, Helvetica" size:30];
|
||||
_boldCustomFont = [CPFont boldFontWithName:@"Helvetica" size:30];
|
||||
}
|
||||
|
||||
- (void)testSystemFontCSSString
|
||||
{
|
||||
[self assert:[_systemFont cssString] equals:@"15px Arial, sans-serif"];
|
||||
var font = _CPFontConcatNameWithFallback([CPFont systemFontFace]);
|
||||
|
||||
[self assert:[_systemFont cssString] equals:@"15px " + font];
|
||||
}
|
||||
|
||||
- (void)testBoldSystemFontCSSString
|
||||
{
|
||||
[self assert:[_boldSystemFont cssString] equals:@"bold 15px Arial, sans-serif"];
|
||||
var font = _CPFontConcatNameWithFallback([CPFont systemFontFace]);
|
||||
|
||||
[self assert:[_boldSystemFont cssString] equals:@"bold 15px " + font];
|
||||
}
|
||||
|
||||
- (void)testCustomFontCSSString
|
||||
{
|
||||
[self assert:[_customFont cssString] equals:@"30px \"Marker Felt\", \"Lucida Grande\", \"Helvetica\", Arial, sans-serif"];
|
||||
[self assert:[_customFont cssString] equals:@"30px \"Marker Felt\", \"Lucida Grande\", Helvetica, Arial, sans-serif"];
|
||||
}
|
||||
|
||||
- (void)testBoldCustomFontCSSString
|
||||
{
|
||||
[self assert:[_boldCustomFont cssString] equals:@"bold 30px \"Helvetica\", Arial, sans-serif"];
|
||||
[self assert:[_boldCustomFont cssString] equals:@"bold 30px Helvetica, Arial, sans-serif"];
|
||||
}
|
||||
|
||||
- (void)testIsEqual
|
||||
@@ -48,3 +52,39 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var _CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
|
||||
|
||||
var _CPFontConcatNameWithFallback = function(aName)
|
||||
{
|
||||
var names = _CPFontNormalizedNameArray(aName),
|
||||
fallbackFaces = ["Arial", "sans-serif"];
|
||||
|
||||
// Remove the fallback names used in the names passed in
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
{
|
||||
for (var j = 0; j < fallbackFaces.length; ++j)
|
||||
{
|
||||
if (names[i].toLowerCase() === fallbackFaces[j].toLowerCase())
|
||||
{
|
||||
fallbackFaces.splice(j, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (names[i].indexOf(" ") > 0)
|
||||
names[i] = '"' + names[i] + '"';
|
||||
}
|
||||
|
||||
return names.concat(fallbackFaces).join(", ");
|
||||
};
|
||||
|
||||
var _CPFontNormalizedNameArray = function(aName)
|
||||
{
|
||||
var names = aName.split(",");
|
||||
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
names[i] = names[i].replace(_CPFontStripRegExp, "");
|
||||
|
||||
return names;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* AppController.j
|
||||
* test
|
||||
*
|
||||
* Created by aparajita on March 9, 2011.
|
||||
* Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
|
||||
var fontLabelField = nil,
|
||||
defaultFontLabelText = @"";
|
||||
|
||||
|
||||
@implementation AppController : CPObject
|
||||
{
|
||||
CPWindow theWindow; //this "outlet" is connected automatically by the Cib
|
||||
CPTextField label1;
|
||||
CPTextField fontLabel;
|
||||
CPTableView theTableView;
|
||||
CPRadio radio1;
|
||||
CPRadio radio2;
|
||||
}
|
||||
|
||||
- (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:NO];
|
||||
|
||||
fontLabelField = fontLabel;
|
||||
defaultFontLabelText = [fontLabelField stringValue];
|
||||
|
||||
var font = [CPFont fontWithName:@"Palatino, Cambria" size:14];
|
||||
|
||||
[radio1 setFont:font];
|
||||
[radio2 setFont:font];
|
||||
}
|
||||
|
||||
- (int)numberOfRowsInTableView:(id)aTableView
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
- (id)tableView:(id)tableView objectValueForTableColumn:(CPTableColumn)aColumn row:(int)aRow
|
||||
{
|
||||
return ["one", "two", "three"][parseInt([aColumn identifier], 10)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPView (testApp)
|
||||
|
||||
- (void)doMouseEntered
|
||||
{
|
||||
[fontLabelField setStringValue:@"View font: " + [[self font] cssString]];
|
||||
}
|
||||
|
||||
- (void)doMouseExited
|
||||
{
|
||||
[fontLabelField setStringValue:defaultFontLabelText];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPControl (testApp)
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
[super awakeFromCib];
|
||||
|
||||
var size = [self frameSize],
|
||||
lineHeight = [[self font] defaultLineHeightForFont],
|
||||
inset = [self hasThemeAttribute:@"content-inset"] ? [self currentValueForThemeAttribute:@"content-inset"] : nil,
|
||||
minSize = [self hasThemeAttribute:@"min-size"] ? [self currentValueForThemeAttribute:@"min-size"] : nil,
|
||||
height = lineHeight + (inset ? inset.top + inset.bottom : 0);
|
||||
|
||||
if (minSize)
|
||||
height = MAX(height, minSize.height);
|
||||
|
||||
[self setFrameSize:CGSizeMake(size.width, MAX(size.height, height))];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
[self doMouseEntered];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
[self doMouseExited];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPTabView (testApp)
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
[_tabs doMouseEntered];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
[_tabs doMouseExited];
|
||||
}
|
||||
|
||||
@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>FontEnhancementTest</string>
|
||||
<key>CPSystemFontFace</key>
|
||||
<string>Lucida Grande</string>
|
||||
<key>CPSystemFontSize</key>
|
||||
<string>12</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Jakefile
|
||||
* test
|
||||
*
|
||||
* Created by aparajita on March 9, 2011.
|
||||
* Copyright 2011, Victory-Heart Productions 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");
|
||||
|
||||
app ("test", function(task)
|
||||
{
|
||||
task.setBuildIntermediatesPath(FILE.join("Build", "test.build", configuration));
|
||||
task.setBuildPath(FILE.join("Build", configuration));
|
||||
|
||||
task.setProductName("test");
|
||||
task.setIdentifier("com.aparajitaworld.test");
|
||||
task.setVersion("1.0");
|
||||
task.setAuthor("Victory-Heart Productions");
|
||||
task.setEmail("feedback @nospam@ yourcompany.com");
|
||||
task.setSummary("test");
|
||||
task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
|
||||
task.setResources(new FileList("Resources/**"));
|
||||
task.setIndexFilePath("index.html");
|
||||
task.setInfoPlistPath("Info.plist");
|
||||
task.setNib2CibFlags("-R Resources/");
|
||||
|
||||
if (configuration === "Debug")
|
||||
task.setCompilerFlags("-DDEBUG -g");
|
||||
else
|
||||
task.setCompilerFlags("-O");
|
||||
});
|
||||
|
||||
task ("default", ["test"], function()
|
||||
{
|
||||
printResults(configuration);
|
||||
});
|
||||
|
||||
task ("build", ["default"]);
|
||||
|
||||
task ("debug", function()
|
||||
{
|
||||
ENV["CONFIGURATION"] = "Debug";
|
||||
JAKE.subjake(["."], "build", ENV);
|
||||
});
|
||||
|
||||
task ("release", function()
|
||||
{
|
||||
ENV["CONFIGURATION"] = "Release";
|
||||
JAKE.subjake(["."], "build", ENV);
|
||||
});
|
||||
|
||||
task ("run", ["debug"], function()
|
||||
{
|
||||
OS.system(["open", FILE.join("Build", "Debug", "test", "index.html")]);
|
||||
});
|
||||
|
||||
task ("run-release", ["release"], function()
|
||||
{
|
||||
OS.system(["open", FILE.join("Build", "Release", "test", "index.html")]);
|
||||
});
|
||||
|
||||
task ("deploy", ["release"], function()
|
||||
{
|
||||
FILE.mkdirs(FILE.join("Build", "Deployment", "test"));
|
||||
OS.system(["press", "-f", FILE.join("Build", "Release", "test"), FILE.join("Build", "Deployment", "test")]);
|
||||
printResults("Deployment")
|
||||
});
|
||||
|
||||
task ("desktop", ["release"], function()
|
||||
{
|
||||
FILE.mkdirs(FILE.join("Build", "Desktop", "test"));
|
||||
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "test"), FILE.join("Build", "Desktop", "test", "test.app"));
|
||||
printResults("Desktop")
|
||||
});
|
||||
|
||||
task ("run-desktop", ["desktop"], function()
|
||||
{
|
||||
OS.system([FILE.join("Build", "Desktop", "test", "test.app", "Contents", "MacOS", "NativeHost"), "-i"]);
|
||||
});
|
||||
|
||||
function printResults(configuration)
|
||||
{
|
||||
print("----------------------------");
|
||||
print(configuration+" app built at path: "+FILE.join("Build", configuration, "test"));
|
||||
print("----------------------------");
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!--
|
||||
index-debug.html
|
||||
test
|
||||
|
||||
Created by aparajita on March 9, 2011.
|
||||
Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1" />
|
||||
|
||||
<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" />
|
||||
<link href='http://fonts.googleapis.com/css?family=Ubuntu,Cabin' rel='stylesheet' type='text/css' />
|
||||
|
||||
<title>FontEnhancementTest</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
OBJJ_MAIN_FILE = "main.j";
|
||||
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks"];
|
||||
</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:
|
||||
|
||||
// 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);
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
body{margin:0; padding:0;}
|
||||
#container {position: absolute; top:50%; left:50%;}
|
||||
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
|
||||
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
|
||||
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
|
||||
</style>
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<STYLE type="text/css">
|
||||
#container { position: relative; top: 50%; }
|
||||
#content { position: relative;}
|
||||
</STYLE>
|
||||
<![endif]-->
|
||||
|
||||
</head>
|
||||
|
||||
<body style="">
|
||||
<div id="cappuccino-body">
|
||||
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
|
||||
<script type="text/javascript">
|
||||
document.write("<div id='container'><p id='content'>" +
|
||||
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
|
||||
"Loading test...</p></div>");
|
||||
</script>
|
||||
|
||||
<noscript>
|
||||
<div id="container">
|
||||
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
|
||||
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
|
||||
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
|
||||
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
|
||||
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
|
||||
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
|
||||
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
|
||||
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
|
||||
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
|
||||
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!--
|
||||
index.html
|
||||
test
|
||||
|
||||
Created by aparajita on March 9, 2011.
|
||||
Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1" />
|
||||
|
||||
<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" />
|
||||
<link href='http://fonts.googleapis.com/css?family=Ubuntu,Cabin' rel='stylesheet' type='text/css' />
|
||||
|
||||
<title>FontEnhancementTest</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
OBJJ_MAIN_FILE = "main.j";
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body{margin:0; padding:0;}
|
||||
#container {position: absolute; top:50%; left:50%;}
|
||||
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
|
||||
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
|
||||
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
|
||||
</style>
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<STYLE type="text/css">
|
||||
#container { position: relative; top: 50%; }
|
||||
#content { position: relative;}
|
||||
</STYLE>
|
||||
<![endif]-->
|
||||
|
||||
</head>
|
||||
|
||||
<body style="">
|
||||
<div id="cappuccino-body">
|
||||
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
|
||||
<script type="text/javascript">
|
||||
document.write("<div id='container'><p id='content'>" +
|
||||
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
|
||||
"Loading test...</p></div>");
|
||||
</script>
|
||||
|
||||
<noscript>
|
||||
<div id="container">
|
||||
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
|
||||
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
|
||||
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
|
||||
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
|
||||
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
|
||||
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
|
||||
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
|
||||
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
|
||||
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
|
||||
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* AppController.j
|
||||
* test
|
||||
*
|
||||
* Created by aparajita on March 9, 2011.
|
||||
* Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
@import "AppController.j"
|
||||
|
||||
|
||||
function main(args, namedArgs)
|
||||
{
|
||||
CPApplicationMain(args, namedArgs);
|
||||
}
|
||||
+4
-2
@@ -1,5 +1,7 @@
|
||||
|
||||
require("../common.jake");
|
||||
|
||||
// nib2cib has to come before capp since capp uses nib2cib
|
||||
subtasks(["nib2cib", "capp", "NativeHost"], ["build"/*, "clean", "clobber"*/]);
|
||||
// nib2cib uses fontinfo and capp uses nib2cib
|
||||
subtasks(["fontinfo", "nib2cib", "capp", "NativeHost"], ["build"/*, "clean", "clobber"*/]);
|
||||
|
||||
subtasks(["fontinfo"], ["clean", "clobber"]);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
build/
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
require ("../../common.jake");
|
||||
|
||||
var OS = require("os"),
|
||||
task = require("jake").task;
|
||||
|
||||
task ("build", function()
|
||||
{
|
||||
if (executableExists("xcodebuild"))
|
||||
{
|
||||
var args = "-alltargets -configuration " + $CONFIGURATION;
|
||||
|
||||
if (FILE.exists(FILE.join("/", "Developer", "SDKs", "MacOSX10.5.sdk")))
|
||||
args = "-sdk macosx10.5 " + args;
|
||||
|
||||
else
|
||||
args = "-sdk macosx " + args;
|
||||
|
||||
if (OS.system("xcodebuild " + args))
|
||||
OS.exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
print("Building fontinfo requires Xcode.");
|
||||
}
|
||||
});
|
||||
|
||||
task ("clean", function()
|
||||
{
|
||||
if (OS.system("xcodebuild clean"))
|
||||
OS.exit(1);
|
||||
});
|
||||
|
||||
task ("clobber", function()
|
||||
{
|
||||
if (OS.system("xcodebuild clean"))
|
||||
OS.exit(1);
|
||||
});
|
||||
|
||||
task ("default", ["build"]);
|
||||
@@ -0,0 +1,51 @@
|
||||
NAME
|
||||
fontinfo -- retrieve information about a font
|
||||
|
||||
SYNOPSIS
|
||||
fontinfo [-n] font [size [string]]
|
||||
|
||||
DESCRIPTION
|
||||
fontinfo is a tiny utility that returns information about a font.
|
||||
The font name must be a full PostScript name, not a display name. So you would use something
|
||||
like "LucidaGrande-Bold", not "Lucida Grande Bold". The size can be any floating point number
|
||||
greater than zero. If no size is given, it defaults to 12.
|
||||
|
||||
If the -n option is passed, the output will not be terminated with a linefeed.
|
||||
|
||||
If the string argument is passed, its width in the given font is measured and returned.
|
||||
|
||||
EXIT STATUS
|
||||
fontinfo exits with a return status of zero if there are no errors.
|
||||
fontinfo exits with a return status of 1 if any arguments are invalid, or a status of 2 if the font
|
||||
cannot be found.
|
||||
|
||||
OUTPUT
|
||||
fontinfo outputs a stringified JSON object with the following structure:
|
||||
|
||||
{
|
||||
familyName:<string>,
|
||||
bold:<boolean>,
|
||||
italic:<boolean>,
|
||||
ascender:<float>,
|
||||
descender:<float>,
|
||||
line-height:<float>
|
||||
width:<float>
|
||||
}
|
||||
|
||||
If -n is not passed, the JSON is terminated with a linefeed. The fields of the object are as follows:
|
||||
|
||||
familyName: The display name of the font's family
|
||||
bold: Whether the font's stylistic traits are considered bold
|
||||
italic: Whether the font's stylistic traits are considered italic
|
||||
ascender: The offset from the baseline in points (not pixels!) of the longest ascender of the given font at
|
||||
the given size.
|
||||
descender: The negative offset from the baseline in points (not pixels!)
|
||||
of the longest descender of the given font at the given size.
|
||||
lineHeight: The height in points (not pixels!) of the largest glyph in the given font at the given size.
|
||||
Note that glyphs include diacritical marks that may appear above and below the largest ascender
|
||||
and descender, so the line height will almost always be greater than ascender + descender.
|
||||
width: If a string is passed, the width in pixels of the string in the given font, otherwise zero
|
||||
|
||||
AUTHORS
|
||||
Aparajita Fishman, Victory-Heart Productions
|
||||
http://www.aparajita.com
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
font_info
|
||||
|
||||
Copyright 2010 Aparajita Fishman
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#define resultFormat @"{\"familyName\":\"%@\", \"bold\":%@, \"italic\":%@, \"ascender\":%g, \"descender\":%g, \"lineHeight\":%g, \"width\":%g}"
|
||||
|
||||
enum {
|
||||
kErrInvalidArguments = 1,
|
||||
kErrInvalidFontName
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||
int exitCode = 0;
|
||||
NSString* stringToMeasure = nil;
|
||||
|
||||
// usage: fontinfo [-n] face [size [string]]
|
||||
|
||||
if (argc >= 2)
|
||||
{
|
||||
BOOL appendLineFeed = YES;
|
||||
int nextArgument = 1;
|
||||
|
||||
if (argv[1][0] == '-')
|
||||
{
|
||||
if (argv[1][1] == 'n')
|
||||
{
|
||||
appendLineFeed = NO;
|
||||
++nextArgument;
|
||||
}
|
||||
else
|
||||
exitCode = kErrInvalidArguments;
|
||||
}
|
||||
|
||||
if (exitCode == 0)
|
||||
{
|
||||
CGFloat fontSize = 12;
|
||||
|
||||
NSString* fontName = [NSString stringWithUTF8String:argv[nextArgument++]];
|
||||
|
||||
if (argc > nextArgument)
|
||||
fontSize = atof(argv[nextArgument++]);
|
||||
|
||||
if (fontSize > 0.0)
|
||||
{
|
||||
NSFont* font = [NSFont fontWithName:fontName size:fontSize];
|
||||
|
||||
if (font)
|
||||
{
|
||||
if (argc > nextArgument)
|
||||
stringToMeasure = [NSString stringWithUTF8String:argv[nextArgument]];
|
||||
|
||||
NSString* familyName = [font familyName];
|
||||
NSFontDescriptor* descriptor = [font fontDescriptor];
|
||||
NSFontSymbolicTraits traits = [descriptor symbolicTraits];
|
||||
BOOL isBold = traits & NSFontBoldTrait;
|
||||
BOOL isItalic = traits & NSFontItalicTrait;
|
||||
CGFloat ascender = [font ascender];
|
||||
CGFloat descender = [font descender];
|
||||
|
||||
NSLayoutManager* layout = [NSLayoutManager new];
|
||||
CGFloat lineHeight = [layout defaultLineHeightForFont:font];
|
||||
[layout release];
|
||||
|
||||
CGFloat width = 0.0;
|
||||
|
||||
if (stringToMeasure)
|
||||
{
|
||||
NSDictionary* attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
|
||||
NSAttributedString* attrString = [[NSAttributedString alloc] initWithString:stringToMeasure attributes:attributes];
|
||||
|
||||
if (attrString)
|
||||
width = [attrString size].width;
|
||||
|
||||
[attrString release];
|
||||
}
|
||||
|
||||
NSMutableString* result = [NSMutableString stringWithFormat:resultFormat,
|
||||
familyName,
|
||||
isBold ? @"true" : @"false", isItalic ? @"true" : @"false",
|
||||
ascender, descender, lineHeight,
|
||||
width];
|
||||
|
||||
if (appendLineFeed)
|
||||
[result appendString:@"\n"];
|
||||
|
||||
printf("%s", [result UTF8String]);
|
||||
}
|
||||
else
|
||||
{
|
||||
exitCode = kErrInvalidFontName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exitCode = kErrInvalidArguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exitCode = kErrInvalidArguments;
|
||||
}
|
||||
|
||||
[pool drain];
|
||||
return exitCode;
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 45;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
E1C392BC133D513B0092D7CA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1C392BB133D513B0092D7CA /* Cocoa.framework */; };
|
||||
E1D3CFAA12AFFB7F00CBB79E /* fontinfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* fontinfo.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
08FB7796FE84155DC02AAC07 /* fontinfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fontinfo.m; sourceTree = "<group>"; };
|
||||
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
|
||||
32A70AAB03705E1F00C91783 /* fontinfo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fontinfo_Prefix.pch; sourceTree = "<group>"; };
|
||||
E11C89CC1277CECE0012609B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
E18587D81279B93100FB6A47 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
E1C392BB133D513B0092D7CA /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
E1E20D0B12B09283005A6A64 /* fontinfo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fontinfo; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
E1D3CF6912AFEE3800CBB79E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E1C392BC133D513B0092D7CA /* Cocoa.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
08FB7794FE84155DC02AAC07 /* font_info */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
08FB7795FE84155DC02AAC07 /* Source */,
|
||||
E18587DD1279B93600FB6A47 /* Documentation */,
|
||||
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */,
|
||||
);
|
||||
name = font_info;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
08FB7795FE84155DC02AAC07 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
32A70AAB03705E1F00C91783 /* fontinfo_Prefix.pch */,
|
||||
08FB7796FE84155DC02AAC07 /* fontinfo.m */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
08FB779EFE84155DC02AAC07 /* Foundation.framework */,
|
||||
E11C89CC1277CECE0012609B /* AppKit.framework */,
|
||||
E1C392BB133D513B0092D7CA /* Cocoa.framework */,
|
||||
);
|
||||
name = "External Frameworks and Libraries";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E1E20D0B12B09283005A6A64 /* fontinfo */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E18587DD1279B93600FB6A47 /* Documentation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E18587D81279B93100FB6A47 /* README */,
|
||||
);
|
||||
name = Documentation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
E1D3CF6A12AFEE3800CBB79E /* fontinfo */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E1D3CF6F12AFEE3B00CBB79E /* Build configuration list for PBXNativeTarget "fontinfo" */;
|
||||
buildPhases = (
|
||||
E1D3CF6812AFEE3800CBB79E /* Sources */,
|
||||
E1D3CF6912AFEE3800CBB79E /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = fontinfo;
|
||||
productName = font_info;
|
||||
productReference = E1E20D0B12B09283005A6A64 /* fontinfo */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "fontinfo" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
Japanese,
|
||||
French,
|
||||
German,
|
||||
);
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* font_info */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
E1D3CF6A12AFEE3800CBB79E /* fontinfo */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
E1D3CF6812AFEE3800CBB79E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E1D3CFAA12AFFB7F00CBB79E /* fontinfo.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
1DEB927908733DD40010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
|
||||
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
|
||||
CONFIGURATION_TEMP_DIR = "$(CAPP_BUILD)";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = fontinfo_Prefix.pch;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
OBJROOT = "$(CAPP_BUILD)";
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
Foundation,
|
||||
"-framework",
|
||||
AppKit,
|
||||
);
|
||||
PREBINDING = NO;
|
||||
PRODUCT_NAME = fontinfo;
|
||||
SDKROOT = macosx10.5;
|
||||
SYMROOT = "$(CAPP_BUILD)/Debug/CommonJS/cappuccino/bin";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB927A08733DD40010E9CD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
|
||||
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
|
||||
CONFIGURATION_TEMP_DIR = "$(CAPP_BUILD)";
|
||||
DEPLOYMENT_LOCATION = NO;
|
||||
DEPLOYMENT_POSTPROCESSING = NO;
|
||||
DSTROOT = "/tmp/$(PROJECT_NAME).dst";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INSTALL_PATH = "";
|
||||
OBJROOT = "$(CAPP_BUILD)";
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PREBINDING = NO;
|
||||
PRODUCT_NAME = fontinfo;
|
||||
SDKROOT = macosx10.5;
|
||||
SYMROOT = "$(CAPP_BUILD)/Release/CommonJS/cappuccino/bin";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E1D3CF6D12AFEE3900CBB79E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E1D3CF6E12AFEE3900CBB79E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.5;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "fontinfo" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1DEB927908733DD40010E9CD /* Debug */,
|
||||
1DEB927A08733DD40010E9CD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E1D3CF6F12AFEE3B00CBB79E /* Build configuration list for PBXNativeTarget "fontinfo" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E1D3CF6D12AFEE3900CBB79E /* Debug */,
|
||||
E1D3CF6E12AFEE3900CBB79E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:fontinfo.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// Prefix header for all source files of the 'font_info' target in the 'font_info' project.
|
||||
//
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
@@ -23,25 +23,25 @@
|
||||
|
||||
@import "Converter.j"
|
||||
|
||||
|
||||
@implementation Converter (Mac)
|
||||
|
||||
- (void)convertedDataFromMacData:(CPData)data resourcesPath:(CPString)aResourcesPath
|
||||
{
|
||||
// Unarchive the NS data
|
||||
var unarchiver = [[Nib2CibKeyedUnarchiver alloc] initForReadingWithData:data resourcesPath:aResourcesPath],
|
||||
objectData = [unarchiver decodeObjectForKey:@"IB.objectdata"];
|
||||
|
||||
// Perform a bit of post-processing on views since all CP views are flipped.
|
||||
// It's better to do this here (instead of say, in NSView::initWithCoder:),
|
||||
// because at this point all the objects an mappings are stabilized.
|
||||
var objects = [unarchiver allObjects],
|
||||
objectData = [unarchiver decodeObjectForKey:@"IB.objectdata"],
|
||||
objects = [unarchiver allObjects],
|
||||
count = [objects count];
|
||||
|
||||
// Perform a bit of post-processing on fonts and views since all CP views are flipped.
|
||||
// It's better to do this here (instead of say, in NSView::initWithCoder:),
|
||||
// because at this point all the objects and mappings are stabilized.
|
||||
while (count--)
|
||||
{
|
||||
var object = objects[count];
|
||||
|
||||
[self replaceFontForObject:object];
|
||||
|
||||
if (![object isKindOfClass:[CPView class]])
|
||||
continue;
|
||||
|
||||
@@ -76,20 +76,82 @@
|
||||
var convertedData = [CPData data],
|
||||
archiver = [[CPKeyedArchiver alloc] initForWritingWithMutableData:convertedData];
|
||||
|
||||
[archiver setDelegate:self];
|
||||
[archiver encodeObject:objectData forKey:@"CPCibObjectDataKey"];
|
||||
[archiver finishEncoding];
|
||||
|
||||
return convertedData;
|
||||
}
|
||||
|
||||
// For some reason, occasionally an attempt is made to archive NSMatrix. That will fail, so prevent it here.
|
||||
- (id)archiver:(CPKeyedArchiver)archiver willEncodeObject:(id)object
|
||||
- (void)replaceFontForObject:(id)object
|
||||
{
|
||||
if ([object isKindOfClass:[NSMatrix class]])
|
||||
return nil;
|
||||
if ([object respondsToSelector:@selector(font)] &&
|
||||
[object respondsToSelector:@selector(setFont:)])
|
||||
{
|
||||
var nibFont = [object font];
|
||||
|
||||
if (nibFont)
|
||||
[self replaceFont:nibFont forObject:object];
|
||||
}
|
||||
else if ([object isKindOfClass:[CPView class]])
|
||||
{
|
||||
/*
|
||||
Determine if a view is actually a container for radio buttons.
|
||||
They have to be manually iterated over because they are not
|
||||
part of the top level object data.
|
||||
*/
|
||||
var subviews = [object subviews],
|
||||
count = [subviews count];
|
||||
|
||||
if (count && [subviews[0] isKindOfClass:[CPRadio class]])
|
||||
{
|
||||
while (count--)
|
||||
{
|
||||
var radio = subviews[count];
|
||||
|
||||
[self replaceFont:[radio font] forObject:radio];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)replaceFont:(CPFont)nibFont forObject:(id)object
|
||||
{
|
||||
var cibFont = nil;
|
||||
|
||||
if ([object respondsToSelector:@selector(cibFontForNibFont)])
|
||||
cibFont = [object cibFontForNibFont];
|
||||
else
|
||||
return object;
|
||||
cibFont = [NSFont cibFontForNibFont:[object font]];
|
||||
|
||||
if (!cibFont || ![cibFont isEqual:nibFont])
|
||||
{
|
||||
var source = "";
|
||||
|
||||
// nil cibFont means try to use theme font
|
||||
if (!cibFont)
|
||||
{
|
||||
var bold = [nibFont isBold];
|
||||
|
||||
cibFont = [theme valueForAttributeWithName:@"font" inState:[object themeState] forClass:[object class]];
|
||||
|
||||
// Substitute legacy theme fonts for the current system font
|
||||
if (!cibFont || [cibFont familyName] === CPFontDefaultSystemFontFace)
|
||||
{
|
||||
var size = [cibFont size] || CPFontDefaultSystemFontSize,
|
||||
bold = cibFont ? [cibFont isBold] : bold;
|
||||
|
||||
if (size === CPFontDefaultSystemFontSize)
|
||||
size = [CPFont systemFontSize];
|
||||
|
||||
cibFont = bold ? [CPFont boldSystemFontOfSize:size] : [CPFont systemFontOfSize:size];
|
||||
source = " (from theme)"
|
||||
}
|
||||
}
|
||||
|
||||
[object setFont:cibFont];
|
||||
|
||||
CPLog.debug("%s: substituted <%s>%s for <%fpx %s>", [object className], cibFont ? [cibFont cssString] : "theme default", source, [nibFont size], [nibFont familyName]);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+98
-69
@@ -18,113 +18,142 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <Foundation/CPData.j>
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
@import <BlendKit/BlendKit.j>
|
||||
|
||||
var FILE = require("file"),
|
||||
OS = require("os");
|
||||
OS = require("os"),
|
||||
|
||||
SharedConverter = nil;
|
||||
|
||||
NibFormatUndetermined = 0,
|
||||
NibFormatMac = 1,
|
||||
NibFormatIPhone = 2;
|
||||
NibFormatUndetermined = 0,
|
||||
NibFormatMac = 1,
|
||||
NibFormatIPhone = 2;
|
||||
|
||||
ConverterConversionException = @"ConverterConversionException";
|
||||
ConverterModeLegacy = 0;
|
||||
ConverterModeNew = 1;
|
||||
|
||||
ConverterConversionException = @"ConverterConversionException";
|
||||
|
||||
@implementation Converter : CPObject
|
||||
{
|
||||
NibFormat format @accessors;
|
||||
CPString inputPath @accessors;
|
||||
CPString outputPath @accessors;
|
||||
CPString resourcesPath @accessors;
|
||||
CPString inputPath @accessors(readonly);
|
||||
CPString outputPath @accessors;
|
||||
CPString resourcesPath @accessors;
|
||||
NibFormat format @accessors(readonly);
|
||||
CPTheme theme @accessors(readonly);
|
||||
}
|
||||
|
||||
- (id)init
|
||||
+ (Converter)sharedConverter
|
||||
{
|
||||
if (!SharedConverter)
|
||||
SharedConverter = [[Converter alloc] init];
|
||||
|
||||
return SharedConverter;
|
||||
}
|
||||
|
||||
- (id)initWithInputPath:(CPString)aPath format:(NibFormat)nibFormat theme:(CPTheme)aTheme
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
[self setFormat:NibFormatUndetermined];
|
||||
{
|
||||
inputPath = aPath;
|
||||
format = nibFormat;
|
||||
theme = aTheme;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)convert
|
||||
{
|
||||
try
|
||||
if ([resourcesPath length] && !FILE.isReadable(resourcesPath))
|
||||
[CPException raise:ConverterConversionException reason:@"Could not read Resources at path \"" + resourcesPath + "\""];
|
||||
|
||||
var inferredFormat = format;
|
||||
|
||||
if (inferredFormat === NibFormatUndetermined)
|
||||
{
|
||||
if ([resourcesPath length] && !FILE.isReadable(resourcesPath))
|
||||
[CPException raise:ConverterConversionException reason:@"Could not read Resources at path \"" + resourcesPath + "\""];
|
||||
// Assume its a Mac file.
|
||||
inferredFormat = NibFormatMac;
|
||||
|
||||
var inferredFormat = format;
|
||||
|
||||
if (inferredFormat === NibFormatUndetermined)
|
||||
{
|
||||
// Assume its a Mac file.
|
||||
inferredFormat = NibFormatMac;
|
||||
|
||||
// Some .xibs are iPhone nibs, check the actual contents in this case.
|
||||
if (FILE.extension(inputPath) !== ".nib" && FILE.isFile(inputPath) &&
|
||||
FILE.read(inputPath, { charset:"UTF-8" }).indexOf("<archive type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\"") !== -1)
|
||||
inferredFormat = NibFormatIPhone;
|
||||
|
||||
if (inferredFormat === NibFormatMac)
|
||||
CPLog.info("Auto-detected Cocoa Nib or Xib File");
|
||||
else
|
||||
CPLog.info("Auto-detected CocoaTouch Xib File");
|
||||
}
|
||||
|
||||
var nibData = [self CPCompliantNibDataAtFilePath:inputPath];
|
||||
// Some .xibs are iPhone nibs, check the actual contents in this case.
|
||||
if (FILE.extension(inputPath) !== ".nib" && FILE.isFile(inputPath) &&
|
||||
FILE.read(inputPath, { charset:"UTF-8" }).indexOf("<archive type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\"") !== -1)
|
||||
inferredFormat = NibFormatIPhone;
|
||||
|
||||
if (inferredFormat === NibFormatMac)
|
||||
var convertedData = [self convertedDataFromMacData:nibData resourcesPath:resourcesPath];
|
||||
CPLog.info("Auto-detected Cocoa Nib or Xib File");
|
||||
else
|
||||
[CPException raise:ConverterConversionException reason:@"nib2cib does not understand this nib format."];
|
||||
|
||||
if (![outputPath length])
|
||||
outputPath = inputPath.substr(0, inputPath.length - FILE.extension(inputPath).length) + ".cib";
|
||||
|
||||
FILE.write(outputPath, [convertedData rawString], { charset:"UTF-8" });
|
||||
}
|
||||
catch(anException)
|
||||
{
|
||||
CPLog.fatal(anException);
|
||||
CPLog.info("Auto-detected CocoaTouch Xib File");
|
||||
}
|
||||
|
||||
var nibData = [self CPCompliantNibDataAtFilePath:inputPath];
|
||||
|
||||
if (inferredFormat === NibFormatMac)
|
||||
var convertedData = [self convertedDataFromMacData:nibData resourcesPath:resourcesPath];
|
||||
else
|
||||
[CPException raise:ConverterConversionException reason:@"nib2cib does not understand this nib format."];
|
||||
|
||||
if (![outputPath length])
|
||||
outputPath = inputPath.substr(0, inputPath.length - FILE.extension(inputPath).length) + ".cib";
|
||||
|
||||
FILE.write(outputPath, [convertedData rawString], { charset:"UTF-8" });
|
||||
CPLog.info(CPLogColorize("Conversion successful", "warn"));
|
||||
}
|
||||
|
||||
- (CPData)CPCompliantNibDataAtFilePath:(CPString)aFilePath
|
||||
{
|
||||
// Compile xib or nib to make sure we have a non-new format nib.
|
||||
var temporaryNibFilePath = FILE.join("/tmp", FILE.basename(aFilePath) + ".tmp.nib");
|
||||
CPLog.info("Converting Xib file to plist...");
|
||||
|
||||
if (OS.popen(["/usr/bin/ibtool", aFilePath, "--compile", temporaryNibFilePath]).wait() === 1)
|
||||
throw "Could not compile file at " + aFilePath;
|
||||
var temporaryNibFilePath = "",
|
||||
temporaryPlistFilePath = "";
|
||||
|
||||
// Convert from binary plist to XML plist
|
||||
var temporaryPlistFilePath = FILE.join("/tmp", FILE.basename(aFilePath) + ".tmp.plist");
|
||||
try
|
||||
{
|
||||
// Compile xib or nib to make sure we have a non-new format nib.
|
||||
temporaryNibFilePath = FILE.join("/tmp", FILE.basename(aFilePath) + ".tmp.nib");
|
||||
|
||||
if (OS.popen(["/usr/bin/plutil", "-convert", "xml1", temporaryNibFilePath, "-o", temporaryPlistFilePath]).wait() === 1)
|
||||
throw "Could not convert to xml plist for file at " + aFilePath;
|
||||
if (OS.popen(["/usr/bin/ibtool", aFilePath, "--compile", temporaryNibFilePath]).wait() === 1)
|
||||
[CPException raise:ConverterConversionException reason:@"Could not compile file: " + aFilePath];
|
||||
|
||||
if (!FILE.isReadable(temporaryPlistFilePath))
|
||||
[CPException raise:ConverterConversionException reason:@"Unable to convert nib file."];
|
||||
// Convert from binary plist to XML plist
|
||||
var temporaryPlistFilePath = FILE.join("/tmp", FILE.basename(aFilePath) + ".tmp.plist");
|
||||
|
||||
var plistContents = FILE.read(temporaryPlistFilePath, { charset:"UTF-8" });
|
||||
if (OS.popen(["/usr/bin/plutil", "-convert", "xml1", temporaryNibFilePath, "-o", temporaryPlistFilePath]).wait() === 1)
|
||||
[CPException raise:ConverterConversionException reason:@"Could not convert to xml plist for file: " + aFilePath];
|
||||
|
||||
// Minor NS keyed archive to CP keyed archive conversion.
|
||||
// Use Java directly because rhino's string.replace is *so slow*. 4 seconds vs. 1 millisecond.
|
||||
// plistContents = plistContents.replace(/\<key\>\s*CF\$UID\s*\<\/key\>/g, "<key>CP$UID</key>");
|
||||
if (system.engine === "rhino")
|
||||
plistContents = String(java.lang.String(plistContents).replaceAll("\\<key\\>\\s*CF\\$UID\\s*\\<\/key\\>", "<key>CP\\$UID</key>"));
|
||||
else
|
||||
plistContents = plistContents.replace(/\<key\>\s*CF\$UID\s*\<\/key\>/g, "<key>CP$UID</key>");
|
||||
if (!FILE.isReadable(temporaryPlistFilePath))
|
||||
[CPException raise:ConverterConversionException reason:@"Unable to convert nib file."];
|
||||
|
||||
plistContents = plistContents.replace(/<string>[\u0000-\u0008\u000B\u000C\u000E-\u001F]<\/string>/g, function(c) {
|
||||
CPLog.warn("Warning: Converting character 0x"+c.charCodeAt(8).toString(16)+" to base64 representation");
|
||||
return "<string type=\"base64\">"+CFData.encodeBase64String(c.charAt(8))+"</string>";
|
||||
});
|
||||
var plistContents = FILE.read(temporaryPlistFilePath, { charset:"UTF-8" });
|
||||
|
||||
// Minor NS keyed archive to CP keyed archive conversion.
|
||||
// Use Java directly because rhino's string.replace is *so slow*. 4 seconds vs. 1 millisecond.
|
||||
// plistContents = plistContents.replace(/\<key\>\s*CF\$UID\s*\<\/key\>/g, "<key>CP$UID</key>");
|
||||
if (system.engine === "rhino")
|
||||
plistContents = String(java.lang.String(plistContents).replaceAll("\\<key\\>\\s*CF\\$UID\\s*\\<\/key\\>", "<key>CP\\$UID</key>"));
|
||||
else
|
||||
plistContents = plistContents.replace(/\<key\>\s*CF\$UID\s*\<\/key\>/g, "<key>CP$UID</key>");
|
||||
|
||||
plistContents = plistContents.replace(/<string>[\u0000-\u0008\u000B\u000C\u000E-\u001F]<\/string>/g, function(c)
|
||||
{
|
||||
CPLog.warn("Warning: converting character 0x" + c.charCodeAt(8).toString(16) + " to base64 representation");
|
||||
return "<string type=\"base64\">"+CFData.encodeBase64String(c.charAt(8))+"</string>";
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (temporaryNibFilePath !== "" && FILE.isWritable(temporaryNibFilePath))
|
||||
FILE.remove(temporaryNibFilePath);
|
||||
|
||||
if (temporaryPlistFilePath !== "" && FILE.isWritable(temporaryPlistFilePath))
|
||||
FILE.remove(temporaryPlistFilePath);
|
||||
}
|
||||
|
||||
return [CPData dataWithRawString:plistContents];
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ function CP_NSMapClassName(aClassName)
|
||||
|
||||
if (CPClassFromString(mappedClassName))
|
||||
{
|
||||
CPLog.info("Mapping " + aClassName + " to " + mappedClassName);
|
||||
CPLog.debug("NSAppKit: mapping " + aClassName + " to " + mappedClassName);
|
||||
|
||||
return mappedClassName;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
|
||||
var _CPButtonBezelStyleHeights = {};
|
||||
|
||||
_CPButtonBezelStyleHeights[CPRoundedBezelStyle] = 18;
|
||||
_CPButtonBezelStyleHeights[CPTexturedRoundedBezelStyle] = 20;
|
||||
_CPButtonBezelStyleHeights[CPHUDBezelStyle] = 20;
|
||||
@@ -117,18 +118,18 @@ var NSButtonIsBorderedMask = 0x00800000,
|
||||
case CPHelpButtonBezelStyle:
|
||||
case CPCircularBezelStyle:
|
||||
case CPDisclosureBezelStyle:
|
||||
CPLog.warn("Unsupported bezel style: " + _bezelStyle);
|
||||
CPLog.warn("NSButton [%s]: unsupported bezel style: %d", _title == null ? "<no title>" : '"' + _title + '"', _bezelStyle);
|
||||
_bezelStyle = CPHUDBezelStyle;
|
||||
break;
|
||||
// error:
|
||||
default:
|
||||
CPLog.error("Unknown bezel style: " + _bezelStyle);
|
||||
CPLog.warn("NSButton [%s]: unknown bezel style: %d", _title == null ? "<no title>" : '"' + _title + '"', _bezelStyle);
|
||||
_bezelStyle = CPHUDBezelStyle;
|
||||
}
|
||||
|
||||
if ([cell isBordered])
|
||||
{
|
||||
CPLog.info("Adjusting CPButton height from " +_frame.size.height+ " / " + _bounds.size.height+" to " + CPButtonDefaultHeight);
|
||||
CPLog.debug("NSButton [%s]: adjusting height from %d to %d", _title == null ? "<no title>" : '"' + _title + '"', _frame.size.height, CPButtonDefaultHeight);
|
||||
_frame.size.height = CPButtonDefaultHeight;
|
||||
_frame.origin.y += 4.0;
|
||||
_bounds.size.height = CPButtonDefaultHeight;
|
||||
|
||||
@@ -119,7 +119,7 @@ var NSUnknownColorSpaceModel = -1,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CPLog(@"-[%@ %s] unknown color space %d", isa, _cmd, colorSpace);
|
||||
CPLog.warn(@"-[%@ %s] unknown color space %d", isa, _cmd, colorSpace);
|
||||
result = [CPColor blackColor];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ var FILE = require("file");
|
||||
var size = CGSizeMakeZero();
|
||||
|
||||
if (![[aCoder resourcesPath] length])
|
||||
CPLog.warn("*** WARNING: Resources found in nib, but no resources path specified with -R option.");
|
||||
CPLog.warn("Resources found in nib, but no resources path specified with -R option.");
|
||||
else
|
||||
{
|
||||
var resourcePath = [aCoder resourcePathForName:_resourceName];
|
||||
|
||||
if (!resourcePath)
|
||||
CPLog.warn("*** WARNING: Resource named " + _resourceName + " not found in supplied resources path.");
|
||||
CPLog.warn("Resource named " + _resourceName + " not found in the supplied resources path.");
|
||||
else
|
||||
size = imageSize(FILE.join(FILE.cwd(), resourcePath));
|
||||
|
||||
|
||||
+35
-14
@@ -22,35 +22,56 @@
|
||||
|
||||
@import <AppKit/CPFont.j>
|
||||
|
||||
var OS = require("os"),
|
||||
fontinfo = require("cappuccino/fontinfo").fontinfo;
|
||||
|
||||
var IBDefaultFontFace = @"Lucida Grande",
|
||||
IBDefaultFontSize = 13.0;
|
||||
|
||||
@implementation CPFont (NSCoding)
|
||||
|
||||
- (id)NS_initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
var isBold = NO,
|
||||
fontName = [aCoder decodeObjectForKey:@"NSName"],
|
||||
size = [aCoder decodeDoubleForKey:@"NSSize"];
|
||||
var name = [aCoder decodeObjectForKey:@"NSName"],
|
||||
size = [aCoder decodeDoubleForKey:@"NSSize"],
|
||||
isBold = false,
|
||||
isItalic = false,
|
||||
info = fontinfo(name, size);
|
||||
|
||||
if (fontName === "LucidaGrande" && size === 13)
|
||||
if (info)
|
||||
{
|
||||
CPLog.debug("Removing default IB font: <"+fontName+", "+size+"> for theme default font.");
|
||||
return nil;
|
||||
name = info.familyName;
|
||||
isBold = info.bold;
|
||||
isItalic = info.italic;
|
||||
}
|
||||
|
||||
// FIXME: Is this alwasy true?
|
||||
if (fontName.indexOf("-Bold") === fontName.length - "-Bold".length)
|
||||
isBold = YES;
|
||||
|
||||
if (fontName === "LucidaGrande" || fontName === "LucidaGrande-Bold")
|
||||
fontName = "Arial";
|
||||
|
||||
return [self _initWithName:fontName size:size bold:isBold];
|
||||
return [self _initWithName:name size:size bold:isBold italic:isItalic];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSFont : CPFont
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
CPLog.debug("NSFont: default IB font: %s %f", IBDefaultFontFace, IBDefaultFontSize);
|
||||
}
|
||||
|
||||
+ (id)cibFontForNibFont:(CPFont)aFont
|
||||
{
|
||||
var name = [aFont familyName];
|
||||
|
||||
if (name === IBDefaultFontFace)
|
||||
{
|
||||
var size = [aFont size];
|
||||
|
||||
if (size === IBDefaultFontSize)
|
||||
return nil;
|
||||
else
|
||||
return [[CPFont alloc] _initWithName:[CPFont systemFontFace] size:size bold:[aFont isBold] italic:[aFont isItalic]];
|
||||
}
|
||||
|
||||
return [aFont copy];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
|
||||
children.forEach(function(aChild)
|
||||
{
|
||||
CPLog.info("Promoted " + aChild + " to child of " + parent);
|
||||
CPLog.debug("NSIBObjectData: promoted " + aChild + " to child of " + parent);
|
||||
_objectsKeys.push(aChild);
|
||||
_objectsValues.push(parent);
|
||||
});
|
||||
|
||||
+90
-36
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
* NSMatrix.j
|
||||
* nib2cib
|
||||
*
|
||||
* Created by Francisco Tolmasky.
|
||||
* Copyright 2008, 280 North, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <AppKit/CPView.j>
|
||||
@@ -9,61 +30,94 @@ var NSMatrixRadioModeMask = 0x40000000,
|
||||
NSMatrixDrawsBackgroundMask = 0x01000000;
|
||||
|
||||
|
||||
@implementation NSMatrix : CPObject
|
||||
{
|
||||
}
|
||||
@implementation NSMatrix : CPView
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
var view = [[CPView alloc] NS_initWithCoder:aCoder];
|
||||
return [self NS_initWithCoder:aCoder];
|
||||
}
|
||||
|
||||
var numberOfRows = [aCoder decodeIntForKey:@"NSNumRows"],
|
||||
numberOfColumns = [aCoder decodeIntForKey:@"NSNumCols"],
|
||||
cellSize = [aCoder decodeSizeForKey:@"NSCellSize"],
|
||||
intercellSpacing = [aCoder decodeSizeForKey:@"NSIntercellSpacing"],
|
||||
flags = [aCoder decodeIntForKey:@"NSMatrixFlags"],
|
||||
isRadioMode = flags & NSMatrixRadioModeMask,
|
||||
drawsBackground = flags & NSMatrixDrawsBackgroundMask,
|
||||
backgroundColor = [aCoder decodeObjectForKey:@"NSBackgroundColor"],
|
||||
cells = [aCoder decodeObjectForKey:@"NSCells"],
|
||||
selectedCell = [aCoder decodeObjectForKey:@"NSSelectedCell"];
|
||||
- (id)NS_initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super NS_initWithCoder:aCoder];
|
||||
|
||||
if (isRadioMode)
|
||||
if (self)
|
||||
{
|
||||
var radioGroup = [CPRadioGroup new],
|
||||
frame = CGRectMake(0.0, 0.0, cellSize.width, cellSize.height);
|
||||
var numberOfRows = [aCoder decodeIntForKey:@"NSNumRows"],
|
||||
numberOfColumns = [aCoder decodeIntForKey:@"NSNumCols"],
|
||||
cellSize = [aCoder decodeSizeForKey:@"NSCellSize"],
|
||||
intercellSpacing = [aCoder decodeSizeForKey:@"NSIntercellSpacing"],
|
||||
flags = [aCoder decodeIntForKey:@"NSMatrixFlags"],
|
||||
isRadioMode = flags & NSMatrixRadioModeMask,
|
||||
drawsBackground = flags & NSMatrixDrawsBackgroundMask,
|
||||
backgroundColor = [aCoder decodeObjectForKey:@"NSBackgroundColor"],
|
||||
cells = [aCoder decodeObjectForKey:@"NSCells"],
|
||||
selectedCell = [aCoder decodeObjectForKey:@"NSSelectedCell"];
|
||||
|
||||
for (var rowIndex = 0; rowIndex < numberOfRows; ++rowIndex)
|
||||
if (isRadioMode)
|
||||
{
|
||||
frame.origin.x = 0;
|
||||
var radioGroup = [CPRadioGroup new],
|
||||
frame = CGRectMake(0.0, 0.0, cellSize.width, cellSize.height);
|
||||
|
||||
for (var columnIndex = 0; columnIndex < numberOfColumns; ++columnIndex)
|
||||
for (var rowIndex = 0; rowIndex < numberOfRows; ++rowIndex)
|
||||
{
|
||||
var cell = cells[rowIndex * numberOfColumns + columnIndex],
|
||||
cellView = [[CPRadio alloc] initWithFrame:frame radioGroup:radioGroup];
|
||||
frame.origin.x = 0;
|
||||
|
||||
[cellView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
[cellView setTitle:[cell title]];
|
||||
[cellView setBackgroundColor:[CPColor clearColor]]; // the IB default
|
||||
[cellView setObjectValue:[cell objectValue]];
|
||||
for (var columnIndex = 0; columnIndex < numberOfColumns; ++columnIndex)
|
||||
{
|
||||
var cell = cells[rowIndex * numberOfColumns + columnIndex],
|
||||
cellView = [[CPRadio alloc] initWithFrame:frame radioGroup:radioGroup cell:cell];
|
||||
|
||||
[view addSubview:cellView];
|
||||
[self addSubview:cellView];
|
||||
|
||||
NIB_CONNECTION_EQUIVALENCY_TABLE[[cell UID]] = cellView;
|
||||
NIB_CONNECTION_EQUIVALENCY_TABLE[[cell UID]] = cellView;
|
||||
|
||||
frame.origin.x = CGRectGetMaxX(frame) + intercellSpacing.width;
|
||||
frame.origin.x = CGRectGetMaxX(frame) + intercellSpacing.width;
|
||||
}
|
||||
|
||||
frame.origin.y = CGRectGetMaxY(frame) + intercellSpacing.height;
|
||||
}
|
||||
|
||||
frame.origin.y = CGRectGetMaxY(frame) + intercellSpacing.height;
|
||||
if (drawsBackground)
|
||||
[self setBackgroundColor:backgroundColor];
|
||||
|
||||
self.isa = [CPView class];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-radio group NSMatrix is not supported
|
||||
self = nil;
|
||||
}
|
||||
|
||||
if (drawsBackground)
|
||||
[view setBackgroundColor:backgroundColor];
|
||||
|
||||
NIB_CONNECTION_EQUIVALENCY_TABLE[[self UID]] = view;
|
||||
}
|
||||
|
||||
return view;
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPRadio (NS)
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame radioGroup:(CPRadioGroup)aRadioGroup cell:(NSButtonCell)aCell
|
||||
{
|
||||
self = [self initWithFrame:aFrame radioGroup:aRadioGroup];
|
||||
|
||||
if (self)
|
||||
{
|
||||
[self setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
[self setTitle:[aCell title]];
|
||||
[self setBackgroundColor:[CPColor clearColor]]; // the IB default
|
||||
[self setFont:[aCell font]];
|
||||
[self setAlignment:[aCell alignment]];
|
||||
[self setLineBreakMode:[aCell lineBreakMode]];
|
||||
[self setImagePosition:[aCell imagePosition]];
|
||||
[self setKeyEquivalent:[aCell keyEquivalent]];
|
||||
[self setKeyEquivalentModifierMask:[aCell keyEquivalentModifierMask]];
|
||||
[self setAllowsMixedState:[aCell allowsMixedState]];
|
||||
[self setObjectValue:[aCell objectValue]];
|
||||
[self setEnabled:[aCell isEnabled]];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -43,17 +43,17 @@ NIB_CONNECTION_EQUIVALENCY_TABLE = {};
|
||||
|
||||
if (sourceUID in NIB_CONNECTION_EQUIVALENCY_TABLE)
|
||||
{
|
||||
CPLog.trace("Swapped object: "+_source+" for object: "+NIB_CONNECTION_EQUIVALENCY_TABLE[sourceUID]);
|
||||
CPLog.debug("NSNibConnector: swapped object: " + _source + " for object: " + NIB_CONNECTION_EQUIVALENCY_TABLE[sourceUID]);
|
||||
_source = NIB_CONNECTION_EQUIVALENCY_TABLE[sourceUID];
|
||||
}
|
||||
|
||||
if (destinationUID in NIB_CONNECTION_EQUIVALENCY_TABLE)
|
||||
{
|
||||
CPLog.trace("Swapped object: "+_destination+" for object: "+NIB_CONNECTION_EQUIVALENCY_TABLE[destinationUID]);
|
||||
CPLog.debug("NSNibConnector: swapped object: " + _destination + " for object: " + NIB_CONNECTION_EQUIVALENCY_TABLE[destinationUID]);
|
||||
_destination = NIB_CONNECTION_EQUIVALENCY_TABLE[destinationUID];
|
||||
}
|
||||
|
||||
CPLog.debug(@"Connection: " + [_source description] + " " + [_destination description] + " " + _label);
|
||||
CPLog.debug(@"NSNibConnector: connection: " + [_source description] + " " + [_destination description] + " " + _label);
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -144,7 +144,7 @@ var NSTramsformers = [CPSet setWithObjects:
|
||||
[_options setObject:NSValue forKey:CPKey];
|
||||
}
|
||||
|
||||
CPLog.debug(@"Binding Connector: " + [_binding description] + " to: " + _destination + " " + [_keyPath description] + " " + [_options description]);
|
||||
CPLog.debug(@"NSNibConnector: binding connector: " + [_binding description] + " to: " + _destination + " " + [_keyPath description] + " " + [_options description]);
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
_items = [aCoder decodeObjectForKey:@"NSTabViewItems"];
|
||||
_selectedIndex = [_items indexOfObject:[aCoder decodeObjectForKey:@"NSSelectedTabViewItem"]];
|
||||
_font = [aCoder decodeObjectForKey:@"NSFont"];
|
||||
|
||||
//_delegate = [aCoder decodeObjectForKey:@""];
|
||||
|
||||
|
||||
@@ -45,26 +45,29 @@
|
||||
else
|
||||
{
|
||||
_dataView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
|
||||
|
||||
|
||||
var font = [dataViewCell font],
|
||||
selectedFont = nil;
|
||||
|
||||
|
||||
if (font)
|
||||
font = [NSFont cibFontForNibFont:font];
|
||||
|
||||
if (!font)
|
||||
font = [CPFont systemFontOfSize:12.0];
|
||||
|
||||
font = [CPFont systemFontOfSize:[CPFont systemFontSize]];
|
||||
|
||||
var selectedFont = [CPFont boldFontWithName:[font familyName] size:[font size]];
|
||||
|
||||
|
||||
[_dataView setFont:font];
|
||||
[_dataView setValue:selectedFont forThemeAttribute:@"font" inState:CPThemeStateSelectedDataView];
|
||||
|
||||
|
||||
[_dataView setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
|
||||
[_dataView setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
|
||||
[_dataView setValue:CGInsetMake(0.0, 5.0, 0.0, 5.0) forThemeAttribute:@"content-inset"];
|
||||
|
||||
|
||||
var textColor = [dataViewCell textColor],
|
||||
defaultColor = [_dataView currentValueForThemeAttribute:@"text-color"];
|
||||
|
||||
|
||||
// Don't change the text color if it is not the default, that messes up the theme lookups later
|
||||
if (![textColor isEqual:defaultColor])
|
||||
[_dataView setTextColor:[dataViewCell textColor]];
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
[self setFrameSize:CGSizeMake(frame.size.width + 7.0, frame.size.height + 7.0)];
|
||||
}
|
||||
|
||||
CPLog.debug([self stringValue] + " => isBordered=" + [self isBordered] + ", isBezeled=" + [self isBezeled] + ", bezelStyle=" + [self bezelStyle] + "("+[cell stringValue]+", " + [cell placeholderString] + ")");
|
||||
CPLog.debug("NSTextField: title=\"" + [self stringValue] + "\", placeholder=" + ([cell placeholderString] == null ? "<none>" : '"' + [cell placeholderString] + '"') + ", isBordered=" + [self isBordered] + ", isBezeled=" + [self isBezeled] + ", bezelStyle=" + [self bezelStyle]);
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -84,8 +84,6 @@ var NSViewAutoresizingMask = 0x3F,
|
||||
@end
|
||||
|
||||
@implementation NSView : CPView
|
||||
{
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
|
||||
+501
-63
@@ -18,11 +18,11 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
|
||||
@import <AppKit/CPCib.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
@import <BlendKit/BlendKit.j>
|
||||
|
||||
@import "NSFoundation.j"
|
||||
@import "NSAppKit.j"
|
||||
@@ -30,39 +30,266 @@
|
||||
@import "Nib2CibKeyedUnarchiver.j"
|
||||
@import "Converter.j"
|
||||
|
||||
var FILE = require("file");
|
||||
var OS = require("os");
|
||||
var FILE = require("file"),
|
||||
OS = require("os"),
|
||||
SYS = require("system"),
|
||||
FileList = require("jake").FileList,
|
||||
stream = require("narwhal/term").stream,
|
||||
|
||||
var parser = new (require("narwhal/args").Parser)();
|
||||
DefaultTheme = "Aristo",
|
||||
BuildTypes = ["Debug", "Release"],
|
||||
DefaultXibFile = "MainMenu.xib";
|
||||
|
||||
parser.usage("INPUT_FILE [OUTPUT_FILE]");
|
||||
var parser = new (require("narwhal/args").Parser)(),
|
||||
nibInfo = {};
|
||||
|
||||
parser.option("-F", "framework", "frameworks")
|
||||
.push()
|
||||
.help("Add a framework to load");
|
||||
|
||||
parser.option("-R", "resources")
|
||||
.set()
|
||||
.help("Set the Resources directory");
|
||||
function main(args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var options = parseOptions(args);
|
||||
|
||||
parser.option("--mac", "format")
|
||||
.set(NibFormatMac)
|
||||
.def(NibFormatUndetermined)
|
||||
.help("Set format to Mac");
|
||||
if (options.watch)
|
||||
watch(options);
|
||||
else
|
||||
convert(options);
|
||||
}
|
||||
catch (anException)
|
||||
{
|
||||
CPLog.fatal([anException reason]);
|
||||
OS.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// parser.option("--iphone", "format")
|
||||
// .set(NibFormatIPhone)
|
||||
// .help("Set format to iPhone");
|
||||
function convert(options, inputFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
inputFile = inputFile || getInputFile(options.args);
|
||||
|
||||
parser.option("-v", "--verbose", "verbose")
|
||||
.inc()
|
||||
.help("Increase verbosity level");
|
||||
var outputFile = getOutputFile(inputFile, options.args),
|
||||
resourcesPath = "";
|
||||
|
||||
parser.option("-q", "--quiet", "quiet")
|
||||
.set(true)
|
||||
.help("No output");
|
||||
if (options.resources)
|
||||
{
|
||||
resourcesPath = FILE.canonical(options.resources);
|
||||
|
||||
parser.helpful();
|
||||
if (!FILE.isDirectory(resourcesPath) || !FILE.isReadable(resourcesPath))
|
||||
fail("Cannot read resources at: " + resourcesPath);
|
||||
}
|
||||
|
||||
var configPath = setSystemFontAndSize(options.configFile || "", inputFile),
|
||||
themeName = "",
|
||||
themeDir = options.themeDir || "";
|
||||
|
||||
if (themeDir)
|
||||
themeName = FILE.basename(themeDir, FILE.extension(themeDir));
|
||||
|
||||
themeName = themeName || getDefaultThemeName();
|
||||
|
||||
if (!themeName)
|
||||
fail("Could not determine the theme name.");
|
||||
|
||||
var theme = loadTheme(themeName, themeDir);
|
||||
|
||||
CPLog.info("\n-------------------------------------------------------------");
|
||||
CPLog.info("Input : " + inputFile);
|
||||
CPLog.info("Output : " + outputFile);
|
||||
CPLog.info("Format : " + ["Auto", "Mac", "iPhone"][options.format]);
|
||||
CPLog.info("Resources : " + resourcesPath);
|
||||
CPLog.info("Frameworks : " + (options.frameworks || ""));
|
||||
CPLog.info("Theme : " + themeName);
|
||||
CPLog.info("Config file : " + (configPath || ""));
|
||||
CPLog.info("System Font : " + [CPFont systemFontSize] + "px " + [CPFont systemFontFace]);
|
||||
CPLog.info("-------------------------------------------------------------\n");
|
||||
|
||||
var converter = [[Converter alloc] initWithInputPath:inputFile
|
||||
format:options.format
|
||||
theme:theme];
|
||||
|
||||
[converter setOutputPath:outputFile];
|
||||
[converter setResourcesPath:resourcesPath];
|
||||
|
||||
loadFrameworks(options.frameworks, function()
|
||||
{
|
||||
[converter convert];
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (anException)
|
||||
{
|
||||
CPLog.fatal([anException reason]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function watch(options)
|
||||
{
|
||||
var verbosity = options.quiet ? -1 : options.verbosity,
|
||||
directory = options.args[0];
|
||||
|
||||
if (!directory)
|
||||
directory = FILE.isDirectory("Resources") ? "Resources" : ".";
|
||||
|
||||
directory = FILE.canonical(directory);
|
||||
|
||||
if (!FILE.isDirectory(directory))
|
||||
fail("Cannot find the directory: " + directory);
|
||||
|
||||
// Turn on info messages
|
||||
setLogLevel(1);
|
||||
|
||||
CPLog.info("Watching: " + CPLogColorize(directory, "debug"));
|
||||
CPLog.info("Press Control-C to stop...");
|
||||
|
||||
while (true)
|
||||
{
|
||||
var modifiedNibs = getModifiedNibs(directory);
|
||||
|
||||
for (var i = 0; i < modifiedNibs.length; ++i)
|
||||
{
|
||||
var action = modifiedNibs[i][0],
|
||||
path = modifiedNibs[i][1],
|
||||
label = action === "add" ? "Added:" : "Modified:",
|
||||
level = action === "add" ? "info" : "debug";
|
||||
|
||||
CPLog.info(">> %s %s", CPLogColorize(label, level), path);
|
||||
|
||||
// Let the converter log however the user configured it
|
||||
setLogLevel(verbosity);
|
||||
|
||||
var success = convert(options, path);
|
||||
|
||||
setLogLevel(1);
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (verbosity > 0)
|
||||
stream.print();
|
||||
else
|
||||
CPLog.warn("Conversion successful");
|
||||
}
|
||||
}
|
||||
|
||||
OS.sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
function parseOptions(args)
|
||||
{
|
||||
parser.usage("[--watch DIRECTORY] [INPUT_FILE [OUTPUT_FILE]]");
|
||||
|
||||
parser.option("--watch", "watch")
|
||||
.set(true)
|
||||
.help("Ask nib2cib to watch a directory for changes");
|
||||
|
||||
parser.option("-F", "framework", "frameworks")
|
||||
.push()
|
||||
.help("Add a framework to load");
|
||||
|
||||
parser.option("-R", "resources")
|
||||
.set()
|
||||
.help("Set the Resources directory");
|
||||
|
||||
parser.option("--mac", "format")
|
||||
.set(NibFormatMac)
|
||||
.def(NibFormatUndetermined)
|
||||
.help("Set format to Mac");
|
||||
|
||||
parser.option("-t", "--theme-dir", "themeDir")
|
||||
.set()
|
||||
.help("A <theme>.build directory to use for theme attribute values");
|
||||
|
||||
parser.option("--config", "configFile")
|
||||
.set()
|
||||
.help("A path to an Info.plist file from which the system font and/or size can be retrieved");
|
||||
|
||||
// parser.option("--iphone", "format")
|
||||
// .set(NibFormatIPhone)
|
||||
// .help("Set format to iPhone");
|
||||
|
||||
parser.option("-v", "--verbose", "verbosity")
|
||||
.inc()
|
||||
.help("Increase verbosity level");
|
||||
|
||||
parser.option("-q", "--quiet", "quiet")
|
||||
.set(true)
|
||||
.help("No output");
|
||||
|
||||
parser.option("--version", "showVersion")
|
||||
.action(printVersionAndExit)
|
||||
.help("Show the version of nib2cib and quit");
|
||||
|
||||
parser.helpful();
|
||||
|
||||
var options = parser.parse(args, null, null, true);
|
||||
|
||||
if (options.args.length > 2)
|
||||
{
|
||||
parser.printUsage(options);
|
||||
OS.exit(0);
|
||||
}
|
||||
|
||||
setLogLevel(options.quiet ? -1 : options.verbosity);
|
||||
|
||||
if (!options.quiet && options.verbosity > 0)
|
||||
printVersion();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function setLogLevel(level)
|
||||
{
|
||||
CPLogUnregister(CPLogPrint);
|
||||
|
||||
if (level === 0)
|
||||
CPLogRegister(CPLogPrint, "warn", logFormatter);
|
||||
else if (level === 1)
|
||||
CPLogRegister(CPLogPrint, "info", logFormatter);
|
||||
else if (level > 1)
|
||||
CPLogRegister(CPLogPrint, null, logFormatter);
|
||||
}
|
||||
|
||||
function getInputFile(args)
|
||||
{
|
||||
var inputFile = args[0] || DefaultXibFile;
|
||||
|
||||
if (!/^.+\.xib$/.test(inputFile))
|
||||
inputFile += ".xib";
|
||||
|
||||
inputFile = FILE.canonical(inputFile);
|
||||
|
||||
if (!FILE.exists(inputFile) && FILE.basename(FILE.dirname(inputFile)) !== "Resources")
|
||||
if (FILE.isDirectory("Resources"))
|
||||
inputFile = FILE.resolve(inputFile, FILE.join("Resources", FILE.basename(inputFile)));
|
||||
|
||||
if (!FILE.isReadable(inputFile))
|
||||
fail("Cannot read the input file: " + inputFile);
|
||||
|
||||
return inputFile;
|
||||
}
|
||||
|
||||
function getOutputFile(inputFile, args)
|
||||
{
|
||||
var outputFile = null;
|
||||
|
||||
if (args.length > 1)
|
||||
outputFile = args[1];
|
||||
else
|
||||
outputFile = FILE.basename(inputFile, FILE.extension(inputFile));
|
||||
|
||||
if (!/^.+\.cib$/.test(outputFile))
|
||||
outputFile += ".cib";
|
||||
|
||||
outputFile = FILE.resolve(inputFile, outputFile);
|
||||
|
||||
if (!FILE.isWritable(FILE.dirname(outputFile)))
|
||||
fail("Cannot write the output file at: " + outputFile);
|
||||
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
function loadFrameworks(frameworkPaths, aCallback)
|
||||
{
|
||||
@@ -71,7 +298,7 @@ function loadFrameworks(frameworkPaths, aCallback)
|
||||
|
||||
frameworkPaths.forEach(function(aFrameworkPath)
|
||||
{
|
||||
print("Loading " + aFrameworkPath);
|
||||
CPLog.info("Loading " + aFrameworkPath);
|
||||
|
||||
var frameworkBundle = [[CPBundle alloc] initWithPath:aFrameworkPath];
|
||||
|
||||
@@ -83,44 +310,255 @@ function loadFrameworks(frameworkPaths, aCallback)
|
||||
aCallback();
|
||||
}
|
||||
|
||||
function main(args)
|
||||
function logFormatter(aString, aLevel, aTitle)
|
||||
{
|
||||
var options = parser.parse(args, null, null, true);
|
||||
if (aLevel === "info")
|
||||
return aString;
|
||||
else
|
||||
return CPLogColorize(aString, aLevel);
|
||||
}
|
||||
|
||||
if (options.args.length < 1 || options.args.length > 2)
|
||||
function getDefaultThemeName()
|
||||
{
|
||||
var themeName = nil,
|
||||
cappBuild = SYS.env["CAPP_BUILD"];
|
||||
|
||||
if (cappBuild)
|
||||
{
|
||||
parser.printUsage(options);
|
||||
OS.exit(1);
|
||||
for (var i = 0; i < BuildTypes.length; ++i)
|
||||
{
|
||||
var path = FILE.join(cappBuild, BuildTypes[i], "AppKit", "Info.plist");
|
||||
themeName = themeNameFromPropertyList(path);
|
||||
|
||||
if (themeName)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.quiet) {}
|
||||
else if (options.verbose === 0)
|
||||
CPLogRegister(CPLogPrint, "warn");
|
||||
else if (options.verbose === 1)
|
||||
CPLogRegister(CPLogPrint, "info");
|
||||
else
|
||||
CPLogRegister(CPLogPrint);
|
||||
|
||||
CPLog.debug("Input: " + options.args[0]);
|
||||
CPLog.debug("Output: " + (options.args[1] || ""));
|
||||
CPLog.debug("Format: " + ["Auto","Mac","iPhone"][options.format]);
|
||||
CPLog.debug("Resources: " + (options.resources || ""));
|
||||
CPLog.debug("Frameworks: " + options.frameworks);
|
||||
|
||||
var converter = [[Converter alloc] init];
|
||||
|
||||
if (options.resources)
|
||||
[converter setResourcesPath:options.resources];
|
||||
|
||||
[converter setFormat:options.format];
|
||||
|
||||
[converter setInputPath:options.args[0]];
|
||||
|
||||
if (options.args.length > 1)
|
||||
[converter setOutputPath:options.args[1]];
|
||||
|
||||
loadFrameworks(options.frameworks, function()
|
||||
{
|
||||
[converter convert];
|
||||
});
|
||||
return themeName || DefaultTheme;
|
||||
}
|
||||
|
||||
function themeNameFromPropertyList(path)
|
||||
{
|
||||
if (!FILE.isReadable(path))
|
||||
return nil;
|
||||
|
||||
var themeName = nil,
|
||||
plist = CFPropertyList.readPropertyListFromFile(path);
|
||||
|
||||
if (plist)
|
||||
themeName = plist.valueForKey("CPDefaultTheme");
|
||||
|
||||
return themeName;
|
||||
}
|
||||
|
||||
function loadTheme(themeName, themeDir)
|
||||
{
|
||||
if (!themeDir)
|
||||
{
|
||||
cappBuild = SYS.env["CAPP_BUILD"];
|
||||
|
||||
if (!cappBuild)
|
||||
fail("$CAPP_BUILD is not set, exiting.");
|
||||
|
||||
if (!FILE.isDirectory(cappBuild))
|
||||
fail("$CAPP_BUILD does not exist: " + cappBuild)
|
||||
|
||||
var baseThemeName = themeName,
|
||||
pos = themeName.indexOf("-");
|
||||
|
||||
if (pos > 0)
|
||||
baseThemeName = themeName.substr(0, pos);
|
||||
|
||||
themeDir = FILE.join(cappBuild, baseThemeName + ".build");
|
||||
}
|
||||
|
||||
themeDir = FILE.canonical(themeDir);
|
||||
|
||||
if (!FILE.isDirectory(themeDir))
|
||||
fail("Cannot find the theme directory: " + themeDir);
|
||||
|
||||
var themePath = null;
|
||||
|
||||
for (var i = 0; i < BuildTypes.length; ++i)
|
||||
{
|
||||
var path = FILE.join(themeDir, BuildTypes[i], "Browser.environment/Resources", themeName + ".keyedtheme");
|
||||
|
||||
if (FILE.isReadable(path))
|
||||
{
|
||||
themePath = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!themePath)
|
||||
fail("Could not find the keyed theme data for \"" + themeName + "\" in the directory: " + themeDir);
|
||||
|
||||
themePath = FILE.canonical(themePath);
|
||||
var plist = FILE.read(themePath);
|
||||
|
||||
if (!plist)
|
||||
fail("Could not read the keyed theme at: " + themePath);
|
||||
|
||||
// The .keyedtheme file has a header that is data I don't need. Strip it off.
|
||||
var m = plist.match(/^t;\d+;/);
|
||||
|
||||
if (!m || m.length === 0)
|
||||
fail("Invalid keyed theme data at: " + themePath);
|
||||
|
||||
plist = plist.substr(m[0].length);
|
||||
plist = CFPropertyList.propertyListFromString(plist);
|
||||
|
||||
var data = [CPData dataWithPlistObject:plist],
|
||||
theme = [CPKeyedUnarchiver unarchiveObjectWithData:data];
|
||||
|
||||
if (!theme)
|
||||
fail("Could not unarchive the theme at: " + themePath);
|
||||
|
||||
CPLog.debug("Loaded theme: " + themePath);
|
||||
return theme;
|
||||
}
|
||||
|
||||
function setSystemFontAndSize(configFile, inputFile)
|
||||
{
|
||||
var configPath = null;
|
||||
|
||||
// First see if the user passed a config file path
|
||||
if (configFile)
|
||||
{
|
||||
var path = FILE.canonical(configFile);
|
||||
|
||||
if (!FILE.isReadable(path))
|
||||
fail("Cannot find the config file: " + path);
|
||||
|
||||
configPath = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
// See if we can find an Info.plist in the parent directory of the input file,
|
||||
// if the input file's directory is "Resources".
|
||||
var path = FILE.canonical(FILE.dirname(inputFile));
|
||||
|
||||
if (FILE.basename(path) === "Resources")
|
||||
{
|
||||
path = FILE.join(FILE.dirname(path), "Info.plist");
|
||||
|
||||
if (FILE.isReadable(path))
|
||||
configPath = path;
|
||||
}
|
||||
}
|
||||
|
||||
if (configPath)
|
||||
{
|
||||
var plist = FILE.read(configPath);
|
||||
|
||||
if (!plist)
|
||||
fail("Could not read the Info.plist at: " + configPath);
|
||||
|
||||
plist = CFPropertyList.propertyListFromString(plist);
|
||||
|
||||
if (!plist)
|
||||
fail("Could not parse the Info.plist at: " + configPath);
|
||||
|
||||
var systemFontFace = plist.valueForKey("CPSystemFontFace");
|
||||
|
||||
if (systemFontFace)
|
||||
[CPFont setSystemFontFace:systemFontFace];
|
||||
|
||||
var systemFontSize = plist.valueForKey("CPSystemFontSize");
|
||||
|
||||
if (systemFontSize)
|
||||
[CPFont setSystemFontSize:parseFloat(systemFontSize, 10)];
|
||||
}
|
||||
|
||||
return configPath;
|
||||
}
|
||||
|
||||
function getModifiedNibs(path)
|
||||
{
|
||||
var nibs = new FileList(FILE.join(path, "*.xib")).items(),
|
||||
count = nibs.length,
|
||||
newNibInfo = {},
|
||||
modifiedNibs = [];
|
||||
|
||||
while (count--)
|
||||
{
|
||||
var nib = nibs[count];
|
||||
|
||||
newNibInfo[nib] = FILE.mtime(nib);
|
||||
|
||||
if (!nibInfo.hasOwnProperty(nib))
|
||||
modifiedNibs.push(["add", nib]);
|
||||
else
|
||||
{
|
||||
if (newNibInfo[nib] - nibInfo[nib] !== 0)
|
||||
modifiedNibs.push(["mod", nib]);
|
||||
|
||||
// Remove matching nibs so that we leave
|
||||
// deleted nibs in nibInfo.
|
||||
delete nibInfo[nib];
|
||||
}
|
||||
}
|
||||
|
||||
for (var nib in nibInfo)
|
||||
{
|
||||
if (nibInfo.hasOwnProperty(nib))
|
||||
CPLog.info(">> %s %s", CPLogColorize("Deleted:", "warn"), nib);
|
||||
}
|
||||
|
||||
nibInfo = newNibInfo;
|
||||
|
||||
return modifiedNibs;
|
||||
}
|
||||
|
||||
function printVersionAndExit()
|
||||
{
|
||||
printVersion();
|
||||
OS.exit(0);
|
||||
}
|
||||
|
||||
function printVersion()
|
||||
{
|
||||
/*
|
||||
There are two usual possibilities for the location of the nib2cib binary.
|
||||
If we are executing the installed narwhal binary, the location is:
|
||||
<narwhal>/packages/cappuccino/bin/nib2cib
|
||||
If we are executing the built binary, the location is:
|
||||
<CAPP_BUILD>/Debug|Release/CommonJS/cappuccino/bin/nib2cib
|
||||
|
||||
Base on these paths we can locate nib2cib's Info.plist.
|
||||
*/
|
||||
var path = FILE.dirname(FILE.dirname(FILE.canonical(SYS.args[0]))),
|
||||
version = null;
|
||||
|
||||
if (FILE.basename(path) === "narwhal")
|
||||
path = FILE.join(path, "packages", "cappuccino");
|
||||
|
||||
path = FILE.join(path, "lib", "nib2cib", "Info.plist");
|
||||
|
||||
if (FILE.isReadable(path))
|
||||
{
|
||||
var plist = FILE.read(path);
|
||||
|
||||
if (!plist)
|
||||
return;
|
||||
|
||||
plist = CFPropertyList.propertyListFromString(plist);
|
||||
|
||||
if (!plist)
|
||||
return;
|
||||
|
||||
version = plist.valueForKey("CPBundleVersion");
|
||||
|
||||
if (version)
|
||||
stream.print("nib2cib v" + version);
|
||||
}
|
||||
|
||||
if (!version)
|
||||
stream.print("<No version info available>");
|
||||
}
|
||||
|
||||
function fail(message)
|
||||
{
|
||||
[CPException raise:ConverterConversionException reason:message];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user