summaryrefslogtreecommitdiff
path: root/lib/astal/io/time.vala
blob: a799f2b07a198cb77af62bbc125364dcfe976307 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
 * `Time` provides shortcuts for GLib timeout functions.
 */
public class AstalIO.Time : Object {
    private Cancellable cancellable;
    private uint timeout_id;
    private bool fulfilled = false;

    /**
     * Emitted when the timer ticks.
     */
    public signal void now ();

    /**
     * Emitted when the timere is cancelled.
     */
    public signal void cancelled ();

    construct {
        cancellable = new Cancellable();
        cancellable.cancelled.connect(() => {
            if (!fulfilled) {
                Source.remove(timeout_id);
                cancelled();
                dispose();
            }
        });
    }

    private void connect_closure(Closure? closure) {
        if (closure == null)
            return;

        now.connect(() => {
            Value ret = Value(Type.POINTER); // void
            closure.invoke(ref ret, {});
        });
    }

    /**
     * Start an interval timer with default Priority.
     */
    public Time.interval_prio(uint interval, int prio = Priority.DEFAULT, Closure? fn) {
        connect_closure(fn);
        Idle.add_once(() => now());
        timeout_id = Timeout.add(interval, () => {
            now();
            return Source.CONTINUE;
        }, prio);
    }

    /**
     * Start a timeout timer with default Priority.
     */
    public Time.timeout_prio(uint timeout, int prio = Priority.DEFAULT, Closure? fn) {
        connect_closure(fn);
        timeout_id = Timeout.add(timeout, () => {
            now();
            fulfilled = true;
            return Source.REMOVE;
        }, prio);
    }

    /**
     * Start an idle timer with default priority.
     */
    public Time.idle_prio(int prio = Priority.DEFAULT_IDLE, Closure? fn) {
        connect_closure(fn);
        timeout_id = Idle.add(() => {
            now();
            fulfilled = true;
            return Source.REMOVE;
        }, prio);
    }

    /**
     * Start an interval timer. Ticks immediately then every `interval` milliseconds.
     *
     * @param interval Tick every milliseconds.
     * @param fn Optional callback.
     */
    public static Time interval(uint interval, Closure? fn) {
        return new Time.interval_prio(interval, Priority.DEFAULT, fn);
    }

    /**
     * Start a timeout timer which ticks after `timeout` milliseconds.
     *
     * @param timeout Tick after milliseconds.
     * @param fn Optional callback.
     */
    public static Time timeout(uint timeout, Closure? fn) {
        return new Time.timeout_prio(timeout, Priority.DEFAULT, fn);
    }

    /**
     * Start a timer which will tick when there are no higher priority tasks pending.
     *
     * @param fn Optional callback.
     */
    public static Time idle(Closure? fn) {
        return new Time.idle_prio(Priority.DEFAULT_IDLE, fn);
    }

    /**
     * Cancel timer and emit [[email protected]::cancelled]
     */
    public void cancel() {
        cancellable.cancel();
    }
}