--****************************************************************************** --* * --* File: Chime.lua Revision: 1.0 * --* * --* Contents: a simple digital chime * --* * --* Creation: 04.03.2002 Last Modification: 04.03.2002 * --* * --* Platform: IBM-compatible PC running Windows 98SE * --* * --* Environment: Lua 4.0, TkLua 4.0 * --* * --* Author: Andreas Rozek Phone: ++49 (711) 6770682 * --* Kirschblütenweg 15 Fax: - * --* D-70569 Stuttgart EMail: Andreas.Rozek@T-Online.De * --* Germany * --* * --* URL: http://www.Andreas-Rozek.de/ * --* * --* Copyright: the software is published under the "GNU Lesser General Pub- * --* lic License" (see "http://www.fsf.org/copyleft/lesser.html" * --* for additional information) * --* * --* Comments: (none) * --* * --****************************************************************************** --**** global constants and variables **** HourTensView, HourUnitsView = nil; -- shows the hours ColonView = nil; -- shows a blinking colon MinuteTensView, MinuteUnitsView = nil; -- shows the minutes AlarmCheck = nil; -- allows to switch the audible alarm on/off StatusBar = nil; -- shows the actual program status SevenSegmentDigit = { -- list of all seven-segment images "./SevenSegment_1.gif","./SevenSegment_2.gif","./SevenSegment_3.gif", "./SevenSegment_4.gif","./SevenSegment_5.gif","./SevenSegment_6.gif", "./SevenSegment_7.gif","./SevenSegment_8.gif","./SevenSegment_9.gif"; [0]="./SevenSegment_0.gif" }; SevenSegmentColon = { -- list of all colon images [0]="./SevenSegment_noColon.gif", [1]="./SevenSegment_Colon.gif" }; oldHours, oldMinutes = nil; -- used to detect significant time changes --**** local constants and variables **** local Icon = "Chime.gif";-- specifying the file name is already sufficient local Title = "Chime"; local Subtitle = "a simple digital chime"; --****************************************************************************** --* * --* processTick processes a timer tick * --* * --****************************************************************************** function processTick (required) local a,b,hours,minutes,seconds = strfind(date(),"(%d*)%:(%d*)%:(%d*)$"); ColonView.image=SevenSegmentColon[mod(seconds,2)]; required = required or ((hours ~= oldHours) or (minutes ~= oldMinutes)); if required then showTime(hours,minutes); updateUserInterface(hours,minutes); oldHours,oldMinutes = hours,minutes; end; end; --****************************************************************************** --* * --* showTime displays the actual time * --* * --****************************************************************************** function showTime (hours,minutes) HourTensView.image=SevenSegmentDigit[floor(hours/10)]; HourUnitsView.image=SevenSegmentDigit[mod(hours,10)]; MinuteTensView.image=SevenSegmentDigit[floor(minutes/10)]; MinuteUnitsView.image=SevenSegmentDigit[mod(minutes,10)]; end; --****************************************************************************** --* * --* updateUserInterface updates user interface according to actual state * --* * --****************************************************************************** function updateUserInterface (hours,minutes) if (AlarmCheck.current == 1) then -- alarm is enabled local AlarmTime = mod(minutes,30); if (AlarmTime == 0) then StatusBar.text = "(alarm is running)"; tkeval("bell"); -- a sound file would be preferable StatusBar.text = ""; elseif (AlarmTime <= 23) then StatusBar.text = "next warning in "..(25-AlarmTime).." minutes"; elseif (AlarmTime == 24) then StatusBar.text = "next warning in 1 minute"; elseif (AlarmTime == 25) then StatusBar.text = "next alarm in 5 minutes"; tkeval("bell"); -- a sound file would be preferable elseif (AlarmTime <= 28) then StatusBar.text = "next alarm in "..(30-AlarmTime).." minutes"; else StatusBar.text = "next alarm in 1 minute"; end; else -- alarm is disabled StatusBar.text = "(alarm is disabled)"; end; end; --****************************************************************************** --* * --* main program * --* * --****************************************************************************** --**** preload any seven-segment images **** for i=0,9 do local TkImage = tkeval("image create photo -file",SevenSegmentDigit[i]); SevenSegmentDigit[i] = TkImage[1]; -- looks strange, but works... end for i=0,1 do local TkImage = tkeval("image create photo -file",SevenSegmentColon[i]); SevenSegmentColon[i] = TkImage[1]; -- looks strange, but works... end --**** define window components **** local IconLabel, TitleLabel, SubtitleLabel = nil; -- title area components local UpperSeparator, LowerSeparator = nil; -- visual separators IconLabel = tklabel{image=Icon, anchor="center", width=32, height=32}; TitleLabel = tklabel{Title; anchor="e", font="-*-helvetica-bold-o-*--16"}; SubtitleLabel = tklabel{Subtitle; anchor="e", font="-*-helvetica-bold-r-*--12"}; UpperSeparator = tkframe{relief="groove", borderwidth=2, height=2}; HourTensView = tklabel{image="./SevenSegment.gif"}; -- preloads dummy image HourUnitsView = tklabel{image="./SevenSegment.gif"}; -- dto. ColonView = tklabel{image="./SevenSegment_noColon.gif"}; MinuteTensView = tklabel{image="./SevenSegment.gif"}; -- dto. MinuteUnitsView = tklabel{image="./SevenSegment.gif"}; -- dto. AlarmCheck = tkcheckbutton{ "Audible Alarm"; anchor="w", font="-*-helvetica-medium-r-*--11", command="processTick(1)"-- actually updates user interface }; LowerSeparator = tkframe{relief="groove", borderwidth=2, height=2}; StatusBar = tklabel{""; anchor="w", font="-*-helvetica-medium-r-*--11"}; --**** construct application window **** local MainWindow = tkmain{ tkframe{ IconLabel, {side="left"}, TitleLabel, {side="top", fill="x", expand=1}, SubtitleLabel, {side="top", fill="x", expand=1} }, {side="top", fill="x", expand=1}, UpperSeparator, {side="top", fill="x"}, tkframe{ HourTensView, {side="left"}, HourUnitsView, {side="left"}, ColonView, {side="left"}, MinuteTensView, {side="left"}, MinuteUnitsView, {side="left"} }, {side="top", anchor="center", pady=4}, AlarmCheck, {side="top", fill="x"}, LowerSeparator, {side="top", fill="x"}, StatusBar, {side="top", fill="x"} }; --**** initialize user interface **** AlarmCheck.current = 1; -- activates the audible alarm processTick(1); -- updates the display to reflect the current state --**** display application window **** MainWindow:title(Title.." - "..Subtitle); MainWindow:show(); -- also triggers a window layout MainWindow:resizable(0,0); -- disables window size changes MainWindow:raise(); -- brings the window into the foreground --**** start continous display **** tktimer(1000,function() processTick(); end); --**** provide an explicit method to terminate this program! **** MainWindow:protocol("WM_DELETE_WINDOW", "print('done...'); tkexit()");