diff --git a/ext/tk/sample/24hr_clock.rb b/ext/tk/sample/24hr_clock.rb new file mode 100644 index 0000000000..60d8072c57 --- /dev/null +++ b/ext/tk/sample/24hr_clock.rb @@ -0,0 +1,286 @@ +#!/usr/bin/env ruby + +require 'tk' + +class Clock + def initialize(clock24 = true) + @clock = (clock24)? 24: 12 + + @size = 200 + @cdot_size = 5 + + @cdot_color = 'black' + @hour_hand_color = 'black' + @minute_hand_color = 'gray25' + @second_hand_color = 'gray50' + + @mark_font = 'Helvetica -14' + @mark_width = 3 + @mark_color = 'black' + @submark_color = 'gray50' + + @c = TkCanvas.new(:width=>2*@size, :height=>2*@size, + :scrollregion=>[-@size, -@size, @size, @size] + ).pack(:fill=>:both, :expand=>true) + + @tag = TkcTag.new(@c) + @hand_tag = TkcTag.new(@c) + + @circle_coords = [[-0.9*@size, -0.9*@size], [0.9*@size, 0.9*@size]] + @oval = TkcOval.new(@c, @circle_coords, :fill=>'white', :tags=>[@tag]) + + f = TkFrame.new.pack + TkLabel.new(f, :text=>'CURRENT:').pack(:side=>:left) + @now = TkLabel.new(f, :text=>'00:00:00').pack(:side=>:left, :padx=>2) + TkLabel.new(f, :text=>' ').pack(:side=>:left) + TkLabel.new(f, :text=>' ').pack(:side=>:right) + @l = TkLabel.new(f, :text=>'00:00').pack(:side=>:right, :padx=>2) + TkLabel.new(f, :text=>'MOUSE-POINTER:').pack(:side=>:right) + + cmd = proc{|x, y| + @l.text = '%02d:%02d' % coords_to_time(@c.canvasx(x), @c.canvasy(y)) + } + @c.bind('Motion', cmd, '%x %y') + @tag.bind('Motion', cmd, '%x %y') + + _create_hands + _create_marks + + timer_proc = proc{ + t = Time.now + @now.text = '%02d:%02d:%02d' % [t.hour, t.min, t.sec] + set_hands(t.hour, t.min, t.sec) + } + + timer_proc.call + @timer = TkRTTimer.start(100, -1, timer_proc) + end + + def _create_marks + @mark_tag = TkcTag.new(@c) + + TkcLine.new(@c, 0, -0.90*@size, 0, -0.85*@size, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@mark_color) + TkcLine.new(@c, 0.90*@size, 0, 0.85*@size, 0, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@mark_color) + TkcLine.new(@c, 0, 0.90*@size, 0, 0.85*@size, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@mark_color) + TkcLine.new(@c, -0.90*@size, 0, -0.85*@size, 0, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@mark_color) + + TkcText.new(@c, [0, -0.92*@size], :text=>0, + :anchor=>'s', :fill=>@mark_color) + TkcText.new(@c, [0.92*@size, 0], :text=>@clock.div(4), + :anchor=>'w', :fill=>@mark_color) + TkcText.new(@c, [0, 0.92*@size], :text=>@clock.div(2), + :anchor=>'n', :fill=>@mark_color) + TkcText.new(@c, [-0.92*@size, 0], :text=>@clock.div(4)*3, + :anchor=>'e', :fill=>@mark_color) + + [30.0, 60.0].each{|angle| + rad = Math::PI * angle / 180.0 + x_base = @size*Math::sin(rad) + y_base = @size*Math::cos(rad) + + x1 = 0.90*x_base + y1 = 0.90*y_base + + x2 = 0.85*x_base + y2 = 0.85*y_base + + TkcLine.new(@c, x1, y1, x2, y2, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@mark_color) + TkcLine.new(@c, x1, -y1, x2, -y2, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@mark_color) + TkcLine.new(@c, -x1, y1, -x2, y2, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@mark_color) + TkcLine.new(@c, -x1, -y1, -x2, -y2, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@mark_color) + + x3 = 0.92*x_base + y3 = 0.92*y_base + + if @clock == 24 + dh = angle.to_i/15 + else # @clock == 12 + dh = angle.to_i/30 + end + + TkcText.new(@c, x3, -y3, :text=>dh, + :anchor=>'sw', :fill=>@mark_color) + TkcText.new(@c, x3, y3, :text=>@clock.div(2)-dh, + :anchor=>'nw', :fill=>@mark_color) + TkcText.new(@c, -x3, y3, :text=>@clock.div(2)+dh, + :anchor=>'ne', :fill=>@mark_color) + TkcText.new(@c, -x3, -y3, :text=>@clock-dh, + :anchor=>'se', :fill=>@mark_color) + } + + if @clock == 24 + [15.0, 45.0, 75.0].each{|angle| + rad = Math::PI * angle / 180.0 + x_base = @size*Math::sin(rad) + y_base = @size*Math::cos(rad) + + x1 = 0.90*x_base + y1 = 0.90*y_base + + x2 = 0.875*x_base + y2 = 0.875*y_base + + TkcLine.new(@c, x1, y1, x2, y2, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@submark_color) + TkcLine.new(@c, x1, -y1, x2, -y2, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@submark_color) + TkcLine.new(@c, -x1, y1, -x2, y2, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@submark_color) + TkcLine.new(@c, -x1, -y1, -x2, -y2, + :tags=>[@tag, @mark_tag], + :width=>@mark_width, :fill=>@submark_color) + } + end + end + + def _create_hands + hour_hand_len = 0.55*@size + minute_hand_len = 0.85*@size + second_hand_len = 0.88*@size + + hour_hand_width = 1.8*@cdot_size + minute_hand_width = 1.0*@cdot_size + second_hand_width = 1 # 0.4*@cdot_size + + @hour_hand_coords = [ + [0, -0.5*@cdot_size], + [hour_hand_width, -0.5*@cdot_size-hour_hand_width], + [hour_hand_width, -hour_hand_len+hour_hand_width], + [0, -hour_hand_len], + [-hour_hand_width, -hour_hand_len+hour_hand_width], + [-hour_hand_width, -0.5*@cdot_size-hour_hand_width], + ] + @minute_hand_coords = [ + [0, -0.5*@cdot_size], + [minute_hand_width, -0.5*@cdot_size - minute_hand_width], + [minute_hand_width, -minute_hand_len+minute_hand_width], + [0, -minute_hand_len], + [-minute_hand_width, -minute_hand_len+minute_hand_width], + [-minute_hand_width, -0.5*@cdot_size-minute_hand_width], + ] + @second_hand_coords = [ + [0, -0.5*@cdot_size], + [second_hand_width, -0.5*@cdot_size - second_hand_width], + [second_hand_width, -second_hand_len+second_hand_width], + [0, -second_hand_len], + [-second_hand_width, -second_hand_len+second_hand_width], + [-second_hand_width, -0.5*@cdot_size-second_hand_width], + ] + + @hour_hand = TkcPolygon.new(@c, @hour_hand_coords, + :tags=>[@tag, @hand_tag], + :outline=>@hour_hand_color, + :fill=>@hour_hand_color) + + @minute_hand = TkcPolygon.new(@c, @minute_hand_coords, + :tags=>[@tag, @hand_tag], + :outline=>@minute_hand_color, + :fill=>@minute_hand_color) + + @second_hand = TkcPolygon.new(@c, @second_hand_coords, + :tags=>[@tag, @hand_tag], + :outline=>@second_hand_color, + :fill=>@second_hand_color) + + @center_dot = TkcOval.new(@c, + [-@cdot_size, -@cdot_size], + [@cdot_size, @cdot_size], + :outline=>@cdot_color, :fill=>@cdot_color) + end + private :_create_hands + + def _raise_hands + @hour_hand.raise + @minute_hand.raise + @second_hand.raise + @center_dot.raise + end + private :_raise_hands + + def _raise_marks + @mark_tag.raise + end + private :_raise_marks + + def set_hands(hh, mm, ss) + ss_angle = Math::PI * ss / 30.0 + mm_angle = Math::PI * (mm + ss/60.0) / 30.0 + hh_angle = Math::PI * (hh + (mm + ss/60.0)/60.0) / (@clock.div(2)) + + @second_hand.coords = @second_hand_coords.collect{|x, y| + r = Math::hypot(y, x) + a = Math::atan2(y, x) + ss_angle + [Math::cos(a) * r, Math::sin(a) * r] + } + + @minute_hand.coords = @minute_hand_coords.collect{|x, y| + r = Math::hypot(y, x) + a = Math::atan2(y, x) + mm_angle + [Math::cos(a) * r, Math::sin(a) * r] + } + + @hour_hand.coords = @hour_hand_coords.collect{|x, y| + r = Math::hypot(y, x) + a = Math::atan2(y, x) + hh_angle + [Math::cos(a) * r, Math::sin(a) * r] + } + + _raise_hands + _raise_marks + end + + def coords_to_time(x, y) + return ((y < 0)? [0, 0]: [@clock.div(2), 0]) if x == 0 + if @clock == 24 + offset = (x<0&&y<0)? 1800.0: 360.0 + m_half = 720.0 + else # @clock == 12 + offset = (x<0&&y<0)? 900.0: 180.0 + m_half = 360.0 + end + (offset + m_half*Math.atan2(y,x)/Math::PI).round.divmod(60) + end + + def create_pie(hh, mm, span, color='red') + if @clock == 24 + start = 90.0 - (hh*60 + mm)/4.0 # 360.0*(hh*60+mm)/(24*60) + extent = -span/4.0 + else # @clock == 12 + start = 90.0 - (hh*60 + mm)/2.0 # 360.0*(hh*60+mm)/(12*60) + extent = -span/2.0 + end + + pie = TkcArc.new(@c, @circle_coords, :tags=>[@tag], + :outline=>'black', 'fill'=>color, + :start=>start, :extent=>extent) + _raise_hands + _raise_marks + pie + end +end + +sched = Clock.new +sched.create_pie(0,0, 60) # 60 minutes from 00:00 +sched.create_pie(6,30, 280, 'green') # 280 minutes from 06:30 +sched.create_pie(15,20, 90, 'blue') # 90 minutes from 15:20 + +Tk.mainloop