/** * Created by rburson on 3/18/16. */ import * as React from 'react' import { CvAction, CvActionCallback, CvActionFiredResult, CvState, CvProps, CvBaseMixin, CvContext, CvNavigationResult, CvDetailsPane, CvDetailsPaneCallback, CvRecord, CvStateChangeResult, CvEvent, CvValueProvider, CvActionHandlerParams, ColorUtil, DateUtil, CvValueListener, CvImagePackageDelete, CvImagePackagePick, CvImagePackageUndo, CvImageProducer } from 'catreact' import { CvAttributeCellValueDef, CvCellValueDef, CvDataAnno, CvImage, CvDetailsPanelControls, CvDetailsPanelCommitCancelControls } from './catreact-html' import { FormContext, EntityRec, CellValueDef, CellDef, CodeRef, LabelCellValueDef, PrintMarkupContext, PrintMarkupDef, XMLHttpClient, Try, Log, TextAlignment, AttributeCellValueDef, Binding, Button, TimeValue, DetailsContext, ObjUtil, Edges, Checkbox, Prop, PropDef } from 'catavolt-sdk' import { Button as PTButton, Cell, Color, Component as PTComponent, // PT = PrintType Container, DatePicker, Grid, GridLine, Form, Image as PTImage, Label, Layout, Page, RichNum, SignatureCapture, TextAttributes, TextArea, TimePicker } from 'catavolt-sdk' import Component = React.Component; import ReactChild = React.ReactChild; import ReactElement = React.ReactElement; import ComponentClass = React.ComponentClass; import {openSignaturePopup} from "./CvSignaturePopup"; import { CvImageDefaultAddButtonClass, CvImageDefaultRemoveButtonClass, CvImageDefaultSignatureButtonClass, CvImageDefaultUndoButtonClass } from "./CvImage"; import {CSSProperties} from "react"; export interface CvPrintPanelState extends CvState { } /** * Details Panel Properties */ export interface CvPrintPanelProps extends CvProps { formContext?:FormContext; paneRef?:number; printMarkupContext?:PrintMarkupContext; navigationListeners?:Array<(event:CvEvent)=>void>; stateChangeListeners?:Array<(event:CvEvent)=>void>; actionListeners?:Array<(event:CvEvent)=>void>; actionProvider?:CvValueProvider; } interface LineProps { top?:String, left?:String, length?:String, borderStyle?:String, thickness?:String, color?:String } interface LineState { } interface BaseFormState { } interface Listeners { navigationListeners?:Array<(event:CvEvent)=>void>; stateChangeListeners?:Array<(event:CvEvent)=>void>; actionListeners?:Array<(event:CvEvent)=>void>; } interface PositionProps { height:number, width:number, left:number, top:number } interface PrintProps extends CvProps { printBundle:PrintBundle, positionProps:PositionProps }; class PrintBundle { public radioGroupRegistry = new RadioGroupRegistry(); constructor( public printMarkupDef:PrintMarkupDef, public printMarkupContext:PrintMarkupContext, public detailsCallback:CvDetailsPaneCallback, public listeners:Listeners) {} } class RadioGroupRegistryEntry { constructor(public value:any, public cb:()=>void) {}; } class RadioGroupRegistry { private _controls = {}; public addControl(radioGroup:string, value:any, cb:()=>void) { let existing:Array = this._controls[radioGroup]; if (!existing) { existing = new Array(); } // If there is already an entry for then drop it out. existing = existing.filter(rge=>(rge.value != value)); // Add control to registry. existing.push(new RadioGroupRegistryEntry(value, cb)); this._controls[radioGroup] = existing; } public forceUpdate(radioGroup:string):void { let existing:Array = this._controls[radioGroup]; if (existing) { existing.forEach(rge=>(rge.cb())); } } } function hasInitialFocus(context:PrintMarkupContext, propName:string) { return context.printMarkupDef.focusPropName ? propName == context.printMarkupDef.focusPropName : false; } /////////////////////////////////////////////////////////////////////////////// // Form /////////////////////////////////////////////////////////////////////////////// interface PFormProps { printBundle:PrintBundle } class PForm extends React.Component { public static pageSeparatorHeight:number=35; childrenFromModel(): Array { const bundle = this.props.printBundle; const form=bundle.printMarkupDef.printMarkupModel; let answer=new Array(); let pagePP = {height:form.layout.singleHeightNum(), width:form.layout.singleWidthNum(), left:0, top:0 }; let separatorPP = {height:PForm.pageSeparatorHeight, width:1, left:0, top:0 }; for (let i:number=0; i < form.pageChildren.length; i++) { let p:Page=form.pageChildren[i]; answer.push(); if (i); } } return answer; } render() { const form=this.props.printBundle.printMarkupDef.printMarkupModel; const formHeight = form.layout.singleHeightNum() * form.pageChildren.length + (form.pageChildren.length-1) * PForm.pageSeparatorHeight; const style:CSSProperties={position:"relative", height: formHeight, width:form.layout.singleWidthNum(), marginLeft:5, marginBottom:5}; const styleCentered={height: formHeight, width:form.layout.singleWidthNum()}; return
{this.childrenFromModel()}
} } /////////////////////////////////////////////////////////////////////////////// // Page /////////////////////////////////////////////////////////////////////////////// interface PPageProps extends PrintProps { page:Page, backgroundColor:Color } class PPage extends React.Component { render() { let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, {backgroundColor:ColorUtil.toColor(this.props.backgroundColor)}); return
{ CvPrintUtil.gridsAsChildren(this.props.printBundle, this.props.page.gridChildren, this.props.positionProps.width) }
} } /////////////////////////////////////////////////////////////////////////////// // Page Separator /////////////////////////////////////////////////////////////////////////////// class PPageSeparator extends React.Component { render() { let style = { height:this.props.positionProps.height, width:this.props.positionProps.width} return
} } /////////////////////////////////////////////////////////////////////////////// // Grid /////////////////////////////////////////////////////////////////////////////// interface GridProps extends PrintProps { grid:Grid, parentSize:number } class PGrid extends React.Component { childrenFromModel(props:GridProps): Array { // The top is a little tricky. Keep a running total of all child heights added. Subtracting this gets // our cell to the top. Then add in a running total based on the row we are working on. let allAddedHeights=0; let currentRowOffset=0; let prevTop:number=0; let answer:Array=[]; let row=0; let grid:Grid=this.props.grid; grid.layout.heights.map(function(hrn) { let nextLeft:number=0; let height=hrn.resolveWithFill(props.parentSize); let col=0; grid.layout.widths.map(function(wrn) { let c=grid.cellChildren[row][col]; let width = wrn.resolveWithFill(props.parentSize); let myTop=currentRowOffset-allAddedHeights; let pp = {height:height, width:width, left:nextLeft, top:myTop } answer.push(); nextLeft+=width; col++; }); currentRowOffset+=height; row++; }); return answer; } render() { let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, {}); return
{this.childrenFromModel(this.props)}
} } /////////////////////////////////////////////////////////////////////////////// // Cell /////////////////////////////////////////////////////////////////////////////// interface CellProps extends PrintProps { cell:Cell } class PCell extends React.Component { render() { let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, {}); if (this.props.cell.backgroundColor) { style["backgroundColor"]=ColorUtil.toColor(this.props.cell.backgroundColor); } return
{CvPrintUtil.gridsAsChildren(this.props.printBundle, this.props.cell.gridChildren, this.props.cell.cellWidth)} {CvPrintUtil.componentsAsChildren(this.props.printBundle, this.props.cell.componentChildren, this.props.cell.cellWidth, this.props.cell.cellHeight)}
} } /////////////////////////////////////////////////////////////////////////////// // GridLines /////////////////////////////////////////////////////////////////////////////// interface GridLinesProps extends PrintProps { grid:Grid } class PGridLines extends React.Component { private OVERFLOW=5; componentDidMount() { this.updateCanvas(); } updateCanvas():void { let canvas:HTMLCanvasElement = this.refs["mycanvas"] as HTMLCanvasElement; // var canvas:HTMLCanvasElement = document.getElementById("mycanvas") as HTMLCanvasElement; let ctx:CanvasRenderingContext2D = canvas.getContext("2d"); ctx.globalCompositeOperation = 'source-over'; ctx.strokeStyle = "black"; for (let gl of this.props.grid.gridLines) { ctx.beginPath(); ctx.lineWidth = gl.lineWidth; ctx.lineCap = "square"; ctx.moveTo(gl.start.x+this.OVERFLOW, gl.start.y+this.OVERFLOW); ctx.lineTo(gl.end.x+this.OVERFLOW, gl.end.y+this.OVERFLOW); ctx.stroke(); } } render() { // Adjust the positionProps to account for the overflow. The overlfow allows the lines to exceed the bounds. let newPP = { height:this.props.positionProps.height+this.OVERFLOW*2, width:this.props.positionProps.width+this.OVERFLOW*2, left:this.props.positionProps.left-this.OVERFLOW, top:this.props.positionProps.top-this.OVERFLOW} let style = CvPrintUtil.applySizeAndLocationStyle(newPP, {pointerEvents:"none"}); return
} } //***************************************************************************** // Components //***************************************************************************** /////////////////////////////////////////////////////////////////////////////// // Button /////////////////////////////////////////////////////////////////////////////// interface ButtonProps extends PrintProps { button:PTButton } class PButton extends React.Component { render() { let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, {cursor:"pointer"}); if (!this.props.button.urlString) return null; const path = this.props.button.binding.path; const leader = "catavolt:action:name:"; let actionID = ""; if (path && path.length > leader.length) { actionID = path.substr(leader.length); } return } } /////////////////////////////////////////////////////////////////////////////// // Checkbox /////////////////////////////////////////////////////////////////////////////// interface CheckboxProps extends PrintProps { checkbox:Checkbox } interface CheckboxState extends BaseFormState { radioGroupChanged:number } class PCheckbox extends React.Component { canvasFromRef:HTMLCanvasElement; constructor(props) { super(props); this.state = {radioGroupChanged: 0}; } componentDidUpdate() { this.updateCanvas(this.canvasFromRef); } updateCanvas(canvasParm:HTMLCanvasElement):void { this.canvasFromRef = canvasParm; if (this.canvasFromRef) { // var canvas:HTMLCanvasElement = document.getElementById("mycanvas") as HTMLCanvasElement; let ctx: CanvasRenderingContext2D = this.canvasFromRef.getContext("2d"); ctx.globalCompositeOperation = 'source-over'; ctx.strokeStyle = "black"; let h:number = this.canvasFromRef.height; let w:number = this.canvasFromRef.width; ctx.clearRect(0,0,w,h); // Fill with appropriate color if (this._isSeleced()) { ctx.fillStyle = ColorUtil.toColor(this.props.checkbox.checkedColor); } else { ctx.fillStyle = ColorUtil.toColor(this.props.checkbox.uncheckedColor); } ctx.fillRect(0,0,w,h); // Draw the framing outline if there is a lineWidth if (this.props.checkbox.lineWidth > 0) { ctx.beginPath(); ctx.lineWidth = this.props.checkbox.lineWidth; ctx.lineCap = "square"; ctx.moveTo(0, 0); ctx.lineTo(0, h); ctx.lineTo(w, h); ctx.lineTo(w, 0); ctx.lineTo(0, 0); if (this._isSeleced()) { ctx.moveTo(0, 0); ctx.lineTo(w, h); ctx.moveTo(0, h); ctx.lineTo(w, 0); } ctx.stroke(); } } } _isSeleced() { const b = this._binding(); if (b.propertyName) { var prop: Prop = this.props.printBundle.printMarkupContext.buffer.propAtName(b.propertyName); var propDef: PropDef = this.props.printBundle.printMarkupContext.entityRecDef.propDefAtName(b.propertyName); } if (!prop) return false; // To be called again when there is data let pv = (prop.value instanceof CodeRef) ? (prop.value as CodeRef).code : prop.value; let tv = this._trueValue(); return (tv == pv); } _trueValue() { return this._binding().hasConstant ? this._binding().constantValue : true } render() { const b = this._binding(); if (b.hasConstant) { this.props.printBundle.radioGroupRegistry.addControl(this.props.checkbox.radioGroup, this._trueValue(), ()=>{ this._forceRefresh()}); } if (b.propertyName) { var prop: Prop = this.props.printBundle.printMarkupContext.buffer.propAtName(b.propertyName); var propDef: PropDef = this.props.printBundle.printMarkupContext.entityRecDef.propDefAtName(b.propertyName); } let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, {}); style = CvPrintUtil.applyPaddingStyleToSizeAndLoc(this.props.checkbox.padding, style); if (!this._isReadOnly(prop)) { style["cursor"] = "pointer"; } return
{ this.updateCanvas(c)} } height={style.height} width={style.width} />
} _forceRefresh():void { let current:number = this.state && !isNaN(this.state.radioGroupChanged) ? this.state.radioGroupChanged : 0; this.setState( {radioGroupChanged: ++current} ); } _binding (): Binding { return (this.props.checkbox as PTComponent).binding; } _checkboxClick (prop: Prop, propDef: PropDef, e: any) { if (!this._isReadOnly(prop)) { let cb: CvDetailsPaneCallback = this.props.printBundle.detailsCallback; if (!this._isSeleced()) { // if(this.props.valueChangeListener) this.props.valueChangeListener(propName, propDef, true); cb.setPropValue(prop.name, this._trueValue()); } else { // if(this.props.valueChangeListener) this.props.valueChangeListener(propName, propDef, false); if (!this._binding().hasConstant) { cb.setPropValue(prop.name, false); } } if (this._binding().hasConstant) { this.props.printBundle.radioGroupRegistry.forceUpdate(this.props.checkbox.radioGroup); } else { this.setState( {radioGroupChanged: this.state.radioGroupChanged + 1} ); // this.updateCanvas(); } } } _isReadOnly(prop:Prop):boolean { return prop ? this.props.printBundle.printMarkupContext.isReadModeFor(prop.name) : true; } }; /////////////////////////////////////////////////////////////////////////////// // Date /////////////////////////////////////////////////////////////////////////////// interface DateProps extends PrintProps { datePicker:DatePicker } class PDatePicker extends React.Component { render() { let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, {}); style = CvPrintUtil.applyTextAttributes(this.props.positionProps.height, this.props.datePicker.textAttributes, style); style = CvPrintUtil.applyPaddingStyle(this.props.datePicker.padding, style); const b: Binding = this.props.datePicker.binding; let prop: Prop = this.props.printBundle.printMarkupContext.buffer.propAtName(b.propertyName); let propDef: PropDef = this.props.printBundle.printMarkupContext.entityRecDef.propDefAtName(b.propertyName); if (!prop) return null; let isReadOnly = this.props.printBundle.printMarkupContext.isReadModeFor(prop.name); let val:string = null; if (prop.value) { // Build the ISO string because toISOString() will adjust for timezone, which we don't want. val = DateUtil.toISOFormatNoOffset(prop.value); } const focusFn = (ref)=>{ if(ref && hasInitialFocus(this.props.printBundle.printMarkupContext, prop.name)) ref.focus(); } return } _datePickerChange (prop: Prop, propDef: PropDef, e: any) { if (prop) { let cb: CvDetailsPaneCallback = this.props.printBundle.detailsCallback; cb.setPropValue(prop.name, e.currentTarget.value); } } } /////////////////////////////////////////////////////////////////////////////// // Image /////////////////////////////////////////////////////////////////////////////// interface ImageProps extends PrintProps { image:PTImage } class PImage extends React.Component { render() { let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, {}); if (!this.props.image.urlString) return null; return } } /////////////////////////////////////////////////////////////////////////////// // Label /////////////////////////////////////////////////////////////////////////////// interface LabelProps extends PrintProps { label:Label } class PLabel extends React.Component { render() { let style:CSSProperties = {wordWrap: "break-word", wordBreak: "keep-all", textOverflow:"clip", overflow:"hidden" }; style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, style); style["pointerEvents"] = "none"; // Labels may be on top of checkboxes style = CvPrintUtil.applyTextAttributes(this.props.positionProps.height, this.props.label.textAttributes, style); style = CvPrintUtil.applyPaddingStyle(this.props.label.padding, style); return

{this.props.label.text}

} } /////////////////////////////////////////////////////////////////////////////// // Signature /////////////////////////////////////////////////////////////////////////////// interface SignatureProps extends PrintProps { signature:SignatureCapture, attributeCellValueDef:AttributeCellValueDef } interface SignatureState extends BaseFormState { imageListener: CvValueListener } class PSignatureCapture extends React.Component { render() { let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps); const b = this.props.signature.binding; const readOnly = this.props.printBundle.printMarkupContext.isReadModeFor(b.propertyName); const detailsContext = this.props.printBundle.printMarkupContext; const detailsCallback = this.props.printBundle.detailsCallback; const emptyClassSelector = (propDef:PropDef, defaultClass?:string):string => { return "cv-print-control" } const hasFocus = hasInitialFocus(this.props.printBundle.printMarkupContext, b.propertyName); let imageProducers:Array = null; if (!readOnly) { imageProducers = [ { prodImageCB: (listener: CvValueListener)=> { openSignaturePopup(listener, this.props.signature, {width: style.width, height: style.height}); }, buttonClassName: CvImageDefaultSignatureButtonClass, includeWhenImageisPresent: true, includeWhenImageIsMissing: true, includeWhenImageIsDeleted: true } ]; } return } } /////////////////////////////////////////////////////////////////////////////// // Time /////////////////////////////////////////////////////////////////////////////// interface TimeProps extends PrintProps { timePicker:TimePicker } class PTimePicker extends React.Component { render() { let style = CvPrintUtil.applySizeAndLocationStyle(this.props.positionProps, {}); style = CvPrintUtil.applyTextAttributes(this.props.positionProps.height, this.props.timePicker.textAttributes, style); style = CvPrintUtil.applyPaddingStyle(this.props.timePicker.padding, style); const b: Binding = this.props.timePicker.binding; let prop: Prop = this.props.printBundle.printMarkupContext.buffer.propAtName(b.propertyName); let propDef: PropDef = this.props.printBundle.printMarkupContext.entityRecDef.propDefAtName(b.propertyName); if (!prop) return null; let isReadOnly = this.props.printBundle.printMarkupContext.isReadModeFor(prop.name); let val:string = null; if (prop.value) { val = (prop.value as TimeValue).toDateValue().toTimeString().substr(0, 8); } const focusFn = (ref)=>{ if(ref && hasInitialFocus(this.props.printBundle.printMarkupContext, prop.name)) ref.focus(); } return } _datePickerChange (prop: Prop, propDef: PropDef, e: any) { if (prop) { let cb: CvDetailsPaneCallback = this.props.printBundle.detailsCallback; cb.setPropValue(prop.name, e.currentTarget.value); } } } /////////////////////////////////////////////////////////////////////////////// // Misc /////////////////////////////////////////////////////////////////////////////// class CvPrintUtil { static applyColorStyle(c:Color, target?:any):any { let answer = ObjUtil.addAllProps(target, {}); // Do not mutate target if (c) { answer["color"] = ColorUtil.toColor(c); } return answer; } static applyFontSizeStyle(size:number, lineCount:number, target?:any) { let answer = ObjUtil.addAllProps(target, {}); // Do not mutate target if (!isNaN(size)) { // if (lineCount > 1) { answer["fontSize"] = size / lineCount * .70 + "px"; // } else { // answer["fontSize"] = size + "px"; // } } return answer; } static applyFontStyle(fs:{bold?:boolean,underline?:boolean,italic?:boolean}, target?:any):any { let answer = ObjUtil.addAllProps(target, {}); // Do not mutate target if (fs.underline) { answer["textDecoration"] = "underline"; } if (fs.bold) { answer["fontWeight"] = "bold"; } if (fs.italic) { answer["fontStyle"] = "italic"; } return answer; } static applyPaddingStyle(p:Edges, target?:any):any { // Not sure this is ever right. Should we always use applyPaddingStyleToSizeAndLoc let answer = ObjUtil.addAllProps(target, {}); // Do not mutate target if (p) { answer["paddingTop"] = p.top; answer["paddingRight"] = p.right; answer["paddingBottom"] = p.bottom; answer["paddingLeft"] = p.left; } return answer; } static applyPaddingStyleToSizeAndLoc(p:Edges, target:any):any { let answer = ObjUtil.addAllProps(target, {}); // Do not mutate target if (p) { let h:number = answer["height"]; let w:number = answer["width"] let left:number = answer["left"] let top:number = answer["top"] answer["height"] = Math.max(0, h - p.top - p.bottom); answer["width"] = Math.max(0, w - p.left - p.right); answer["top"] = top + p.top; answer["left"] = left + p.left; } return answer; } static applySizeAndLocationStyle(pp:PositionProps, target?:any):any { let answer = ObjUtil.addAllProps(target, {}); // Do not mutate target return ObjUtil.addAllProps(answer, {height:pp.height, width:pp.width, position:"absolute", left:pp.left, top:pp.top }); } static applyTextAlignment(t:{textAlignment?:TextAlignment}, target?:any):any { let answer = ObjUtil.addAllProps(target, {}); // Do not mutate target if (t.textAlignment) { if (t.textAlignment.isRight) { answer["textAlign"] = "right" // answer["justifyContent"] = "flex-end" } else if (t.textAlignment.isCenter) { answer["textAlign"] = "center" // answer["justifyContent"] = "center" } else { answer["textAlign"] = "left" // answer["justifyContent"] = "flex-start" } } return answer; } static applyTextAttributes(textSize:number, textAttributes:TextAttributes, target?:any):any { let answer = ObjUtil.addAllProps(target, {}); // Do not mutate target answer = CvPrintUtil.applyColorStyle(textAttributes.textColor, answer); answer = CvPrintUtil.applyTextAlignment(textAttributes, answer); answer = CvPrintUtil.applyFontSizeStyle(textSize, textAttributes.numberOfLines, answer); answer = CvPrintUtil.applyFontStyle(textAttributes, answer); if (textAttributes.numberOfLines > 1) { answer["whiteSpace"] = "pre-wrap"; } return answer; } static buildImageProducers(readOnly:boolean):Array { let imageProducers:Array = null; if (!readOnly) { imageProducers = [ { // Pick a new file with the file chooser. prodImageCB: (listener: CvValueListener)=> { listener(new CvImagePackagePick()) }, buttonClassName: CvImageDefaultAddButtonClass, includeWhenImageisPresent: true, includeWhenImageIsMissing: true, includeWhenImageIsDeleted: true }, { // Delete existing image prodImageCB: (listener: CvValueListener)=> { listener(new CvImagePackageDelete()) }, buttonClassName: CvImageDefaultRemoveButtonClass, includeWhenImageisPresent: true, includeWhenImageIsMissing: false, includeWhenImageIsDeleted: false }, { // Undo previous delete image prodImageCB: (listener: CvValueListener)=> { listener(new CvImagePackageUndo()) }, buttonClassName: CvImageDefaultUndoButtonClass, includeWhenImageisPresent: false, includeWhenImageIsMissing: false, includeWhenImageIsDeleted: true } ]; } return imageProducers; } static componentsAsChildren(printBundle:PrintBundle, components:Array, fillWidth:number, fillHeight:number) { let answer:Array=[]; components.map((c, index) => { let h = c.layout.singleHeightRichNum().resolveWithFill(fillHeight); let w = c.layout.singleWidthRichNum().resolveWithFill(fillWidth); const b: Binding = (c as PTComponent).binding; if (b && b.propertyName) { var acd: AttributeCellValueDef = printBundle.printMarkupDef.orderedCellValueDefs[b.propertyName]; } const pp:PositionProps = {height:h, width:w, left:c.layout.x, top:c.layout.y}; if (c instanceof Label) { answer.push(); } else if (c instanceof Checkbox && b) { answer.push( ); } else if (c instanceof DatePicker && b) { answer.push( ); } else if (c instanceof TimePicker && b) { answer.push( ); } else if (c instanceof SignatureCapture && b) { answer.push( ); } else { if (c instanceof PTComponent) { if (b && b.propertyName) { const detailsContext = printBundle.printMarkupContext; const detailsCallback= printBundle.detailsCallback; let style = CvPrintUtil.applySizeAndLocationStyle(pp, {}); let readOnly = false; // Textish & TextAttributes if (c.textAttributes) { style = CvPrintUtil.applyTextAttributes(c.layout.singleHeightRichNum().resolveWithFill(fillHeight), c.textAttributes, style); } style = CvPrintUtil.applyPaddingStyle(c.padding, style); if (c instanceof PTImage) { // If this is an image, move the width & height to maxWidth & maxHeight and set the width & height // to auto. This should size and center the image in the space but preserve aspect ratio. style = ObjUtil.addAllProps({objectFit:"contain"}, style); } let imageProducers:Array = null; if (c instanceof SignatureCapture) { // Add signature capture here } else if (c instanceof PTImage) { readOnly = !(c as PTImage).allowPickOptions; imageProducers = this.buildImageProducers(readOnly); } const emptyClassSelector = (propDef:PropDef, defaultClass?:string):string => { return "cv-print-control" } // const emptyClassSelector = (propDef:PropDef, defaultClass?:string):string => { return "" } const hasFocus = hasInitialFocus(printBundle.printMarkupContext, b.propertyName); answer.push( ); } else { // Components with no property binding if (c instanceof Button) { answer.push( ); } else if (c instanceof PTImage) { answer.push( ); } } } } }); return answer; } static gridsAsChildren(printBundle:PrintBundle, grids:Array, parentSize:number) { let answer:Array=[]; grids.map(function(g) { let h=g.layout.sumOfHeights(); let w=g.layout.sumOfWidths(parentSize); // Add the Grid containing the cells const pp:PositionProps = {height:h, width:w, left:g.layout.x, top:g.layout.y}; answer.push(); // Add the grid lines element (draws the grid lines on a canvas) answer.push(); }); return answer; } } /////////////////////////////////////////////////////////////////////////////// // CvPrintPanel /////////////////////////////////////////////////////////////////////////////// /** * Renders a Details Panel, styled by CSS */ export let CvPrintPanel = React.createClass({ mixins: [CvBaseMixin], render: function () { return { const printMarkupContext:PrintMarkupContext = cvContext.scopeCtx.scopeObj; const printMarkupDef:PrintMarkupDef = printMarkupContext.printMarkupDef; const printMarkupModel:Form=printMarkupDef.printMarkupModel; const listeners = {navigationListeners:this.props.navigationListeners, stateChangeListeners:this.props.stateChangeListeners, actionListeners:this.props.actionListeners }; const printBundle = new PrintBundle(printMarkupDef, printMarkupContext, detailsCallback, listeners); return ( { return (
{(()=>{ if(printMarkupContext.printMarkupDef.editable) { if(printMarkupContext.isReadMode) { return
} else if (printMarkupContext.isWriteMode){ const cancelButtonText = printMarkupContext.printMarkupDef.cancelButtonText; const commitButtonText = printMarkupContext.printMarkupDef.commitButtonText; return
} } else { return null } })()}
{(()=>{ const cancelButtonText = printMarkupContext.printMarkupDef.cancelButtonText; const commitButtonText = printMarkupContext.printMarkupDef.commitButtonText; return (printMarkupContext.printMarkupDef.editable && printMarkupContext.isWriteMode) ?
: null; })()}
); }}/> ); }}/> }, // componentDidMount() { // this.setState({ // styles: { // top: computeTopWith(this.refs.child), // left: computeLeftWith(this.refs.child) // } // }) // }, _isSectionTitleDef: function (row) { return row.every((cellDef:CellDef)=>{ return cellDef.values.every((cellValueDef:CellValueDef)=>{ return cellValueDef instanceof LabelCellValueDef; })}); }, _cellCount(rows:Array>):number{ return rows.reduce((prev, cellDefRow:Array)=>{ const numCellValueDefs:number = cellDefRow.reduce((prev, cellDef:CellDef)=>{ return cellDef.values ? prev + cellDef.values.length : prev; }, 0); return numCellValueDefs > prev ? numCellValueDefs : prev; }, 0); }, _openWriteMode: function(detailsCallback:CvDetailsPaneCallback) { detailsCallback.openWriteMode((success, error)=>{ }); }, _openReadMode: function(detailsCallback:CvDetailsPaneCallback) { detailsCallback.openReadMode((success, error)=>{ }); }, _refresh: function(detailsCallback:CvDetailsPaneCallback) { detailsCallback.refresh(); }, _save: function(detailsCallback:CvDetailsPaneCallback) { detailsCallback.saveChanges((success, error)=>{ }); } });