Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-18062] iOS: AttributedString Parity with Android #6463

Merged
merged 13 commits into from Jan 15, 2015

Conversation

ashcoding
Copy link
Contributor

Jira: https://jira.appcelerator.org/browse/TIMOB-18062

This PR is a continuation of #6409 which came from #6358.

It addresses the comments by @pingwang2011 for the Android portion of the code. The doc is still not completed yet as Titanium.UI.iOS.Attribute and Titanium.UI.iOS.AttributedString yml files are missing the "deprecated".

The propertyAccessors is now used in AttributedStringProxy.java, AttributeProxy.java and LabelProxy.java.

-Using property accessors in AttributedProxy for Range
-Using property accessors in Label Proxy for AttributedString
-Using property accessors in AttributedStringProxy for AttributedString
@ashcoding ashcoding changed the title TIMOB-18062 [TIMOB-18062] iOS: AttributedString Parity with Android Dec 11, 2014
-Added attributed string for TextArea and TextField on Android
-Added docs for TextArea and TextField
@@ -98,97 +98,6 @@ -(NSNumber*)CLIP_MODE_DISABLED
return NUMINT(-1);
}

#ifdef USE_TI_UIIOSATTRIBUTEDSTRING
MAKE_SYSTEM_PROP(ATTRIBUTE_FONT, AttributeNameFont);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These properties should not be deleted. Instead they should be marked DEPRECATED REPLACED

@vishalduggal
Copy link
Contributor

TiUIAttributedStringProxy.m is only a member of Target Titanium-KitchenSink. It also needs to be added to target Titanium-KitchenSink-iPad and Titanium-KitchenSink-universal

@vishalduggal
Copy link
Contributor

Code reviewed. Please address comments. Will do FR only after CR passes. As it stands right now this PR is rejected

@matt-langston
Copy link
Contributor

@ashcoding, great work on this effort. I just noticed that 38 valuable comments from @pingwang2011 from PR #6409 pertain to this PR #6463. Will you please make sure those comments are addressed in this PR #6463? Here is the list of Ping's comments. Thank you!

  1. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  2. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  3. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  4. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  5. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  6. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  7. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  8. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  9. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  10. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  11. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  12. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  13. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  14. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  15. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  16. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  17. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  18. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  19. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  20. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  21. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  22. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  23. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  24. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  25. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  26. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  27. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  28. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  29. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  30. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  31. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  32. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  33. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  34. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  35. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (diff)
  36. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  37. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)
  38. [TIMOB-18062] iOS: AttributedString Parity with Android #6409 (comment)

@pingwang2011
Copy link
Contributor

For the question about duplicate properties, I meant:
{code}
var TEXT1 = 'Hello';
var TEXT2 = "Hi";

