summaryrefslogtreecommitdiff
path: root/src/notificationbar.vala
blob: d9d8e5d7dc4ad926190233a654100eb6fc5d977e (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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// This file is part of GNOME Boxes. License: LGPLv2+
using Gtk;

private class Boxes.Notificationbar: GLib.Object {
    public const int DEFAULT_TIMEOUT = 6;

    public Clutter.Actor actor { get { return gtk_actor; } }

    public delegate void OKFunc ();
    public delegate void CancelFunc ();
    public delegate void AuthenticateFunc (string username, string password);

    private GtkClutter.Actor gtk_actor;
    private Gtk.Grid top_grid;

    GLib.List<Widget> active_notifications;

    public Notificationbar () {
        active_notifications = new GLib.List<Widget> ();

        top_grid = new Gtk.Grid ();
        top_grid.show ();

        gtk_actor = new GtkClutter.Actor.with_contents (top_grid);
        gtk_actor.name = "notificationbar";
        gtk_actor.x_align = Clutter.ActorAlign.CENTER;
        gtk_actor.y_align = Clutter.ActorAlign.START;
        gtk_actor.x_expand = true;
        gtk_actor.y_expand = true;
        Gdk.RGBA transparent = { 0, 0, 0, 0};
        gtk_actor.get_widget ().override_background_color (0, transparent);

        App.app.notebook.notify["page"].connect ( () => {
            foreach (var w in active_notifications) {
                var parent = w.get_parent () as Container;
                if (parent != null)
                    parent.remove (w);
                add_notification (w);
            }
        });
    }

    public Gd.Notification display_for_action (string            message,
                                               string            action_label,
                                               owned OKFunc      action_func,
                                               owned CancelFunc? ignore_func = null,
                                               int               timeout = DEFAULT_TIMEOUT) {
        return display (message, MessageType.INFO, action_label, (owned) action_func, (owned) ignore_func, timeout);
    }

    public Gd.Notification display_for_authentication (string broker_name,
                                                       owned AuthenticateFunc? auth_func,
                                                       owned CancelFunc? cancel_func) {
        Notificationbar.OKFunc next_auth_step = () => {
            display_for_auth_next (broker_name, (owned) auth_func, (owned) cancel_func);
        };
        return display_for_action (_("Not connected to %s").printf (broker_name), _("Sign In"), (owned) next_auth_step, (owned) cancel_func, -1);
    }

    private Gd.Notification display_for_auth_next (string auth_string,
                                                   owned AuthenticateFunc? auth_func,
                                                   owned CancelFunc? cancel_func) {
        var notification = new Gd.Notification ();
        notification.valign = Gtk.Align.START;
        notification.timeout = -1;
        notification.show_close_button = false;

        active_notifications.prepend (notification);

        notification.dismissed.connect ( () => {
            active_notifications.remove (notification);
        });

        var title_label = new Gtk.Label (null);
        string title_str = "<span font-weight=\"bold\">" + _("Sign In to %s").printf(auth_string) + "</span>";

        title_label.set_markup (title_str);
        title_label.halign = Gtk.Align.START;
        title_label.margin_bottom = 18;

        var username_label = new Gtk.Label.with_mnemonic (_("_Username"));
        var username_entry = new Gtk.Entry ();
        username_entry.focus_in_event.connect ( () => {
            App.app.searchbar.disable_key_handler ();
            return false;
        });
        username_entry.focus_out_event.connect ( () => {
            App.app.searchbar.enable_key_handler ();
            return false;
        });
        username_entry.map.connect ( () => {
            username_entry.grab_focus ();
        });
        username_label.mnemonic_widget = username_entry;
        username_label.margin_left = 12;
        var password_label = new Gtk.Label.with_mnemonic (_("_Password"));
        var password_entry = new Gtk.Entry ();
        password_entry.visibility = false;
        password_entry.focus_in_event.connect ( () => {
            App.app.searchbar.disable_key_handler ();
            return false;
        });
        password_entry.focus_out_event.connect ( () => {
            App.app.searchbar.enable_key_handler ();
            return false;
        });
        password_label.mnemonic_widget = password_entry;
        password_label.margin_left = 12;

        var auth_button = new Button.from_stock (_("Sign In"));
        auth_button.halign = Gtk.Align.END;

        auth_button.clicked.connect ( () => {
            if (auth_func != null) auth_func (username_entry.get_text (), password_entry.get_text ());
            notification.dismiss ();
        });

        username_entry.activate.connect (() => {
            password_entry.grab_focus ();
        });
        password_entry.activate.connect (() => {
            auth_button.activate ();
        });

        var grid = new Gtk.Grid ();
        grid.column_spacing = 12;
        grid.row_spacing = 6;
        grid.border_width = 6;
        grid.attach (title_label, 0, 0, 2, 1);
        grid.attach (username_label, 0, 1, 1, 1);
        grid.attach (username_entry, 1, 1, 1, 1);
        grid.attach (password_label, 0, 2, 1, 1);
        grid.attach (password_entry, 1, 2, 1, 1);
        grid.attach (auth_button, 1, 3, 1, 1);
        notification.add (grid);

        add_notification (notification);
        notification.show_all ();

        return notification;
    }

    public Gd.Notification display_error (string message, int timeout = DEFAULT_TIMEOUT) {
        return display (message, MessageType.ERROR, null, null, null, timeout);
    }

    public void cancel () {
        // We destroy all active notifications, which will cause them to be dismissed
        while (active_notifications != null) {
            active_notifications.data.destroy ();
            active_notifications.remove (active_notifications.data);
        }
    }

    private void add_notification (Widget w) {
        if (App.app.notebook.page == AppPage.MAIN)
            top_grid.attach (w, 0, 0, 1, 1);
        else
            App.app.display_page.add_notification (w);
    }

    private Gd.Notification display (string            message,
                                     MessageType       message_type,
                                     string?           ok_label,
                                     owned OKFunc?     ok_func,
                                     owned CancelFunc? cancel_func,
                                     int               timeout) {
        var notification = new Gd.Notification ();
        notification.valign = Gtk.Align.START;
        notification.timeout = timeout;

        active_notifications.prepend (notification);

        bool ok_pressed = false;
        notification.dismissed.connect ( () => {
            if (!ok_pressed && cancel_func != null)
                cancel_func ();
            active_notifications.remove (notification);
        });

        var grid = new Gtk.Grid ();
        grid.set_orientation (Gtk.Orientation.HORIZONTAL);
        grid.margin_left = 12;
        grid.margin_right = 12;
        grid.column_spacing = 12;
        grid.valign = Gtk.Align.CENTER;
        notification.add (grid);

        var message_label = new Label (message);
        grid.add (message_label);

        if (ok_label != null) {
            var ok_button = new Button.from_stock (ok_label);
            ok_button.halign = Gtk.Align.END;
            grid.add (ok_button);

            ok_button.clicked.connect ( () => {
                ok_pressed = true;
                if (ok_func != null)
                    ok_func ();
                notification.dismiss ();
            });
        }

        add_notification (notification);
        notification.show_all ();

        return notification;
    }
}