(phixonline)--> -- -- demo\rosetta\Clock.exw -- ====================== -- with javascript_semantics include pGUI.e Ihandle dlg, canvas, hTimer cdCanvas cd_canvas procedure draw_hand(atom degrees, atom r, baseangle, baselen, cx, cy) atom a = PI-(degrees+90)*PI/180, -- tip x1 = cos(a)*(r), y1 = sin(a)*(r), -- base x2 = cos(a+PI-baseangle)*baselen, y2 = sin(a+PI-baseangle)*baselen, x3 = cos(a+PI+baseangle)*baselen, y3 = sin(a+PI+baseangle)*baselen cdCanvasSetLineWidth(cd_canvas,1) cdCanvasLine(cd_canvas,cx+x1,cy+y1,cx+x2,cy+y2) cdCanvasLine(cd_canvas,cx+x2,cy+y2,cx+x3,cy+y3) cdCanvasLine(cd_canvas,cx+x3,cy+y3,cx+x1,cy+y1) cdCanvasBegin(cd_canvas,CD_FILL) cdCanvasVertex(cd_canvas,cx+x1,cy+y1) cdCanvasVertex(cd_canvas,cx+x2,cy+y2) cdCanvasVertex(cd_canvas,cx+x3,cy+y3) cdCanvasEnd(cd_canvas) end procedure procedure draw_clock(atom cx, cy, d) atom w = 2+floor(d/25) cdCanvasFont(cd_canvas, "Helvetica", CD_PLAIN, floor(d/15)) cdCanvasSetLineWidth(cd_canvas, w) cdCanvasArc(cd_canvas, cx, cy, d, d, 0, 360) d -= w+8 w = 1+floor(d/50) for i=6 to 360 by 6 do integer h = remainder(i,30)=0 cdCanvasSetLineWidth(cd_canvas, max(floor(w*(1+h)/3),1)) atom a = PI-(i+90)*PI/180, x1 = cos(a)*d/2, x2 = cos(a)*(d/2-w*(2+h)*.66), y1 = sin(a)*d/2, y2 = sin(a)*(d/2-w*(2+h)*.66) cdCanvasLine(cd_canvas, cx+x1, cy+y1, cx+x2, cy+y2) if h then x1 = cos(a)*(d/2-w*4.5) y1 = sin(a)*(d/2-w*4.5) cdCanvasText(cd_canvas,cx+x1,cy+y1,sprintf("%d",{i/30})) end if end for atom {hour,mins,secs,msecs} = date(true)[DT_HOUR..DT_MSEC] if IupGetInt(hTimer,"TIME")<1000 then -- (if showing once a second, always land on exact -- seconds, ie completely ignore msecs, otherwise -- show smooth running (fractional) second hand.) secs += msecs/1000 end if mins += secs/60 hour += mins/60 atom r = d/2 draw_hand(hour*360/12,r-w*9,0.3,d/20,cx,cy) draw_hand(mins*360/60,r-w*2,0.2,d/16,cx,cy) cdCanvasSetForeground(cd_canvas, CD_RED) draw_hand(secs*360/60,r-w*2,0.05,d/16,cx,cy) cdCanvasSetForeground(cd_canvas, CD_BLACK) end procedure function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/) integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE"), r = floor(min(width,height)*0.9), cx = floor(width/2), cy = floor(height/2) cdCanvasActivate(cd_canvas) cdCanvasClear(cd_canvas) draw_clock(cx,cy,r) cdCanvasFlush(cd_canvas) return IUP_DEFAULT end function function timer_cb(Ihandle /*ih*/) IupUpdate(canvas) return IUP_IGNORE end function function map_cb(Ihandle ih) IupGLMakeCurrent(canvas) if platform()=JS then cd_canvas = cdCreateCanvas(CD_IUP, canvas) else atom res = IupGetDouble(NULL, "SCREENDPI")/25.4 cd_canvas = cdCreateCanvas(CD_GL, "10x10 %g", {res}) end if cdCanvasSetBackground(cd_canvas, CD_WHITE) cdCanvasSetForeground(cd_canvas, CD_BLACK) cdCanvasSetTextAlignment(cd_canvas, CD_CENTER) return IUP_DEFAULT end function function canvas_resize_cb(Ihandle /*canvas*/) integer {canvas_width, canvas_height} = IupGetIntInt(canvas, "DRAWSIZE") atom res = IupGetDouble(NULL, "SCREENDPI")/25.4 cdCanvasSetAttribute(cd_canvas, "SIZE", "%dx%d %g", {canvas_width, canvas_height, res}) return IUP_DEFAULT end function procedure main() IupOpen() canvas = IupGLCanvas("RASTERSIZE=350x350") IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"), "ACTION", Icallback("redraw_cb"), "RESIZE_CB", Icallback("canvas_resize_cb")}) hTimer = IupTimer(Icallback("timer_cb"), 40) -- smooth secs -- hTimer = IupTimer(Icallback("timer_cb"), 1000) -- tick seconds dlg = IupDialog(canvas, "TITLE=Clock") IupShow(dlg) IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation if platform()!=JS then IupMainLoop() IupClose() end if end procedure main()