var attr = Titanium.UI.createAttributedString({
text: TEXT1,
attributes: [
//font
{
type: Ti.UI.ATTRIBUTE_FONT,
value: FONT1,
range: [0, text.length]
},
// Sets a background color
{
type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
value: COLOR1,
range: [0, text.length]
}
]
var label = Titanium.UI.createLabel({
text: TEXT2,
font: FONT2,
backgroundColor: COLOR2,
attributedString: attr
});
{code}

Which text (TEXT1 or TEXT2), font (FONT1 or FONT2) and backgroundColor (COLOR1 or COLOR2) will be respected?

@@ -0,0 +1,58 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2009-2014 by Appcelerator, Inc. All Rights Reserved.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#6409 (diff)

Fixed from 2013 to 2014

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be "Copyright (c) 2014 by Appcelerator, Inc. All Rights Reserved" because it's added in 2014.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should be 2014-2015, since 2014 is coming to an end.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hieupham007 , you are farsighted 👍

if (attributedString instanceof AttributedStringProxy) {
Spannable spannableText = AttributedStringProxy.toSpannable(((AttributedStringProxy)attributedString), getProxy());
if (spannableText != null) {
((TextView)getNativeView()).setText(spannableText);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use tv instead of ((TextView)getNativeView()).

@pingwang2011
Copy link
Contributor

In TextField and TextArea, if you set attributedString, font and backgroundColor initially, which properties will be applied for the user input text (the text input by soft keyboard)?

@ashcoding
Copy link
Contributor Author

In TextField and TextArea, if you set attributedString, font and backgroundColor initially, which properties will be applied for the user input text (the text input by soft keyboard)?

The input text will use font and backgroundColor that is set if the input text is not in between the attributedString.

@ashcoding
Copy link
Contributor Author

Sample Code.
Tab 1:-
It is a label with text "Appcelerator" as a link. You can click it and it will open a window.
Clicking the button will change the attributes.

Tab 2:-
First TextField has a normal input and an attributedStringHint. Erase the input to see the hint.

Second TextField has an AttributedString as input and background set to red, font color to yellow and size to 20. If you erase the AttributedString or type after it, the input will be yellow, font size 20 with red background. Background color affects both AttributedString and the input.

Third TextField has AttributedString and AttributedString hint. Erase it to reveal the hint.
Font has been set to size 10 and color red. If you type after or erase the AttributedString, the input will be size 10 and with color red.

Tab 3:-

TextArea has attributedString and font, color and backgroundColor set. If you erase the Attributed String or type after it, all the input text will be font 20, bold, yellow with red background. Background color affects both AttributedString and the input.

// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');
// create tab group
var tabGroup = Titanium.UI.createTabGroup();
// create base UI tab and root window
//////////////////////////////////////
var win1 = Titanium.UI.createWindow({  
    title:'Label',
    backgroundColor:'#ddd'
});
var tab1 = Titanium.UI.createTab({  
    icon:'KS_nav_views.png',
    title:'Label',
    window:win1
});


var text =  'Bacon ipsum dolor Appcelerator Titanium rocks! sit amet fatback leberkas salami sausage tongue strip steak.';

var attr = Ti.UI.createAttributedString({
    text: text,
    attributes: [
        //font
        {
            type: Ti.UI.ATTRIBUTE_FONT,
            value: {font:{fontSize:50,fontFamily:'Helvetica Neue'}},
            range: [0, text.length]
        },
        // Underlines text
        {
            type: Ti.UI.ATTRIBUTE_UNDERLINES_STYLE,
            value: Ti.UI.ATTRIBUTE_UNDERLINE_STYLE_SINGLE, //only iOS needs this, android ignores.
            range: [0, text.length]
        },
        // Sets a background color
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "red",
            range: [text.indexOf('Appcelerator'), ('Appcelerator').length]
        }
    ]
});

attr.addAttribute(
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "blue",
            range: [text.indexOf('Titanium'), ('Titanium').length]
        }
);  

attr.addAttribute(
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "yellow",
            range: [text.indexOf('rocks!'), ('rocks!').length]
        }
);        

attr.addAttribute(
        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "orange",
            range: [0,  text.length]
        }
);

attr.addAttribute(
        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "black",
            range: [text.indexOf('rocks!'), ('rocks!').length]
        }
);

attr.addAttribute(
        {
            type: Ti.UI.ATTRIBUTE_LINK,//ignored in iOS, label doesn't support attribute link. Use textArea instead. 
            value: "http://www.appcelerator.com",
            range: [text.indexOf('Appcelerator'), ('Appcelerator').length]
        }
);

var label = Titanium.UI.createLabel({
    left: 20,
    right: 20,
    height: Titanium.UI.SIZE,
    attributedString: attr
});

var changeStyle = Titanium.UI.createButton({
    bottom:200,
    title: "ChangeStyle"
});

win1.add(label);
win1.add(changeStyle);

var attr2 = Titanium.UI.createAttributedString({
    text: text,
    attributes: [
        //font
        {
            type: Ti.UI.ATTRIBUTE_FONT,
            value: {font:{fontSize:30,fontFamily:'Helvetica Neue'}},
            range: [0, text.length]
        },
        // Underlines text
        {
            type: Ti.UI.ATTRIBUTE_UNDERLINES_STYLE,
            value: Ti.UI.ATTRIBUTE_UNDERLINE_STYLE_SINGLE, //only iOS needs this, android ignores.
            range: [0, text.length]
        },
        // Sets a background color
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "green",
            range: [text.indexOf('Appcelerator'), ('Appcelerator').length]
        },
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "red",
            range: [text.indexOf('Titanium'), ('Titanium').length]
        },
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "blue",
            range: [text.indexOf('rocks!'), ('rocks!').length]
        },
        // Sets a foreground color
        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "black",
            range: [0,  text.length]
        },
        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "red",
            range: [text.indexOf('rocks!'), ('rocks!').length]
        },
        // Sets strike through
        {
            type: Ti.UI.ATTRIBUTE_STRIKETHROUGH_STYLE,
            value: Titanium.UI.ATTRIBUTE_UNDERLINE_STYLE_SINGLE, //only iOS needs this, android ignores.
            range: [text.indexOf('tongue'), ('tongue').length]
        },
        {
            type: Ti.UI.ATTRIBUTE_LINK, //ignored in iOS, label doesn't support attribute link. Use textArea instead. 
            value: "http://www.appcelerator.com",
            range: [text.indexOf('Appcelerator'), ('Appcelerator').length]
        }
    ]
});

changeStyle.addEventListener('click', function(){
    label.attributedString=attr2;});


//////////////////////////////////////
var win2 = Titanium.UI.createWindow({  
    title:'TextField',
    backgroundColor:'#ddd'
});
var tab2 = Titanium.UI.createTab({  
    icon:'KS_nav_views.png',
    title:'TextField',
    window:win2
});

