Skip to content

Commit

Permalink
element migrated
Browse files Browse the repository at this point in the history
  • Loading branch information
rvilarl committed Apr 7, 2021
1 parent 95623df commit 95b1e98
Showing 1 changed file with 149 additions and 37 deletions.
186 changes: 149 additions & 37 deletions src/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,109 @@
import { Vex } from './vex';
import { Registry } from './registry';
import { Flow } from './tables';
import { BoundingBox } from './boundingbox';
import { Font } from './smufl';

export class Element {
static newID() {
return 'auto' + Element.ID++;
/** Element attributes. */
export interface ElementAttributes {
[name: string]: any;
id: string;
el?: SVGSVGElement;
type: string;
classes: Record<string, boolean>;
}

/** Contexts common interface */
export interface RenderContext {
clear(): void;
setFont(family: string, size: number, weight?: string): RenderContext;
setRawFont(font: string): RenderContext;
setFillStyle(style: string): RenderContext;
setBackgroundFillStyle(style: string): RenderContext;
setStrokeStyle(style: string): RenderContext;
setShadowColor(color: string): RenderContext;
setShadowBlur(blur: string): RenderContext;
setLineWidth(width: number): RenderContext;
setLineCap(cap_type: string): RenderContext;
setLineDash(dash: string): RenderContext;
scale(x: number, y: number): RenderContext;
resize(width: number, height: number): RenderContext;
fillRect(x: number, y: number, width: number, height: number): RenderContext;
clearRect(x: number, y: number, width: number, height: number): RenderContext;
beginPath(): RenderContext;
moveTo(x: number, y: number): RenderContext;
lineTo(x: number, y: number): RenderContext;
bezierCurveTo(x1: number, y1: number, x2: number, y2: number, x: number, y: number): RenderContext;
quadraticCurveTo(x1: number, y1: number, x2: number, y2: number): RenderContext;
arc(
x: number,
y: number,
radius: number,
startAngle: number,
endAngle: number,
antiClockwise: boolean
): RenderContext;
glow(): RenderContext;
fill(): RenderContext;
stroke(): RenderContext;
closePath(): RenderContext;
fillText(text: string, x: number, y: number): RenderContext;
save(): RenderContext;
restore(): RenderContext;
openGroup(): Node | undefined;
closeGroup(): void;

/**
* canvas returns TextMetrics, SVG returns SVGRect, Raphael returns {width : number, height : number}. Only width is used throughout VexFlow.
*/
measureText(text: string): { width: number };
}

//** Element style */
export interface Style {
shadowColor?: string;
shadowBlur?: string;
fillStyle?: string;
strokeStyle?: string;
lineWidth?: number;
}

/**
* Element implements a generic base class for VexFlow, with implementations
* of general functions and properties that can be inherited by all VexFlow elements.
*/
export abstract class Element {
protected static ID: number = 1000;

protected context?: RenderContext;

protected rendered: boolean;

protected style?: Style;

private attrs: ElementAttributes;

protected boundingBox?: BoundingBox;

protected fontStack: Font[];

protected musicFont: Font;

protected registry?: Registry;

static newID(): string {
return `auto${Element.ID++}`;
}

constructor({ type } = {}) {
//** Constructor, type is optional. */
constructor({ type } = {} as ElementAttributes) {
this.attrs = {
id: Element.newID(),
el: null,
el: undefined,
type: type || 'Base',
classes: {},
};

this.boundingBox = null;
this.context = null;
this.rendered = false;
this.fontStack = Flow.DEFAULT_FONT_STACK;
this.musicFont = Flow.DEFAULT_FONT_STACK[0];
Expand All @@ -35,28 +122,33 @@ export class Element {
}
}

// set music font
setFontStack(fontStack) {
/** Sets music fonts stack. */
setFontStack(fontStack: Font[]): this {
this.fontStack = fontStack;
this.musicFont = fontStack[0];
return this;
}
getFontStack() {

/** gets music fonts stack. */
getFontStack(): Font[] {
return this.fontStack;
}

// set the draw style of a stemmable note:
setStyle(style) {
/** Sets the draw style of a stemmable note. */
setStyle(style: Style): this {
this.style = style;
return this;
}
getStyle() {

/** Gets the draw style of a stemmable note. */
getStyle(): Style | undefined {
return this.style;
}

// Apply current style to Canvas `context`
applyStyle(context = this.context, style = this.getStyle()) {
/** Applies current style to Canvas `context`. */
applyStyle(context: RenderContext | undefined = this.context, style: Style | undefined = this.getStyle()): this {
if (!style) return this;
if (!context) return this;

context.save();
if (style.shadowColor) context.setShadowColor(style.shadowColor);
Expand All @@ -67,25 +159,32 @@ export class Element {
return this;
}

restoreStyle(context = this.context, style = this.getStyle()) {
/** Restores style of Canvas `context`. */
restoreStyle(context: RenderContext | undefined = this.context, style: Style | undefined = this.getStyle()): this {
if (!style) return this;
if (!context) return this;
context.restore();
return this;
}

// draw with style of an element.
drawWithStyle() {
/** Draws with style of an element. */
drawWithStyle(): void {
this.checkContext();
this.applyStyle();
this.draw();
this.restoreStyle();
}

// An element can have multiple class labels.
hasClass(className) {
/** Draws an element. */
abstract draw(element?: Element, x_shift?: number): void;

/** Checkes if it has a class label (An element can have multiple class labels). */
hasClass(className: string): boolean {
return this.attrs.classes[className] === true;
}
addClass(className) {

/** Adds a class label (An element can have multiple class labels). */
addClass(className: string): this {
this.attrs.classes[className] = true;
if (this.registry) {
this.registry.onUpdate({
Expand All @@ -98,7 +197,8 @@ export class Element {
return this;
}

removeClass(className) {
/** Removes a class label (An element can have multiple class labels). */
removeClass(className: string): this {
delete this.attrs.classes[className];
if (this.registry) {
this.registry.onUpdate({
Expand All @@ -111,27 +211,36 @@ export class Element {
return this;
}

// This is called by the registry after the element is registered.
onRegister(registry) {
/** Call back from registry after the element is registered. */
onRegister(registry: Registry): this {
this.registry = registry;
return this;
}
isRendered() {

/** Returns the rendered status. */
isRendered(): boolean {
return this.rendered;
}
setRendered(rendered = true) {

/** Sets the rendered status. */
setRendered(rendered = true): this {
this.rendered = rendered;
return this;
}

getAttributes() {
/** Returns the element attributes. */
getAttributes(): ElementAttributes {
return this.attrs;
}
getAttribute(name) {

/** Returns an attribute. */
getAttribute(name: string): string {
return this.attrs[name];
}
setAttribute(name, value) {
const id = this.attrs.id;

/** Sets an attribute. */
setAttribute(name: string, value: string): this {
const { id } = this.attrs;
const oldValue = this.attrs[name];
this.attrs[name] = value;
if (this.registry) {
Expand All @@ -141,24 +250,27 @@ export class Element {
return this;
}

getContext() {
/** Returns the context. */
getContext(): RenderContext | undefined {
return this.context;
}
setContext(context) {

/** Sets the context. */
setContext(context?: RenderContext): this {
this.context = context;
return this;
}
getBoundingBox() {

/** Gets the boundingBox. */
getBoundingBox(): BoundingBox | undefined {
return this.boundingBox;
}

// Validators
checkContext() {
/** Validates and returns the context. */
checkContext(): RenderContext {
if (!this.context) {
throw new Vex.RERR('NoContext', 'No rendering context attached to instance');
}
return this.context;
}
}

Element.ID = 1000;

0 comments on commit 95b1e98

Please sign in to comment.