mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
287 lines
9.1 KiB
Ruby
287 lines
9.1 KiB
Ruby
|
#!/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
|