var textFieldtextHint =  'Hints are awesome!';

var attrFieldHint = Ti.UI.createAttributedString({
    text: textFieldtextHint,
    attributes: [
        //font
        {
            type: Ti.UI.ATTRIBUTE_FONT,
            value: {font:{fontSize:30,fontFamily:'Helvetica Neue'}},
            range: [0, textFieldtextHint.length]
        },
        // Underlines text
        {
            type: Ti.UI.ATTRIBUTE_UNDERLINES_STYLE,
            value: Ti.UI.ATTRIBUTE_UNDERLINE_STYLE_SINGLE, //only iOS needs this, android ignores.
            range: [0, textFieldtextHint.length]
        },
        // Sets a background color
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "red",
            range: [textFieldtextHint.indexOf('Hints'), ('Hints').length]
        },
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "blue",
            range: [textFieldtextHint.indexOf('are'), ('are').length]
        },
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "yellow",
            range: [textFieldtextHint.indexOf('awesome!'), ('awesome!').length]
        },
        // Sets a foreground color
        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "orange",
            range: [0,  textFieldtextHint.length]
        },
        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "black",
            range: [textFieldtextHint.indexOf('awesome!'), ('awesome!').length]
        }
    ]
});

var textFieldtext =  'Textfields are awesome!';

var attrField = Ti.UI.createAttributedString({
    text: textFieldtext,
    attributes: [
        //font
        {
            type: Ti.UI.ATTRIBUTE_FONT,
            value: {font:{fontSize:50,fontFamily:'Helvetica Neue'}},
            range: [0, textFieldtext.length]
        },
        // Underlines text
        {
            type: Ti.UI.ATTRIBUTE_UNDERLINES_STYLE,
            value: Ti.UI.ATTRIBUTE_UNDERLINE_STYLE_SINGLE, //only iOS needs this, android ignores.
            range: [0, textFieldtext.length]
        },
        // Sets a background color
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "red",
            range: [textFieldtext.indexOf('Text'), ('Text').length]
        },
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "blue",
            range: [textFieldtext.indexOf('field'), ('field').length]
        },
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "yellow",
            range: [textFieldtext.indexOf('awesome!'), ('awesome!').length]
        },
        // Sets a foreground color
        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "orange",
            range: [0,  textFieldtext.length]
        },
        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "black",
            range: [textFieldtext.indexOf('awesome!'), ('awesome!').length]
        }
    ]
});

var textField1 = Ti.UI.createTextField({
  borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
  color: 'black',
  top: 10,
  width: 'auto', height: 'auto',
  value: 'value text',
  attributedHintText: attrFieldHint
});

var textField2 = Ti.UI.createTextField({
  borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
  color: 'black',
  top: 110,
  width: 'auto', height: 'auto',
  attributedString: attrField,
  value: 'value text',
  font: {fontSize:20,fontFamily:'Helvetica Neue'},
  backgroundColor: 'red',
  color: 'yellow'

});

var textField3 = Ti.UI.createTextField({
  borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
  color: 'black',
  top: 210,
  width: 'auto', height: 'auto',
  attributedHintText: attrFieldHint,
  attributedString: attrField,
  value: 'value text',
  font: {fontSize:10,fontFamily:'Helvetica Neue'},  
  color: 'red'
});

win2.add(textField1);
win2.add(textField2);
win2.add(textField3);

//////////////////////////////////////
var win3 = Titanium.UI.createWindow({  
    title:'TextArea',
    backgroundColor:'#ddd'
});
var tab3 = Titanium.UI.createTab({  
    icon:'KS_nav_views.png',
    title:'TextArea',
    window:win3
});

var textArea1 = Ti.UI.createTextArea({
  borderWidth: 2,
  borderColor: '#bbb',
  borderRadius: 5,
  textAlign: 'left',
  attributedString: attrField,
  value: 'value text',
  font: {fontSize:20, fontWeight:'bold'},
  backgroundColor: 'red',
  color: 'yellow',
  top: 10,
  width: 'auto', height: 'auto'
});

win3.add(textArea1);
//////////////////////////////////

tabGroup.addTab(tab1);  
tabGroup.addTab(tab2); 
tabGroup.addTab(tab3); 
// open tab group
tabGroup.open();

@ashcoding ashcoding force-pushed the TIMOB-18062 branch 3 times, most recently from 48a912c to 447119d Compare December 16, 2014 09:21
@pingwang2011
Copy link
Contributor

Code reviewed. Left one comment about parity.
Ran the above sample code. It works as expected.

@ingo
Copy link
Contributor

ingo commented Jan 13, 2015

@ashcoding can you finish the review?

@ashcoding
Copy link
Contributor Author

