File

lib/common/src/widgets/widgets.commons.ts

Description

Represents any kind of WidgetControl. This class is meant to be extended and not to be instantiated on its own. Every time you want to create a new type of widget, you should define a control class extending this base class. A control class defined this way will serve as indicator of your widget type and consists of all the data and methods, widgets of your new widget type can make use of.

This class does nothing on its own. Howto Widgets

import	{	
			Type,
			InjectionToken,
			Directive
		}							from '@angular/core'

import	{	assert			}		from '@rcc/core'



/**  
 * Represents any kind of WidgetControl. 
 * This class is meant to be extended and not to be instantiated on its own. 
 * Every time you want to create a new type of widget, you should define a control class extending this base class.
 * A control class defined this way will serve as indicator of your widget type and consists of all the data and methods, 
 * widgets of your new widget type can make use of.
 * 
 * This class does nothing on its own. {@link /modules/WidgetsModule.html#readme | Howto Widgets}
 */
export class WidgetControl{}










/**
 * A method that evaluates how well the parent object suits a given instance of a {@link WidgetControl} extension.
 * 
 * Return values are interpreted like this:
 * 
 * ```  
 *   -1: can't handle this kind of WidgetControl instance 
 *    0: can handle this kind of WidgetControl instance - if need be 
 *    1: good at handling this kind of WidgetControl instance 
 * >= 2: specifically made to handle this kind of WidgetControl instance 
 * ```
 * You should very rarely return a value greater than 2.
 * 
 * {@link WidgetsModule|More on Widgets}
 */ 
export type WidgetMatchFn<C extends WidgetControl> = (control : C) => number 









/**
 * Every custom widget component class has to have the static property and the static method of this interface.
 * 
 * {@link /modules/WidgetsModule.html#readme | More on Widgets} 
 */
  
 
export interface WidgetComponentType<C extends WidgetControl = WidgetControl>{

	label?		: string
	controlType : Type<C>    
	widgetMatch : WidgetMatchFn<C>

    new (widgetControl: C): WidgetComponent<C>
}





/** 
 * Every custom WidgetComponent has to extend this class.
 * {@link /modules/WidgetsModule.html#readme | More on Widgets} 
 * 
 * And every extension has to have the following static property and method matching your extension of WidgetControl `MyWidgetControl extends WidgetControl`:
 * ```ts
 * 
 *	class MyWidgetComponent<MyWidgetControl> extends WidgetComponent<MyWidgetControl>{
 * 
 *		static controlType : Type<MyWidgetControl>    
 * 		static widgetMatch : WidgetMatchFn<MyWidgetControl>
 * 		
 * 		constructor(myWidgetControl: MyWidgetControl){
 *			super(myWidgetControl) 
 * 			...
 * 		}
 *	}
 * ```
 * 
 * 
 */ 
 @Directive()
export class WidgetComponent<C extends WidgetControl> {

	static label		: string

	static controlType 	: Type<unknown>
	static widgetMatch 	: WidgetMatchFn<unknown> = () => { throw "WidgetComponent missing static widgetMatch()" }


	constructor(widgetControl: C){


		const staticSelf		        = (this.constructor as WidgetComponentType<C>)
		const widgetComponentTypeName	= staticSelf.name
		const expectedControlType		= staticSelf.controlType
		const actualControlType			= widgetControl.constructor

		assert(widgetControl, 								`${widgetComponentTypeName} -> WidgetComponent.constructor missing static idgetControl.`)
		assert(expectedControlType, 						`${widgetComponentTypeName} -> WidgetComponent.constructor missing static controlType`)
		assert(expectedControlType == actualControlType,	`${widgetComponentTypeName} -> WidgetComponent.constructor controlType mismatch: expected ${expectedControlType.name}, got ${actualControlType.name} instead.`)

		assert(staticSelf.widgetMatch(widgetControl) >= 0,	`${widgetComponentTypeName} -> WidgetComponent.constructor() control mismatch.`)

	}

}








/**
 * Token to register WidgetCompoents.{@link WidgetsModule|More on Widgets}. Don't use this on it's own, instead use {@link provideWidgets}
 */
 export const WIDGETS = new InjectionToken<Type<WidgetComponent<unknown>>>('WidgetComponents')







/**
 * Registers {@link WidgetComponent}s to be used by {@link RccWidgetComponent}. 
 * 
 * * ```
 * @NgModule({
 * 	providers: [
 * 		provideWidgets(MyTranslator, ...),
 * 		...
 * 	],
 * 	...
 * })
 * ```
 */	 
export function provideWidget(widgetComponent: Type<WidgetComponent<unknown>>){

	assert(typeof (widgetComponent as any).controlType == 'function', 'provideWidget: provided widgetComponent lacks static property "controlType"')

	return	{
				provide:	WIDGETS,
				useValue:	widgetComponent,
				multi:		true
			}
				
}

results matching ""

    No results matching ""