output file "Rosetta Code Clock" _window = 1 begin enum 1 _clockView _one _two _three _four _five _six _seven _eight _nine _ten _eleven _twelve end enum local fn BuildWindow CALayerRef layer, hoursLayer, minutesLayer, secondsLayer CAShapeLayerRef shapeLayer, hubLayer CATextLayerRef textLayer BezierPathRef circle, hub CGPoint pt CGRect r, frame CFDateRef dt CFTimeInterval ti CGFloat h, m, s, ha, ma, sa NSUInteger i CFStringRef num CABasicAnimationRef secondsAnimation, minutesAnimation, hoursAnimation // Window r = fn CGRectMake( 0, 0, 500, 500 ) window _window, @"FutureBasic Rosetta Code Clock", r WindowSetBackgroundColor( _window, fn ColorBlack ) // View to hold clock layers view _clockView, r, _window ViewSetWantsLayer( _clockView, YES ) layer = fn ViewLayer( _clockView ) frame = fn ViewFrame( _clockView ) // Blank clock face shapeLayer = fn CAShapeLayerInit circle = fn BezierPathWithOvalInRect( fn CGRectInset( r, 35, 35 ) ) CAShapeLayerSetPath( shapeLayer, circle ) CAShapeLayerSetLineWidth( shapeLayer, 6.5 ) CAShapeLayerSetLineCap( shapeLayer, kCALineCapRound ) CAShapeLayerSetFillColor( shapeLayer, fn ColorDarkGray ) CAShapeLayerSetStrokeColor( shapeLayer, fn ColorWithRGB( 0.711, 0.533, 0.258, 1.0 ) ) CALayerAddSublayer( layer, shapeLayer ) // Clock numerals for i = _one to _twelve if i = _one then pt = fn CGPointMake( frame.size.width / 2 + 95, frame.size.height / 2 + 115 ) : num = @"1" if i = _two then pt = fn CGPointMake( frame.size.width / 2 + 160, frame.size.height / 2 + 45 ) : num = @"2" if i = _three then pt = fn CGPointMake( frame.size.width / 2 + 180, frame.size.height / 2 - 40 ) : num = @"3" if i = _four then pt = fn CGPointMake( frame.size.width / 2 + 155, frame.size.height / 2 - 125 ) : num = @"4" if i = _five then pt = fn CGPointMake( frame.size.width / 2 + 90, frame.size.height / 2 - 190 ) : num = @"5" if i = _six then pt = fn CGPointMake( frame.size.width / 2, frame.size.height / 2 - 215 ) : num = @"6" if i = _seven then pt = fn CGPointMake( frame.size.width / 2 - 90, frame.size.height / 2 - 190 ) : num = @"7" if i = _eight then pt = fn CGPointMake( frame.size.width / 2 - 155, frame.size.height / 2 - 125 ) : num = @"8" if i = _nine then pt = fn CGPointMake( frame.size.width / 2 - 185, frame.size.height / 2 - 40 ) : num = @"9" if i = _ten then pt = fn CGPointMake( frame.size.width / 2 - 155, frame.size.height / 2 + 45 ) : num = @"10" if i = _eleven then pt = fn CGPointMake( frame.size.width / 2 - 90, frame.size.height / 2 + 115 ) : num = @"11" if i = _twelve then pt = fn CGPointMake( frame.size.width / 2, frame.size.height / 2 + 145 ) : num = @"12" textLayer = fn CATextLayerInit CATextLayerSetString( textLayer, num ) CATextLayerSetFont( textLayer, @"Times" ) CATextLayerSetFontSize( textLayer, 50.0 ) CATextLayerSetForegroundColor( textLayer, fn ColorGreen ) CALayerSetAnchorPoint( textLayer, fn CGPointMake( 0.5, 0 ) ) CATextLayerSetAlignmentMode( textLayer, kCAAlignmentCenter ) CALayerSetPosition( textLayer, pt ) CALayerSetBounds( textLayer, fn CGRectMake( 0, 0, 70, 65 ) ) CALayerAddSublayer( layer, textLayer ) next // Hours layer hoursLayer = fn CALayerInit CALayerSetBackgroundColor( hoursLayer, fn ColorWhite ) CALayerSetAnchorPoint( hoursLayer, fn CGPointMake( 0.5, 0 ) ) CALayerSetPosition( hoursLayer, fn CGPointMake( frame.size.width / 2, frame.size.height / 2 ) ) CALayerSetBounds( hoursLayer, fn CGRectMake( 0, 0, 10, frame.size.width / 2 -90 ) ) CALayerSetCornerRadius( hoursLayer, 4.0 ) CALayerAddSublayer( layer, hoursLayer ) // Minutes layer minutesLayer = fn CALayerInit CALayerSetBackgroundColor( minutesLayer, fn ColorWhite ) CALayerSetAnchorPoint( minutesLayer, fn CGPointMake( 0.5, 0 ) ) CALayerSetPosition( minutesLayer, fn CGPointMake( frame.size.width / 2, frame.size.height / 2 ) ) CALayerSetBounds( minutesLayer, fn CGRectMake( 0, 0, 6, frame.size.width / 2 -45 ) ) CALayerSetCornerRadius( minutesLayer, 3.0 ) CALayerAddSublayer( layer, minutesLayer ) // Seconds layer secondsLayer = fn CALayerInit CALayerSetBackgroundColor( secondsLayer, fn ColorWithRGB( 0.502, 0.000, 0.251, 1.0 ) ) CALayerSetAnchorPoint( secondsLayer, fn CGPointMake( 0.5, 0 ) ) CALayerSetPosition( secondsLayer, fn CGPointMake( frame.size.width / 2, frame.size.height / 2 ) ) CALayerSetBounds( secondsLayer, fn CGRectMake( 0, 0, 3, frame.size.width / 2 -35 ) ) CALayerAddSublayer( layer, secondsLayer ) // Timing functions and calculations dt = fn CalendarStartOfDayForDate( fn CalendarCurrent, fn DateInit ) ti = fn DateTimeIntervalSinceDate( fn DateInit, dt ) h = ti / 3600.0 m = ( h - int(h) ) * 60.0 s = ( m - int(m) ) * 60.0 ha = h / 12.0 * 360.0 ma = m / 60.0 * 360.0 sa = s / 60.0 * 360.0 // Rotation calculation CALayerSetTransform( secondsLayer, fn CATransform3DMakeRotation( sa / 180.0 * PI, 0, 0, 1 ) ) CALayerSetTransform( minutesLayer, fn CATransform3DMakeRotation( ma / 180.0 * PI, 0, 0, 1 ) ) CALayerSetTransform( hoursLayer, fn CATransform3DMakeRotation( ha / 180.0 * PI, 0, 0, 1 ) ) // Animations for each clock hand secondsAnimation = fn CABasicAnimationWithKeyPath( @"transform.rotation.z" ) CAMediaTimingSetRepeatCount( secondsAnimation, INFINITY ) CAMediaTimingSetDuration( secondsAnimation, 60 ) CAAnimationSetRemovedOnCompletion( secondsAnimation, NO ) CABasicAnimationSetFromValue( secondsAnimation, @( -sa * PI / 180 ) ) CABasicAnimationSetByValue( secondsAnimation, @( -2 * PI ) ) CAAnimationSetTimingFunction( secondsAnimation, fn CAMediaTimingFunctionWithName( kCAMediaTimingFunctionLinear ) ) CALayerAddAnimation( secondsLayer, secondsAnimation, @"SecondAnimationKey" ) minutesAnimation = fn CABasicAnimationWithKeyPath( @"transform.rotation.z" ) CAMediaTimingSetRepeatCount( minutesAnimation, INFINITY ) CAMediaTimingSetDuration( minutesAnimation, 60 * 60 ) CAAnimationSetRemovedOnCompletion( minutesAnimation, NO ) CABasicAnimationSetFromValue( minutesAnimation, @( -ma * PI / 180 ) ) CABasicAnimationSetByValue( minutesAnimation, @( -2 * PI ) ) CAAnimationSetTimingFunction( minutesAnimation, fn CAMediaTimingFunctionWithName( kCAMediaTimingFunctionLinear ) ) CALayerAddAnimation( minutesLayer, minutesAnimation, @"MinutesAnimationKey" ) hoursAnimation = fn CABasicAnimationWithKeyPath( @"transform.rotation.z" ) CAMediaTimingSetRepeatCount( hoursAnimation, INFINITY ) CAMediaTimingSetDuration( hoursAnimation, 60 * 60 * 12 ) CAAnimationSetRemovedOnCompletion( hoursAnimation, NO ) CABasicAnimationSetFromValue( hoursAnimation, @( -ha * PI / 180 ) ) CABasicAnimationSetByValue( hoursAnimation, @( -2 * PI ) ) CAAnimationSetTimingFunction( hoursAnimation, fn CAMediaTimingFunctionWithName( kCAMediaTimingFunctionLinear ) ) CALayerAddAnimation( hoursLayer, hoursAnimation, @"HoursAnimationKey" ) // Center hub hubLayer = fn CAShapeLayerInit r = fn CGRectMake( 244, 242, 16, 16 ) hub = fn BezierPathWithOvalInRect( r ) CAShapeLayerSetPath( hubLayer, hub ) CAShapeLayerSetLineWidth( hubLayer, 1.5 ) CAShapeLayerSetFillColor( hubLayer, fn ColorBlack ) CALayerAddSublayer( layer, hubLayer ) end fn local fn DoDialog( ev as long, tag as long ) select ( ev ) case _viewWantsUpdateLayer : DialogEventSetBool(YES) case _windowWillClose : end end select end fn on dialog fn DoDialog fn BuildWindow HandleEvents