Cleanup the vala code of gtk3 panel and tool by:
[platform/upstream/ibus.git] / ui / gtk3 / candidatearea.vala
1 /* vim:set et sts=4 sw=4:
2  *
3  * ibus - The Input Bus
4  *
5  * Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or(at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA  02111-1307  USA
21  */
22
23 class CandidateArea : Gtk.Box {
24     private bool m_vertical;
25     private Gtk.Label[] m_labels;
26     private Gtk.Label[] m_candidates;
27     private Gtk.Widget[] m_widgets;
28
29     private IBus.Text[] m_ibus_candidates;
30     private uint m_focus_candidate;
31     private bool m_show_cursor;
32
33     private const string LABELS[] = {
34         "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
35         "9.", "0.", "a.", "b.", "c.", "d.", "e.", "f."
36     };
37
38     public signal void candidate_clicked(uint index, uint button, uint state);
39     public signal void page_up();
40     public signal void page_down();
41     public signal void cursor_up();
42     public signal void cursor_down();
43
44     public CandidateArea(bool vertical) {
45         GLib.Object(
46             orientation: vertical ? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL
47         );
48         m_vertical = vertical;
49         recreate_ui();
50         show_all();
51     }
52
53     public void set_vertical(bool vertical) {
54         if (m_vertical == vertical)
55             return;
56         m_vertical = vertical;
57         recreate_ui();
58
59         // Workaround a vala issue https://bugzilla.gnome.org/show_bug.cgi?id=661130
60         set_candidates((owned)m_ibus_candidates, m_focus_candidate, m_show_cursor);
61         if (m_candidates.length > 0)
62             show_all();
63     }
64
65     public void set_labels(IBus.Text[] labels) {
66         int i;
67         for (i = 0; i < int.min(16, labels.length); i++)
68             m_labels[i].set_text(labels[i].get_text());
69         for (; i < 16; i++)
70             m_labels[i].set_text(LABELS[i]);
71     }
72
73     public void set_candidates(IBus.Text[] candidates,
74                                uint focus_candidate = 0,
75                                bool show_cursor = true) {
76         m_ibus_candidates = candidates;
77         m_focus_candidate = focus_candidate;
78         m_show_cursor = show_cursor;
79
80         assert(candidates.length < 16);
81         for (int i = 0 ; i < 16 ; i++) {
82             Gtk.Label label = m_candidates[i];
83             bool visible = false;
84             if (i < candidates.length) {
85                 Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(candidates[i]);
86                 if (i == focus_candidate && show_cursor) {
87                     Gtk.StyleContext context = m_candidates[i].get_style_context();
88                     Gdk.RGBA color = context.get_color(Gtk.StateFlags.SELECTED);
89                     Pango.Attribute pango_attr = Pango.attr_foreground_new(
90                             (uint16)(color.red * uint16.MAX),
91                             (uint16)(color.green * uint16.MAX),
92                             (uint16)(color.blue * uint16.MAX));
93                     pango_attr.start_index = 0;
94                     pango_attr.end_index = candidates[i].get_text().length;
95                     attrs.insert((owned)pango_attr);
96
97                     color = context.get_background_color(Gtk.StateFlags.SELECTED);
98                     pango_attr = Pango.attr_background_new(
99                             (uint16)(color.red * uint16.MAX),
100                             (uint16)(color.green * uint16.MAX),
101                             (uint16)(color.blue * uint16.MAX));
102                     pango_attr.start_index = 0;
103                     pango_attr.end_index = candidates[i].get_text().length;
104                     attrs.insert((owned)pango_attr);
105                 }
106                 label.set_text(candidates[i].get_text());
107                 label.set_attributes(attrs);
108                 visible = true;
109             } else {
110                 label.set_text("");
111                 label.set_attributes(new Pango.AttrList());
112             }
113             if (m_vertical) {
114                 m_widgets[i * 2].set_visible(visible);
115                 m_widgets[i * 2 +1].set_visible(visible);
116             } else {
117                 m_widgets[i].set_visible(visible);
118             }
119         }
120     }
121
122     private void recreate_ui() {
123         foreach (Gtk.Widget w in get_children()) {
124             w.destroy();
125         }
126
127         Gtk.Button prev_button = new Gtk.Button();
128         prev_button.clicked.connect((b) => page_up());
129         prev_button.set_image(new Gtk.Image.from_icon_name(Gtk.Stock.GO_UP, Gtk.IconSize.MENU));
130         prev_button.set_relief(Gtk.ReliefStyle.NONE);
131
132         Gtk.Button next_button = new Gtk.Button();
133         next_button.clicked.connect((b) => page_down());
134         next_button.set_image(new Gtk.Image.from_icon_name(Gtk.Stock.GO_DOWN, Gtk.IconSize.MENU));
135         next_button.set_relief(Gtk.ReliefStyle.NONE);
136
137         if (m_vertical) {
138             // Add Candidates
139             Gtk.HBox candidates_hbox = new Gtk.HBox(false, 0);
140             pack_start(candidates_hbox, false, false, 0);
141             Gtk.VBox labels_vbox = new Gtk.VBox(true, 0);
142             Gtk.VBox candidates_vbox = new Gtk.VBox(true, 0);
143             candidates_hbox.pack_start(labels_vbox, false, false, 4);
144             candidates_hbox.pack_start(new VSeparator(), false, false, 0);
145             candidates_hbox.pack_start(candidates_vbox, true, true, 4);
146
147             // Add HSeparator
148             pack_start(new HSeparator(), false, false, 0);
149
150             // Add buttons
151             Gtk.HBox buttons_hbox = new Gtk.HBox(false, 0);
152             Gtk.Label state_label = new Gtk.Label(null);
153             state_label.set_size_request(20, -1);
154             buttons_hbox.pack_start(state_label, true, true, 0);
155             buttons_hbox.pack_start(prev_button, false, false, 0);
156             buttons_hbox.pack_start(next_button, false, false, 0);
157             pack_start(buttons_hbox, false, false, 0);
158
159             m_labels = {};
160             m_candidates = {};
161             m_widgets = {};
162             for (int i = 0; i < 16; i++) {
163                 Gtk.Label label = new Gtk.Label(LABELS[i]);
164                 label.set_alignment(0.0f, 0.5f);
165                 label.show();
166                 m_labels += label;
167
168                 Gtk.Label candidate = new Gtk.Label("test");
169                 candidate.set_alignment(0.0f, 0.5f);
170                 candidate.show();
171                 m_candidates += candidate;
172
173                 label.set_property("xpad", 8);
174                 candidate.set_property("xpad", 8);
175
176                 // Make a copy of i to workaround a bug in vala.
177                 // https://bugzilla.gnome.org/show_bug.cgi?id=628336
178                 int index = i;
179                 Gtk.EventBox label_ebox = new Gtk.EventBox();
180                 label_ebox.set_no_show_all(true);
181                 label_ebox.button_press_event.connect((w, e) => {
182                     candidate_clicked(i, e.button, e.state);
183                     return true;
184                 });
185                 label_ebox.add(label);
186                 labels_vbox.pack_start(label_ebox, false, false, 2);
187                 m_widgets += label_ebox;
188
189                 Gtk.EventBox candidate_ebox = new Gtk.EventBox();
190                 candidate_ebox.set_no_show_all(true);
191                 candidate_ebox.button_press_event.connect((w, e) => {
192                     candidate_clicked(index, e.button, e.state);
193                     return true;
194                 });
195                 candidate_ebox.add(candidate);
196                 candidates_vbox.pack_start(candidate_ebox, false, false, 2);
197                 m_widgets += candidate_ebox;
198             }
199         } else {
200             Gtk.HBox hbox = new Gtk.HBox(false, 0);
201             add(hbox);
202
203             m_labels = {};
204             m_candidates = {};
205             m_widgets = {};
206             for (int i = 0; i < 16; i++) {
207                 Gtk.Label label = new Gtk.Label(LABELS[i]);
208                 label.set_alignment(0.0f, 0.5f);
209                 label.show();
210                 m_labels += label;
211
212                 Gtk.Label candidate = new Gtk.Label("test");
213                 candidate.set_alignment(0.0f, 0.5f);
214                 candidate.show();
215                 m_candidates += candidate;
216
217                 Gtk.HBox candidate_hbox = new Gtk.HBox(false, 0);
218                 candidate_hbox.show();
219                 candidate_hbox.pack_start(label, false, false, 2);
220                 candidate_hbox.pack_start(candidate, false, false, 2);
221
222                 // Make a copy of i to workaround a bug in vala.
223                 // https://bugzilla.gnome.org/show_bug.cgi?id=628336
224                 int index = i;
225                 Gtk.EventBox ebox = new Gtk.EventBox();
226                 ebox.set_no_show_all(true);
227                 ebox.button_press_event.connect((w, e) => {
228                     candidate_clicked(index, e.button, e.state);
229                     return true;
230                 });
231                 ebox.add(candidate_hbox);
232                 hbox.pack_start(ebox, false, false, 4);
233                 m_widgets += ebox;
234             }
235             hbox.pack_start(new VSeparator(), false, false, 0);
236             hbox.pack_start(prev_button, false, false, 0);
237             hbox.pack_start(next_button, false, false, 0);
238         }
239     }
240 }
241