add more spacing
[personal-kdebase.git] / workspace / plasma / scriptengines / ruby / examples / applets / clock / contents / code / main.rb
blob7e42cc702439effb3710a24545c11fa057ed9b74
1 =begin
2 /***************************************************************************
3  *   Copyright (C) 2005,2006,2007 by Siraj Razick                          *
4  *   siraj@kdemail.net                                                     *
5  *                                                                         *
6  *   Translated to Ruby by Richard Dale                                    *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with self program; if not, write to the                         *
20  *   Free Software Foundation, Inc.,                                       *
21  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
22  ***************************************************************************/
23 =end
25 require 'plasma_applet'
26 require 'analog_clock_config'
27 require 'timezones_config'
28 require 'calendar'
29 require 'clockapplet'
31 module RubyClock
33 class Main < ClockApplet
35   slots :moveSecondHand, :configAccepted, 
36         'dataUpdated(QString, Plasma::DataEngine::Data)'
38   def initialize(parent, args = nil)
39     super
40     KDE::Global.locale.insertCatalog("libplasmaclock")
42     setHasConfigurationInterface(true)
43     resize(125, 125)
44     setAspectRatioMode(Plasma::Square)
46     @theme = Plasma::Svg.new(self)
47     @theme.imagePath = "widgets/clock"
48     @theme.containsMultipleImages = false
49     @theme.resize(size())
51     @timezone = ""
52     @showTimeString = false
53     @showSecondHand = false
54     @ui = Ui::AnalogClockConfig.new
55     @calendarUi = Ui::Calendar.new
57     @lastTimeSeen = Qt::Time.new
58     @calendar = 0
59     @time = Qt::Time.new
60   end
62   def init
63     cg = config()
64     @showTimeString = cg.readEntry("showTimeString", false)
65     @showSecondHand = cg.readEntry("showSecondHand", false)
66     @fancyHands = cg.readEntry("fancyHands", false)
67     self.currentTimezone = cg.readEntry("timezone", localTimezone())
69     connectToEngine()
70   end
72   def connectToEngine
73     # Use 'dataEngine("ruby-time")' for the ruby version of the engine
74     timeEngine = dataEngine("time")
75     if @showSecondHand
76         timeEngine.connectSource(currentTimezone(), self, 500)
77     else 
78         timeEngine.connectSource(currentTimezone(), self, 6000, Plasma::AlignToMinute)
79     end
80   end
82   def constraintsEvent(constraints)
83     if constraints.to_i & Plasma::FormFactorConstraint.to_i
84       setBackgroundHints(NoBackground)
85     end
87     if constraints.to_i & Plasma::SizeConstraint.to_i
88         @theme.resize(size())
89     end
90   end
92   def shape
93     if @theme.hasElement("hint-square-clock")
94         return super
95     end
97     path = Qt::PainterPath.new
98     path.addEllipse(boundingRect().adjusted(-2, -2, 2, 2))
99     return path
100   end
102   def dataUpdated(source, data)
103     @time = data["Time"].toTime()
104     if @time.minute == @lastTimeSeen.minute &&
105       @time.second == @lastTimeSeen.second
106       # avoid unnecessary repaints
107       return
108     end
110     if @secondHandUpdateTimer
111         @secondHandUpdateTimer.stop
112     end
114     @lastTimeSeen = @time
115     update()
116   end
118   def createClockConfigurationInterface(parent)
119     # TODO: Make the size settable
120     widget = Qt::Widget.new
121     @ui.setupUi(widget)
122     parent.addPage(widget, KDE.i18n("General"), icon)
124     @ui.showTimeStringCheckBox.checked = @showTimeString
125     @ui.showSecondHandCheckBox.checked = @showSecondHand
126   end
128   def clockConfigAccepted()
129     cg = config()
130     @showTimeString = @ui.showTimeStringCheckBox.checked?
131     @showSecondHand = @ui.showSecondHandCheckBox.checked?
133     cg.writeEntry("showTimeString", @showTimeString)
134     cg.writeEntry("showSecondHand", @showSecondHand)
135     update()
137     dataEngine("time").disconnectSource(currentTimezone(), self)
138     connectToEngine
140     constraintsEvent(Plasma::AllConstraints)
141     emit configNeedsSaving
142   end
144   def changeEngineTimezone(oldTimezone, newTimezone)
145     dataEngine("time").disconnectSource(oldTimezone, self)
146     timeEngine = dataEngine("time")
147     if @showSecondHand
148         timeEngine.connectSource(newTimezone, self, 500)
149     else
150         timeEngine.connectSource(newTimezone, self, 6000, Plasma::AlignToMinute)
151     end
152   end
154   def moveSecondHand
155     update
156   end
158   def drawHand(p, rotation, handName)
159     p.save
160     boundSize = boundingRect.size
161     elementRect = @theme.elementRect(handName)
163     p.translate(boundSize.width() / 2, boundSize.height() / 2)
164     p.rotate(rotation)
165     p.translate(-elementRect.width / 2, -(@theme.elementRect("clockFace").center.y - elementRect.top))
166     @theme.paint(p, Qt::RectF.new(Qt::PointF.new(0.0, 0.0), elementRect.size), handName)
168     p.restore
169   end
171   def paintInterface(p, option, rect)
172     tempRect = Qt::RectF.new(0, 0, 0, 0)
174     boundSize = geometry.size
176     p.renderHint = Qt::Painter::SmoothPixmapTransform
178     minutes = 6.0 * @time.minute - 180
179     hours = 30.0 * @time.hour - 180 + ((@time.minute / 59.0) * 30.0)
181     @theme.paint(p, Qt::RectF.new(rect), "ClockFace")
183     if @showTimeString
184       fm = Qt::FontMetrics.new(Qt::Application.font)
185       margin = 4
186       if @showSecondHand
187         # FIXME: temporary time output
188         time = @time.toString
189       else
190         time = @time.toString("hh:mm")
191       end
193       textRect = Qt::Rect.new((rect.width/2 - fm.width(time) / 2),((rect.height / 2) - fm.xHeight * 4),
194                   fm.width(time), fm.xHeight())
196       p.pen = Qt::NoPen
197       background = Plasma::Theme.defaultTheme.color(Plasma::Theme::BackgroundColor)
198       background.setAlphaF(0.5)
199       p.brush = Qt::Brush.new(background)
201       p.setRenderHint(Qt::Painter::Antialiasing, true)
202       p.drawPath(Plasma::PaintUtils.roundedRectangle(Qt::RectF.new(textRect.adjusted(-margin, -margin, margin, margin)), margin))
203       p.setRenderHint(Qt::Painter::Antialiasing, false)
205       p.pen = Plasma::Theme::defaultTheme.color(Plasma::Theme::TextColor)
206         
207       p.drawText(textRect.bottomLeft, time)
208     end
210     # Make sure we paint the second hand on top of the others
211     if @showSecondHand
212       anglePerSec = 6.0
213       seconds = anglePerSec * @time.second() - 180
215       if @fancyHands
216         if @secondHandUpdateTimer.nil?
217           @secondHandUpdateTimer = Qt::Timer.new(self)
218           connect(@secondHandUpdateTimer, SIGNAL(:timeout), self, SLOT(:moveSecondHand))
219         end
221         if !@secondHandUpdateTimer.active?
222           @secondHandUpdateTimer.start(50)
223           @animationStart = Qt::Time.currentTime.msec
224         else
225           runTime = 500
226           m = 1.0 # Mass
227           b = 1.0 # Drag coefficient
228           k = 1.5 # Spring constant
229           gamma = b / (2 * m) # Dampening constant
230           omega0 = Math.sqrt(k / m)
231           omega1 = Math.sqrt(omega0 * omega0 - gamma * gamma)
232           elapsed = Qt::Time.currentTime().msec() - @animationStart
233           t = (4 * Math::PI) * (elapsed / runTime)
234           val = 1 + exp(-gamma * t) * -Math.cos(omega1 * t)
236           if elapsed > runTime
237             @secondHandUpdateTimer.stop
238           else
239             seconds += -anglePerSec + (anglePerSec * val)
240           end
241         end
242       end
243     end
245     if @theme.hasElement("HourHandShadow")
246         p.translate(1,3)
248         drawHand(p, hours, "HourHandShadow")
249         drawHand(p, minutes, "MinuteHandShadow")
251         if @showSecondHand
252             drawHand(p, seconds, "SecondHandShadow")
253         end
255         p.translate(-1,-3)
256     end
258     drawHand(p, hours, "HourHand")
259     drawHand(p, minutes, "MinuteHand")
260     if @showSecondHand
261         drawHand(p, seconds, "SecondHand")
262     end
264     p.save
265     @theme.resize(boundSize)
266     elementSize = Qt::SizeF.new(@theme.elementSize("HandCenterScrew"))
267     tempRect.size = elementSize
268     p.translate(boundSize.width / 2.0 - elementSize.width / 2.0, boundSize.height / 2.0 - elementSize.height / 2.0)
269     @theme.paint(p, tempRect, "HandCenterScrew")
270     p.restore
272     @theme.paint(p, Qt::RectF.new(rect), "Glass")
273   end