package displayShelf; import f3.ui.*; import f3.ui.canvas.*; import java.lang.Math; import f3.ui.filter.*; public class TiltingPane extends CompositeNode { public attribute content: Node?; public attribute angle: Number; attribute contentWidth: Number; attribute contentHeight: Number; attribute kPerspective: Number; attribute kFalloff:Number; attribute contentView: Group; function widthForAngle(angle:Number):Number; function makeContent(content:Node, angle:Number): Node; } attribute TiltingPane.kPerspective = 0.15; attribute TiltingPane.kFalloff = 0.4; attribute TiltingPane.contentWidth = bind content.currentWidth; attribute TiltingPane.contentHeight = bind content.currentHeight; trigger on TiltingPane.angle = value { contentView.content = makeContent(content, value); } trigger on TiltingPane.contentWidth = value { if (content.currentWidth > 0 and content.currentHeight > 0) { do later { contentView.content = makeContent(content, angle); } } } trigger on TiltingPane.contentHeight = value { if (content.currentWidth > 0 and content.currentHeight > 0) { do later { contentView.content = makeContent(content, angle); } } } operation TiltingPane.makeContent(content:Node, angle:Number) { var contentWidth = content.currentWidth; var contentHeight = content.currentHeight; var unscaledWidth = contentWidth; var centerX = contentWidth/2; var yPosition = 0; var frameWidth = contentWidth; var frameHeight = contentHeight; var p = Math.sqrt(Math.abs(angle)/90); var horizontalScale = 1 - p; var verticalShear = if angle >= 0 then p * -kPerspective else p * kPerspective; var verticalShearEffect = contentWidth/2 * verticalShear; var frameLeft = 0; function makeTrapezoid(fill:Paint, strokeWidth:Number) { return if angle >= 0 then Path { stroke: fill strokeWidth: strokeWidth d: [MoveTo {x: frameLeft, y: -verticalShearEffect}, LineTo {x: frameLeft, y: frameHeight - verticalShearEffect}, LineTo {x: frameLeft + frameWidth * horizontalScale, y: frameHeight + verticalShearEffect}, LineTo {x: frameLeft + frameWidth * horizontalScale, y: 3 * -verticalShearEffect}, LineTo {x: frameLeft, y: -verticalShearEffect}] } else Path { stroke: fill strokeWidth: strokeWidth d: [MoveTo {x: frameLeft, y: 3*verticalShearEffect}, LineTo {x: frameLeft, y: frameHeight - verticalShearEffect}, LineTo {x: frameLeft + frameWidth * horizontalScale, y: frameHeight + verticalShearEffect}, LineTo {x: frameLeft + frameWidth * horizontalScale, y: verticalShearEffect}, LineTo {x: frameLeft, y: 3*verticalShearEffect}] }; } return Clip { shape: makeTrapezoid(null, 0) var contentView = Group { content: [Group { transform: matrix(horizontalScale, verticalShear, 0, 1, 0, -verticalShearEffect) content: content }] } content: contentView }; } function TiltingPane.widthForAngle(angle:Number):Number { var p = Math.sqrt(Math.abs(angle)/90); var scale = 1 - p; var r = content.currentWidth * scale; return r; } function TiltingPane.composeNode() = Group { attribute: contentView } ;