~ubuntu-branches/ubuntu/natty/lua-gtk/natty

« back to all changes in this revision

Viewing changes to tests/clutter/006-carousel.lua

  • Committer: Bazaar Package Importer
  • Author(s): Enrico Tassi
  • Date: 2009-05-17 18:16:21 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090517181621-9kmdd82nxg54jsio
* new upstream snapshot comprising many more GNOME libraries:
    Gtk, GDK, GLib, Pango, Atk, Libxml2, Cairo, Clutter, Gtkhtml, 
    GtkSourceView, Gio, Gtkspell and GConf. 
* new upstream release includes a new configure script written in Lua,
  no more bashisms there (Closes: #507205)
* renamed binary packages to liblua5.1-gnome-*
* updated standards-version to 3.8.1, no changes needed
* patch to load .so.* version of libraries and not .so (that was requiring
  -dev packages) (Closes: #522087)
* removed redundant Architecture line from the source stanza of control
  (Closes: #498120)
* updated copyright file, Wolfgang Oertl holds it for 2009 too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env lua
 
2
-- vim:sw=4:sts=4
 
3
-- based on http://svn.o-hand.com/repos/clutter/trunk/toys/courasel/
 
4
-- (http://git.clutter-project.org/cgit.cgi?url=toys/tree/courasel)
 
5
 
 
6
require 'clutter'
 
7
 
 
8
-- configuration --
 
9
local init_duration = 1000  -- in ms
 
10
local fps = 20
 
11
local items_init = {
 
12
    { "accessories-text-editor.png", "Text Editor" },
 
13
    { "applications-games.png", "Game" },
 
14
    { "dates.png", "Dates" },
 
15
    { "im-client.png", "Chat" },
 
16
    { "preferences-desktop-theme.png", "Preferences" },
 
17
    { "tasks.png", "Todo List" },
 
18
    { "utilities-terminal.png", "Terminal" },
 
19
    { "web-browser.png", "Browser"},
 
20
}
 
21
local alpha_low = 0x66
 
22
local scale_small = 0.6
 
23
local ms_per_step = 400     -- higher value is lower rotation speed
 
24
-- end configuration --
 
25
 
 
26
local stage, timeline, csw, csh, label, label_behave
 
27
local items = {}            -- actor, move, opacity, scale, text
 
28
local selected_index = 1    -- currently selected item
 
29
local STEP = 360 / #items_init
 
30
local running = 0           -- current direction (-1 or 1) or 0 when stopped
 
31
local alpha_sine_inc        -- alpha function for the movement
 
32
local stop_from_pos = 0     -- at which timeline position the stop was initiated
 
33
local stopping
 
34
local mydir = string.gsub(arg[0], "[%w.-]+$", "")
 
35
 
 
36
 
 
37
---
 
38
-- During the intro, all items start at angle -90 and move at different speeds
 
39
-- to their target positions.  The selected item will be scaled to 1.0 and
 
40
-- have full opacity.
 
41
--
 
42
function introduce_items()
 
43
    for i, item in pairs(items) do
 
44
        item.move:set_angle_start(-90)
 
45
        item.move:set_angle_end(STEP * i)
 
46
 
 
47
        if i == selected_index then
 
48
            item.opacity:set('opacity-end', 0xff)
 
49
            item.scale:set('x-scale-end', 1, 'y-scale-end', 1)
 
50
        end
 
51
    end
 
52
 
 
53
    timeline:start()
 
54
end
 
55
 
 
56
 
 
57
 
 
58
---
 
59
-- Configure the timeline to rotate one item forward or backward, then start
 
60
-- it.
 
61
--
 
62
function rotate_items()
 
63
    local from_index, ang, b, scale, opacity
 
64
    local step = running
 
65
    
 
66
    from_index = selected_index
 
67
    ang = 360 - from_index * STEP + 90
 
68
    selected_index = 1 + (selected_index - step - 1 + #items) % #items
 
69
 
 
70
    for i, item in ipairs(items) do
 
71
        b = item.move
 
72
        b:set_direction(step > 0 and clutter.ROTATE_CW or clutter.ROTATE_CCW)
 
73
        b:set_angle_start(ang)
 
74
        b:set_angle_end(ang + STEP * step)
 
75
 
 
76
        opacity = { alpha_low, alpha_low }
 
77
        scale = { scale_small, scale_small }
 
78
 
 
79
        if i == from_index then
 
80
            opacity[1] = 0xff
 
81
            scale[1] = 1
 
82
        elseif i == selected_index then
 
83
            opacity[2] = 0xff
 
84
            scale[2] = 1
 
85
        end
 
86
 
 
87
        item.opacity:set('opacity-start', opacity[1], 'opacity-end',
 
88
            opacity[2])
 
89
        item.scale:set('x-scale-start', scale[1], 'y-scale-start',
 
90
            scale[1], 'x-scale-end', scale[2], 'y-scale-end', scale[2])
 
91
 
 
92
        ang = ang + STEP
 
93
   end
 
94
 
 
95
    timeline:start()
 
96
end
 
97
 
 
98
 
 
99
-- Key Symbols are not available... yet?
 
100
clutter.Left = 65361
 
101
clutter.Right = 65363
 
102
clutter.q = 113
 
103
 
 
104
local handler_press = {
 
105
    [clutter.Left] = function() running=-1; rotate_items() end,
 
106
    [clutter.Right] = function() running=1; rotate_items() end,
 
107
}
 
108
 
 
109
---
 
110
-- Respond to some key presses.
 
111
--
 
112
function on_key_press(actor, event, self)
 
113
    local sym = event.key:symbol()
 
114
    if sym == clutter.q then
 
115
        clutter.main_quit()
 
116
        return false
 
117
    end
 
118
 
 
119
    -- currently stopping - don't disturb that.
 
120
    if stopping then
 
121
        return false
 
122
    end
 
123
 
 
124
    -- abort stopping
 
125
    stop_from_pos = nil
 
126
    if timeline:is_playing() then
 
127
        return false
 
128
    end
 
129
 
 
130
    local fn = handler_press[sym]
 
131
    if fn then fn() end
 
132
end
 
133
 
 
134
-- release: may be followed immediately by press, which means that the
 
135
-- key is being held down.
 
136
function on_key_release(actor, event, self)
 
137
    local sym = event.key:symbol()
 
138
    if sym == clutter.Left or sym == clutter.Right then
 
139
        if not stopping then
 
140
            stop_from_pos = timeline:get_progress()
 
141
        end
 
142
    end
 
143
end
 
144
 
 
145
function on_scroll_event(actor, event)
 
146
    if not timeline:is_playing() then
 
147
        running = (event.scroll.direction == clutter.SCROLL_UP) and -1 or 1
 
148
        stop_from_pos = 0
 
149
        rotate_items()
 
150
    end
 
151
end
 
152
 
 
153
function movement_alpha(alpha)
 
154
    local tl = alpha:get_timeline()
 
155
    local p = tl:get_progress()
 
156
 
 
157
    -- continuous operation: linear
 
158
    if stop_from_pos == nil then
 
159
        return math.floor(p * 65535)
 
160
    end
 
161
 
 
162
    -- otherwise, gradual stop
 
163
    stopping = true
 
164
    local range = 1 - stop_from_pos
 
165
    local p2 = (p - stop_from_pos) / range
 
166
    p = stop_from_pos + range * (math.sin(p2 * math.pi / 2))
 
167
 
 
168
    return math.floor(p * 65535)
 
169
end
 
170
 
 
171
 
 
172
---
 
173
-- Change the label text at the middle of the animation, which is when
 
174
-- the text has been faded out.
 
175
--
 
176
function on_timeline_new_frame(timeline, frame_num, app)
 
177
    if frame_num == math.floor(timeline:get_n_frames() / 2) then
 
178
        label:set_text(items[selected_index].text)
 
179
    end
 
180
end
 
181
 
 
182
 
 
183
---
 
184
-- Rotating should be quick, regardless of the intro speed.
 
185
--
 
186
function on_timeline_completed(timeline, frame_num, app)
 
187
    timeline:set_duration(ms_per_step)
 
188
    stopping = false
 
189
    if not stop_from_pos then
 
190
        rotate_items()
 
191
    end
 
192
end
 
193
 
 
194
function init()
 
195
    local color, item, alpha_ramp, ac
 
196
 
 
197
    stage = clutter.stage_get_default()
 
198
    stage:set_size(800, 600)
 
199
    stage:set_title"Clutter Carousel Demo"
 
200
 
 
201
    color = clutter.new"Color"
 
202
    color:from_pixel(0x343939ff)
 
203
    stage:set_color(color)
 
204
 
 
205
    -- the into should be 1 second long.
 
206
    timeline = clutter.timeline_new(init_duration * fps / 1000, fps)
 
207
 
 
208
    cl = gnome.closure(movement_alpha)
 
209
    alpha_sine_inc = clutter.alpha_new_full(timeline, cl, nil, nil)
 
210
    alpha_ramp = clutter.alpha_new_full(timeline, clutter.sine_half_func,
 
211
        nil, nil)
 
212
    alpha_scale = clutter.alpha_new_full(timeline, clutter.sine_inc_func, nil,
 
213
        nil)
 
214
 
 
215
    csw = stage:get_width()
 
216
    csh = stage:get_height()
 
217
 
 
218
    for k, v in pairs(items_init) do
 
219
        ac = clutter.texture_new_from_file(mydir .. v[1], nil)
 
220
        assert(ac, "Couldn't load file " .. mydir .. tostring(v[1]))
 
221
 
 
222
        item = {
 
223
            actor = ac,
 
224
            move = clutter.behaviour_ellipse_new(alpha_sine_inc,
 
225
                csw/4, csh-(csh/2), csw/2, csh-(csh/4),
 
226
                clutter.ROTATE_CW, 0, 360),
 
227
            opacity = clutter.behaviour_opacity_new(alpha_sine_inc,
 
228
                alpha_low, alpha_low),
 
229
            scale = clutter.behaviour_scale_new(alpha_scale,
 
230
                scale_small, scale_small, scale_small, scale_small),
 
231
            text = v[2]
 
232
        }
 
233
        item.move:apply(ac)
 
234
        item.opacity:apply(ac)
 
235
        item.scale:apply(ac)
 
236
        stage:add_actor(ac)
 
237
        items[#items + 1] = item
 
238
    end
 
239
 
 
240
    color:from_pixel(0x729fcfff)
 
241
    label = clutter.label_new_with_text('Coolvetica 60px', '')
 
242
    label:set_color(color)
 
243
    label:set_size(300, 200)
 
244
    label:set_line_wrap(false)
 
245
    label:set_position(csw/2-40, 40)
 
246
    stage:add_actor(label)
 
247
 
 
248
    label_behave = clutter.behaviour_opacity_new(alpha_ramp, 0xff, 0)
 
249
    label_behave:apply(label)
 
250
 
 
251
    stage:connect('key-press-event', on_key_press)
 
252
    stage:connect('key-release-event', on_key_release)
 
253
    stage:connect('scroll-event', on_scroll_event)
 
254
    timeline:connect('new-frame', on_timeline_new_frame)
 
255
    timeline:connect('completed', on_timeline_completed)
 
256
    stage:connect('destroy', clutter.main_quit)
 
257
    stage:show_all()
 
258
 
 
259
    introduce_items()
 
260
end
 
261
 
 
262
-- MAIN --
 
263
clutter.init(0, nil)
 
264
init()
 
265
collectgarbage"collect"
 
266
collectgarbage"collect"
 
267
clutter.main()
 
268