Will do.

@ashcoding
Copy link
Contributor Author

iOS code needs to change for the color property. Sample code to show issue as follows:

// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');
//////////////////////////////////////
var win1 = Titanium.UI.createWindow({  
    title:'Label',
    backgroundColor:'#ddd'
});

var text =  'Bacon ipsum dolor Appcelerator Titanium rocks! sit amet fatback leberkas salami sausage tongue strip steak.';

var attr = Ti.UI.createAttributedString({
    text: text,
    attributes: [
        //font
        {
            type: Ti.UI.ATTRIBUTE_FONT,
            value: {font:{fontSize:50,fontFamily:'Helvetica Neue'}},
            range: [0, text.length]
        },
        // Underlines text
        {
            type: Ti.UI.ATTRIBUTE_UNDERLINES_STYLE,
            value: Ti.UI.ATTRIBUTE_UNDERLINE_STYLE_SINGLE, //only iOS needs this, android ignores.
            range: [0, text.length]
        },
        // Sets a background color
        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "red",
            range: [text.indexOf('Appcelerator'), ('Appcelerator').length]
        },

        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "blue",
            range: [text.indexOf('Titanium'), ('Titanium').length]
        },

        {
            type: Ti.UI.ATTRIBUTE_BACKGROUND_COLOR,
            value: "yellow",
            range: [text.indexOf('rocks!'), ('rocks!').length]
        },

        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "orange",
            range: [0,  text.length]
        },

        {
            type: Ti.UI.ATTRIBUTE_FOREGROUND_COLOR,
            value: "black",
            range: [text.indexOf('rocks!'), ('rocks!').length]
        },

        {
            type: Ti.UI.ATTRIBUTE_LINK,//ignored in iOS, label doesn't support attribute link. Use textArea instead. 
            value: "http://www.appcelerator.com",
            range: [text.indexOf('Appcelerator'), ('Appcelerator').length]
        }

    ]
});


var label = Titanium.UI.createLabel({
    left: 20,
    right: 20,
    height: Titanium.UI.SIZE,
    attributedString: attr
});

//Changing the following properties shouldn't affect label as attributedString is respected first
label.text = "New text is here"; // This doesn't change on iOS and Android. Expected behavior.
label.setFont({fontSize:5}); // This doesn't change on iOS and Android. Expected behavior.
label.color = "red"; //iOS seems to be affected by this. Unexpected behavior.
//Shadow properties are working in iOS and Android. Doc should mention this.
label.shadowColor = "blue"; 
label.shadowRadius = 5;

win1.add(label);
win1.open();

@cheekiatng
Copy link
Contributor

After some verification, existing iOS "attributedString"' behavior on UILabel is DIFFERENT from what the existing documents say.
if "attributedString" and other properties of UILabel is set initially, iOS respects the other properties. This has been confirmed. So there should no further changes to IOS behavior, and we will require Android to achieve parity with this behavior. Documents must also be updated to inform the correct behavior.
Thanks Ash.

@ashcoding
Copy link
Contributor Author

I'll go change the Android behavior of the attributedString to match iOS when other properties is set.

@ashcoding ashcoding force-pushed the TIMOB-18062 branch 2 times, most recently from 7e4b0d3 to d1cecab Compare January 14, 2015 05:38
@ashcoding
Copy link
Contributor Author

I looked into this further.

In Android, if you set an attributed string, when you use methods such as setFont or setColor, natively it sets it to the Text in the TextView to those properties. If the AttributedString (natively it is SpannableString), those methods do not seem to change the properties of the AttributedString.

setColor, setFont and etc would affect the whole Text when used normally while normally when you use AttributedStrings, you would specify at which part does it have a certain color. Thus, I don't think it should be used in that way too.

So in this case, I would not recommend for parity in this case when AttributedString, text, color and font is used.

Instead I would recommend a document change to specify that you should not use AttributedString with the other properties, eg text, font and color in Android. Either use AttributedString or use the other properties.

Shadow properties work with no issue.

@pingwang2011
Copy link
Contributor

CR & FR passed for Android.
Please attach the test case to the JIRA ticket so QE can test it.

@vishalduggal
Copy link
Contributor

I am going to accept this PR as is. There are some problems with the iOS implementation (formatting, un-required checks etc) but that will be fixed in a subsequent PR.

APPROVED

vishalduggal added a commit that referenced this pull request Jan 15, 2015
[TIMOB-18062] iOS: AttributedString Parity with Android
@vishalduggal vishalduggal merged commit ab63641 into tidev:master Jan 15, 2015
@alexgbernier
Copy link
Contributor

Custom fonts don't appear to be working: https://jira.appcelerator.org/browse/AC-70

@ashcoding ashcoding deleted the TIMOB-18062 branch May 21, 2015 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants