Merge pull request #3306 from NativeScript/font-refactor

FontStyle and FontWeight enums everywhere
This commit is contained in:
Rossen Hristov
2016-12-16 17:02:07 +02:00
committed by GitHub
8 changed files with 130 additions and 82 deletions

View File

@ -9,7 +9,7 @@ import {
gestureFromString, isIOS, traceEnabled, traceWrite, traceCategories, traceNotifyEvent, printUnregisteredProperties
} from "./view-base";
import { observe as gestureObserve, GesturesObserver, GestureTypes, GestureEventData } from "ui/gestures";
import { Font, parseFont } from "ui/styling/font";
import { Font, parseFont, FontStyle, FontWeight } from "ui/styling/font";
import { fontSizeConverter } from "../styling/converters";
// TODO: Remove this and start using string as source (for android).
@ -1815,12 +1815,8 @@ export const fontSizeProperty = new InheritedCssProperty<Style, number>({
});
fontSizeProperty.register(Style);
export const fontStyleProperty = new InheritedCssProperty<Style, "normal" | "italic">({
name: "fontStyle", cssName: "font-style", defaultValue: "normal", valueChanged: (target, newValue) => {
if (!(newValue === "normal" || newValue === "italic")) {
throw new Error(`font-style should be 'normal' or 'italic'. value: ${newValue}`)
}
export const fontStyleProperty = new InheritedCssProperty<Style, FontStyle>({
name: "fontStyle", cssName: "font-style", defaultValue: FontStyle.NORMAL, valueConverter: FontStyle.parse, valueChanged: (target, newValue) => {
let currentFont = target.fontInternal;
if (currentFont.fontStyle !== newValue) {
target.fontInternal = currentFont.withFontStyle(newValue);
@ -1829,20 +1825,8 @@ export const fontStyleProperty = new InheritedCssProperty<Style, "normal" | "ita
});
fontStyleProperty.register(Style);
export const fontWeightProperty = new InheritedCssProperty<Style, "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900">({
name: "fontWeight", cssName: "font-weight", defaultValue: "normal", valueChanged: (target, newValue) => {
if (!newValue) {
console.trace();
}
// TODO: Console.log errors or throw error?
if (!(newValue === "normal" || newValue === "bold"
|| newValue === "100" || newValue === "200" || newValue === "300"
|| newValue === "400" || newValue === "500" || newValue === "600"
|| newValue === "700" || newValue === "800" || newValue === "900")) {
throw new Error(`Invalid font-weight value: ${newValue}`);
}
export const fontWeightProperty = new InheritedCssProperty<Style, FontWeight>({
name: "fontWeight", cssName: "font-weight", defaultValue: FontWeight.NORMAL, valueConverter: FontWeight.parse, valueChanged: (target, newValue) => {
let currentFont = target.fontInternal;
if (currentFont.fontWeight !== newValue) {
target.fontInternal = currentFont.withFontWeight(newValue);

View File

@ -1,22 +1,23 @@
import { Font as FontDefinition, ParsedFont } from "ui/styling/font";
import { makeValidator, makeParser} from "ui/core/view";
export abstract class FontBase implements FontDefinition {
public static default = undefined;
private _fontFamily: string;
private _fontStyle: "normal" | "italic";
private _fontWeight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
private _fontStyle: FontStyle;
private _fontWeight: FontWeight;
private _fontSize: number;
get fontFamily(): string {
return this._fontFamily;
}
get fontStyle(): "normal" | "italic" {
get fontStyle(): FontStyle {
return this._fontStyle;
}
get fontWeight(): "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900" {
get fontWeight(): FontWeight {
return this._fontWeight;
}
@ -24,16 +25,16 @@ export abstract class FontBase implements FontDefinition {
return this._fontSize;
}
get isBold(): boolean {
return this._fontWeight.toLowerCase() === "bold"
|| this._fontWeight.toLowerCase() === "700";
}
get isItalic(): boolean {
return this._fontStyle.toLowerCase() === "italic";
return this._fontStyle === FontStyle.ITALIC;
}
protected constructor(family: string, size: number, style: "normal" | "italic", weight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900") {
get isBold(): boolean {
return this._fontWeight === FontWeight.BOLD
|| this._fontWeight === "700";
}
protected constructor(family: string, size: number, style: FontStyle, weight: FontWeight) {
this._fontFamily = family;
this._fontSize = size;
this._fontStyle = style;
@ -65,6 +66,29 @@ export abstract class FontBase implements FontDefinition {
}
}
export type FontStyle = "normal" | "italic";
export namespace FontStyle {
export const NORMAL: "normal" = "normal";
export const ITALIC: "italic" = "italic";
export const isValid = makeValidator<FontStyle>(NORMAL, ITALIC);
export const parse = makeParser(isValid, NORMAL);
}
export type FontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
export namespace FontWeight {
export const THIN: "100" = "100";
export const EXTRA_LIGHT: "200" = "200";
export const LIGHT: "300" = "300";
export const NORMAL: "normal" = "normal";
export const MEDIUM: "500" = "500";
export const SEMI_BOLD: "600" = "600";
export const BOLD: "bold" = "bold";
export const EXTRA_BOLD: "800" = "800";
export const BLACK: "900" = "900";
export const isValid = makeValidator<FontWeight>(THIN, EXTRA_LIGHT, LIGHT, NORMAL, "400", MEDIUM, SEMI_BOLD, BOLD, "700", EXTRA_BOLD, BLACK);
export const parse = makeParser(isValid, NORMAL);
}
export function parseFontFamily(value: string): Array<string> {
const result = new Array<string>();
if (!value) {
@ -89,7 +113,10 @@ export module genericFontFamilies {
}
const styles = new Set();
["italic", "oblique"].forEach((val, i, a) => styles.add(val));
[
FontStyle.NORMAL,
FontStyle.ITALIC
].forEach((val, i, a) => styles.add(val));
// http://www.w3schools.com/cssref/pr_font_weight.asp
//- normal(same as 400)
@ -104,7 +131,19 @@ const styles = new Set();
//- 800(Extra Bold / Ultra Bold) (API16 -bold)
//- 900(Black / Heavy) (API21 -black)
const weights = new Set();
["normal", "bold", "100", "200", "300", "400", "500", "600", "700", "800", "900"].forEach((val, i, a) => weights.add(val));
[
FontWeight.THIN,
FontWeight.EXTRA_LIGHT,
FontWeight.LIGHT,
FontWeight.NORMAL,
"400",
FontWeight.MEDIUM,
FontWeight.SEMI_BOLD,
FontWeight.BOLD,
"700",
FontWeight.EXTRA_BOLD,
FontWeight.BLACK
].forEach((val, i, a) => weights.add(val));
export function parseFont(fontValue: string): ParsedFont {
let result: ParsedFont = {

View File

@ -1,4 +1,4 @@
import { FontBase, parseFontFamily, genericFontFamilies, parseFont } from "./font-common";
import { FontBase, parseFontFamily, genericFontFamilies, parseFont, FontWeight } from "./font-common";
import { enabled as traceEnabled, write as traceWrite, categories as traceCategories, messageType as traceMessageType } from "trace";
import * as application from "application";
import * as fs from "file-system";
@ -9,14 +9,12 @@ const FONTS_BASE_PATH = "/fonts/";
const typefaceCache = new Map<string, android.graphics.Typeface>();
let appAssets: android.content.res.AssetManager;
type fontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
export class Font extends FontBase {
public static default = new Font(undefined, undefined, "normal", "normal");
private _typeface: android.graphics.Typeface;
constructor(family: string, size: number, style: "normal" | "italic", weight: fontWeight) {
constructor(family: string, size: number, style: "normal" | "italic", weight: FontWeight) {
super(family, size, style, weight);
}
@ -28,7 +26,7 @@ export class Font extends FontBase {
return new Font(this.fontFamily, this.fontSize, style, this.fontWeight);
}
public withFontWeight(weight: fontWeight): Font {
public withFontWeight(weight: FontWeight): Font {
return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight);
}
@ -134,26 +132,26 @@ function createTypeface(font: Font): android.graphics.Typeface {
return null;
}
function getFontWeightSuffix(fontWeight: string): string {
function getFontWeightSuffix(fontWeight: FontWeight): string {
switch (fontWeight) {
case "100":
case FontWeight.THIN:
return android.os.Build.VERSION.SDK_INT >= 16 ? "-thin" : "";
case "200":
case "300":
case FontWeight.EXTRA_LIGHT:
case FontWeight.LIGHT:
return android.os.Build.VERSION.SDK_INT >= 16 ? "-light" : "";
case "normal":
case FontWeight.NORMAL:
case "400":
case undefined:
case null:
return "";
case "500":
case "600":
case FontWeight.MEDIUM:
case FontWeight.SEMI_BOLD:
return android.os.Build.VERSION.SDK_INT >= 21 ? "-medium" : "";
case "bold":
case FontWeight.BOLD:
case "700":
case "800":
case FontWeight.EXTRA_BOLD:
return "";
case "900":
case FontWeight.BLACK:
return android.os.Build.VERSION.SDK_INT >= 21 ? "-black" : "";
default:
throw new Error(`Invalid font weight: "${fontWeight}"`);

View File

@ -3,8 +3,8 @@
public static default: Font;
public fontFamily: string;
public fontStyle: "normal" | "italic";
public fontWeight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
public fontStyle: FontStyle;
public fontWeight: FontWeight;
public fontSize: number;
public isBold: boolean;
@ -23,10 +23,33 @@
public static equals(value1: Font, value2: Font): boolean;
}
export type FontStyle = "normal" | "italic";
export namespace FontStyle {
export const NORMAL: "normal";
export const ITALIC: "italic";
export function isValid(value: any): boolean;
export function parse(value: string): FontStyle;
}
export type FontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
export namespace FontWeight {
export const THIN: "100";
export const EXTRA_LIGHT: "200";
export const LIGHT: "300";
export const NORMAL: "normal";
export const MEDIUM: "500";
export const SEMI_BOLD: "600";
export const BOLD: "bold";
export const EXTRA_BOLD: "800";
export const BLACK: "900";
export function isValid(value: any): boolean;
export function parse(value: string): FontWeight;
}
interface ParsedFont {
fontStyle?: "normal" | "italic";
fontStyle?: FontStyle;
fontVariant?: string;
fontWeight?: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900",
fontWeight?: FontWeight,
lineHeight?: string,
fontSize?: string,
fontFamily?: string

View File

@ -1,14 +1,14 @@
import { FontBase, parseFontFamily, genericFontFamilies, parseFont } from "./font-common";
import { FontBase, parseFontFamily, genericFontFamilies, parseFont, FontStyle, FontWeight } from "./font-common";
import { enabled as traceEnabled, write as traceWrite, categories as traceCategories, messageType as traceMessageType } from "trace";
import fs = require("file-system");
import * as utils from "utils/utils";
export class Font extends FontBase {
public static default = new Font(undefined, undefined, "normal", "normal");
public static default = new Font(undefined, undefined, FontStyle.NORMAL, FontWeight.NORMAL);
private _uiFont: UIFont;
constructor(family: string, size: number, style: "normal" | "italic", weight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900") {
constructor(family: string, size: number, style: FontStyle, weight: FontWeight) {
super(family, size, style, weight);
}
@ -16,11 +16,11 @@ export class Font extends FontBase {
return new Font(family, this.fontSize, this.fontStyle, this.fontWeight);
}
public withFontStyle(style: "normal" | "italic"): Font {
public withFontStyle(style: FontStyle): Font {
return new Font(this.fontFamily, this.fontSize, style, this.fontWeight);
}
public withFontWeight(weight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"): Font {
public withFontWeight(weight: FontWeight): Font {
return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight);
}
@ -187,33 +187,33 @@ declare const UIFontWeightBold: number; //0.4
declare const UIFontWeightHeavy: number; //0.56
declare const UIFontWeightBlack: number; //0.62
function getiOSFontWeight(fontWeight: string): number {
function getiOSFontWeight(fontWeight: FontWeight): number {
if (!(<any>UIFont).systemFontOfSizeWeight) {
throw new Error("Font weight is available in iOS 8.2 and later.");
}
switch (fontWeight) {
case "100":
case FontWeight.THIN:
return UIFontWeightThin;
case "200":
case FontWeight.EXTRA_LIGHT:
return UIFontWeightUltraLight;
case "300":
case FontWeight.LIGHT:
return UIFontWeightLight;
case "normal":
case FontWeight.NORMAL:
case "400":
case undefined:
case null:
return UIFontWeightRegular;
case "500":
case FontWeight.MEDIUM:
return UIFontWeightMedium;
case "600":
case FontWeight.SEMI_BOLD:
return UIFontWeightSemibold;
case "bold":
case FontWeight.BOLD:
case "700":
return UIFontWeightBold;
case "800":
case FontWeight.EXTRA_BOLD:
return UIFontWeightHeavy;
case "900":
case FontWeight.BLACK:
return UIFontWeightBlack;
default:
throw new Error(`Invalid font weight: "${fontWeight}"`);
@ -248,39 +248,39 @@ function findCorrectWeightString(fontFamily: string, weightStringAlternatives: A
return weightStringAlternatives[0];
}
function getiOSFontFace(fontFamily: string, fontWeight: string, isItalic: boolean): string {
function getiOSFontFace(fontFamily: string, fontWeight: FontWeight, isItalic: boolean): string {
// ... with a lot of fuzzy logic and artificial intelligence thanks to the lack of font naming standards.
let weight: string;
switch (fontWeight) {
case "100":
case FontWeight.THIN:
weight = "Thin";
break;
case "200":
case FontWeight.EXTRA_LIGHT:
weight = findCorrectWeightString(fontFamily, ["Ultra Light", "UltraLight", "Extra Light", "ExtraLight", "Ultra light", "Ultralight", "Extra light", "Extralight"], isItalic);
break;
case "300":
case FontWeight.LIGHT:
weight = "Light";
break;
case "normal":
case FontWeight.NORMAL:
case "400":
case undefined:
case null:
weight = ""; // We dont' need to write Regular
break;
case "500":
case FontWeight.MEDIUM:
weight = "Medium";
break;
case "600":
case FontWeight.SEMI_BOLD:
weight = findCorrectWeightString(fontFamily, ["Demi Bold", "DemiBold", "Semi Bold", "SemiBold", "Demi bold", "Demibold", "Semi bold", "Semibold"], isItalic);
break;
case "bold":
case FontWeight.BOLD:
case "700":
weight = "Bold";
break;
case "800":
case FontWeight.EXTRA_BOLD:
weight = findCorrectWeightString(fontFamily, ["Heavy", "Extra Bold", "ExtraBold", "Extra bold", "Extrabold"], isItalic);
break;
case "900":
case FontWeight.BLACK:
weight = "Black";
break;
default:

View File

@ -1,6 +1,7 @@
declare module "ui/styling/style" {
import { Length, PercentLength, Color, Background, Font, ViewBase, Observable } from "ui/core/view";
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "ui/text-base";
import { FontStyle, FontWeight } from "ui/styling/font";
export interface Thickness {
left: number;
@ -77,8 +78,8 @@ declare module "ui/styling/style" {
public fontSize: number;
public fontFamily: string;
public fontStyle: "normal" | "italic";
public fontWeight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
public fontStyle: FontStyle;
public fontWeight: FontWeight;
public font: string;
public zIndex: number;

View File

@ -9,6 +9,7 @@ import {
} from "ui/layouts/flexbox-layout";
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "ui/text-base";
import { FontStyle, FontWeight } from "ui/styling/font";
export class Style extends Observable implements StyleDefinition {
constructor(public view: ViewBase) {
@ -56,8 +57,8 @@ export class Style extends Observable implements StyleDefinition {
public fontSize: number;
public fontFamily: string;
public fontStyle: "normal" | "italic";
public fontWeight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
public fontStyle: FontStyle;
public fontWeight: FontWeight;
public font: string;
public zIndex: number;

View File

@ -17,6 +17,8 @@
]
},
"exclude": [
"apps",
"tests",
"tns-platform-declarations/node_modules/",
"tns-platform-declarations/package/",
"tns-core-modules/node_modules/",