|
Packit |
3ff832 |
/* vim:set et sts=4 sw=4:
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* ibus - The Input Bus
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* Copyright(c) 2011-2015 Peng Huang <shawn.p.huang@gmail.com>
|
|
Packit |
3ff832 |
* Copyright(c) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
3ff832 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
3ff832 |
* License as published by the Free Software Foundation; either
|
|
Packit |
3ff832 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
3ff832 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
3ff832 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
3ff832 |
* Lesser General Public License for more details.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
3ff832 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
3ff832 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
Packit |
3ff832 |
* USA
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
class CandidateArea : Gtk.Box {
|
|
Packit |
3ff832 |
private bool m_vertical;
|
|
Packit |
3ff832 |
private Gtk.Label[] m_labels;
|
|
Packit |
3ff832 |
private Gtk.Label[] m_candidates;
|
|
Packit |
3ff832 |
private Gtk.Widget[] m_widgets;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
private IBus.Text[] m_ibus_candidates;
|
|
Packit |
3ff832 |
private uint m_focus_candidate;
|
|
Packit |
3ff832 |
private bool m_show_cursor;
|
|
Packit |
3ff832 |
private ThemedRGBA m_rgba;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
private const string LABELS[] = {
|
|
Packit |
3ff832 |
"1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
|
|
Packit |
3ff832 |
"9.", "0.", "a.", "b.", "c.", "d.", "e.", "f."
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
private const string PREV_PAGE_ICONS[] = {
|
|
Packit |
3ff832 |
"go-previous",
|
|
Packit |
3ff832 |
"go-up"
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
private const string NEXT_PAGE_ICONS[] = {
|
|
Packit |
3ff832 |
"go-next",
|
|
Packit |
3ff832 |
"go-down"
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
public signal void candidate_clicked(uint index, uint button, uint state);
|
|
Packit |
3ff832 |
public signal void page_up();
|
|
Packit |
3ff832 |
public signal void page_down();
|
|
Packit |
3ff832 |
public signal void cursor_up();
|
|
Packit |
3ff832 |
public signal void cursor_down();
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
public CandidateArea(bool vertical) {
|
|
Packit |
3ff832 |
GLib.Object();
|
|
Packit |
3ff832 |
set_vertical(vertical, true);
|
|
Packit |
3ff832 |
m_rgba = new ThemedRGBA(this);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
public bool candidate_scrolled(Gdk.EventScroll event) {
|
|
Packit |
3ff832 |
switch (event.direction) {
|
|
Packit |
3ff832 |
case Gdk.ScrollDirection.UP:
|
|
Packit |
3ff832 |
cursor_up();
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
case Gdk.ScrollDirection.DOWN:
|
|
Packit |
3ff832 |
cursor_down();
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
return true;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
public bool get_vertical() {
|
|
Packit |
3ff832 |
return m_vertical;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
public void set_vertical(bool vertical, bool force = false) {
|
|
Packit |
3ff832 |
if (!force && m_vertical == vertical)
|
|
Packit |
3ff832 |
return;
|
|
Packit |
3ff832 |
m_vertical = vertical;
|
|
Packit |
3ff832 |
orientation = vertical ?
|
|
Packit |
3ff832 |
Gtk.Orientation.VERTICAL :
|
|
Packit |
3ff832 |
Gtk.Orientation.HORIZONTAL;
|
|
Packit |
3ff832 |
recreate_ui();
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (m_ibus_candidates.length > 0) {
|
|
Packit |
3ff832 |
// Workaround a vala issue
|
|
Packit |
3ff832 |
// https://bugzilla.gnome.org/show_bug.cgi?id=661130
|
|
Packit |
3ff832 |
set_candidates((owned)m_ibus_candidates,
|
|
Packit |
3ff832 |
m_focus_candidate,
|
|
Packit |
3ff832 |
m_show_cursor);
|
|
Packit |
3ff832 |
show_all();
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
public void set_labels(IBus.Text[] labels) {
|
|
Packit |
3ff832 |
int i;
|
|
Packit |
3ff832 |
for (i = 0; i < int.min(16, labels.length); i++)
|
|
Packit |
3ff832 |
m_labels[i].set_text(labels[i].get_text());
|
|
Packit |
3ff832 |
for (; i < 16; i++)
|
|
Packit |
3ff832 |
m_labels[i].set_text(LABELS[i]);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
public void set_candidates(IBus.Text[] candidates,
|
|
Packit |
3ff832 |
uint focus_candidate = 0,
|
|
Packit |
3ff832 |
bool show_cursor = true) {
|
|
Packit |
3ff832 |
m_ibus_candidates = candidates;
|
|
Packit |
3ff832 |
m_focus_candidate = focus_candidate;
|
|
Packit |
3ff832 |
m_show_cursor = show_cursor;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
assert(candidates.length < 16);
|
|
Packit |
3ff832 |
for (int i = 0 ; i < 16 ; i++) {
|
|
Packit |
3ff832 |
Gtk.Label label = m_candidates[i];
|
|
Packit |
3ff832 |
bool visible = false;
|
|
Packit |
3ff832 |
if (i < candidates.length) {
|
|
Packit |
3ff832 |
Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(candidates[i]);
|
|
Packit |
3ff832 |
if (i == focus_candidate && show_cursor) {
|
|
Packit |
3ff832 |
Pango.Attribute pango_attr = Pango.attr_foreground_new(
|
|
Packit |
3ff832 |
(uint16)(m_rgba.selected_fg.red * uint16.MAX),
|
|
Packit |
3ff832 |
(uint16)(m_rgba.selected_fg.green * uint16.MAX),
|
|
Packit |
3ff832 |
(uint16)(m_rgba.selected_fg.blue * uint16.MAX));
|
|
Packit |
3ff832 |
pango_attr.start_index = 0;
|
|
Packit |
3ff832 |
pango_attr.end_index = candidates[i].get_text().length;
|
|
Packit |
3ff832 |
attrs.insert((owned)pango_attr);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
pango_attr = Pango.attr_background_new(
|
|
Packit |
3ff832 |
(uint16)(m_rgba.selected_bg.red * uint16.MAX),
|
|
Packit |
3ff832 |
(uint16)(m_rgba.selected_bg.green * uint16.MAX),
|
|
Packit |
3ff832 |
(uint16)(m_rgba.selected_bg.blue * uint16.MAX));
|
|
Packit |
3ff832 |
pango_attr.start_index = 0;
|
|
Packit |
3ff832 |
pango_attr.end_index = candidates[i].get_text().length;
|
|
Packit |
3ff832 |
attrs.insert((owned)pango_attr);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
label.set_text(candidates[i].get_text());
|
|
Packit |
3ff832 |
label.set_attributes(attrs);
|
|
Packit |
3ff832 |
visible = true;
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
label.set_text("");
|
|
Packit |
3ff832 |
label.set_attributes(new Pango.AttrList());
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
if (m_vertical) {
|
|
Packit |
3ff832 |
m_widgets[i * 2].set_visible(visible);
|
|
Packit |
3ff832 |
m_widgets[i * 2 +1].set_visible(visible);
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
m_widgets[i].set_visible(visible);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
private void recreate_ui() {
|
|
Packit |
3ff832 |
foreach (Gtk.Widget w in get_children()) {
|
|
Packit |
3ff832 |
w.destroy();
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
Gtk.Button prev_button = new Gtk.Button();
|
|
Packit |
3ff832 |
prev_button.clicked.connect((b) => page_up());
|
|
Packit |
3ff832 |
prev_button.set_image(new Gtk.Image.from_icon_name(
|
|
Packit |
3ff832 |
PREV_PAGE_ICONS[orientation],
|
|
Packit |
3ff832 |
Gtk.IconSize.MENU));
|
|
Packit |
3ff832 |
prev_button.set_relief(Gtk.ReliefStyle.NONE);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
Gtk.Button next_button = new Gtk.Button();
|
|
Packit |
3ff832 |
next_button.clicked.connect((b) => page_down());
|
|
Packit |
3ff832 |
next_button.set_image(new Gtk.Image.from_icon_name(
|
|
Packit |
3ff832 |
NEXT_PAGE_ICONS[orientation],
|
|
Packit |
3ff832 |
Gtk.IconSize.MENU));
|
|
Packit |
3ff832 |
next_button.set_relief(Gtk.ReliefStyle.NONE);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (m_vertical) {
|
|
Packit |
3ff832 |
Gtk.EventBox container_ebox = new Gtk.EventBox();
|
|
Packit |
3ff832 |
container_ebox.add_events(Gdk.EventMask.SCROLL_MASK);
|
|
Packit |
3ff832 |
container_ebox.scroll_event.connect(candidate_scrolled);
|
|
Packit |
3ff832 |
add(container_ebox);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
Gtk.Box vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
|
|
Packit |
3ff832 |
container_ebox.add(vbox);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Add Candidates
|
|
Packit |
3ff832 |
Gtk.Box candidates_hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
|
|
Packit |
3ff832 |
vbox.pack_start(candidates_hbox, false, false, 0);
|
|
Packit |
3ff832 |
Gtk.Box labels_vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
|
|
Packit |
3ff832 |
labels_vbox.set_homogeneous(true);
|
|
Packit |
3ff832 |
Gtk.Box candidates_vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
|
|
Packit |
3ff832 |
candidates_vbox.set_homogeneous(true);
|
|
Packit |
3ff832 |
candidates_hbox.pack_start(labels_vbox, false, false, 4);
|
|
Packit |
3ff832 |
candidates_hbox.pack_start(new VSeparator(), false, false, 0);
|
|
Packit |
3ff832 |
candidates_hbox.pack_start(candidates_vbox, true, true, 4);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Add HSeparator
|
|
Packit |
3ff832 |
vbox.pack_start(new HSeparator(), false, false, 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Add buttons
|
|
Packit |
3ff832 |
Gtk.Box buttons_hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
|
|
Packit |
3ff832 |
Gtk.Label state_label = new Gtk.Label(null);
|
|
Packit |
3ff832 |
state_label.set_size_request(20, -1);
|
|
Packit |
3ff832 |
buttons_hbox.pack_start(state_label, true, true, 0);
|
|
Packit |
3ff832 |
buttons_hbox.pack_start(prev_button, false, false, 0);
|
|
Packit |
3ff832 |
buttons_hbox.pack_start(next_button, false, false, 0);
|
|
Packit |
3ff832 |
vbox.pack_start(buttons_hbox, false, false, 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
m_labels = {};
|
|
Packit |
3ff832 |
m_candidates = {};
|
|
Packit |
3ff832 |
m_widgets = {};
|
|
Packit |
3ff832 |
for (int i = 0; i < 16; i++) {
|
|
Packit |
3ff832 |
Gtk.Label label = new Gtk.Label(LABELS[i]);
|
|
Packit |
3ff832 |
label.set_halign(Gtk.Align.START);
|
|
Packit |
3ff832 |
label.set_valign(Gtk.Align.CENTER);
|
|
Packit |
3ff832 |
label.show();
|
|
Packit |
3ff832 |
m_labels += label;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
Gtk.Label candidate = new Gtk.Label("test");
|
|
Packit |
3ff832 |
candidate.set_halign(Gtk.Align.START);
|
|
Packit |
3ff832 |
candidate.set_valign(Gtk.Align.CENTER);
|
|
Packit |
3ff832 |
candidate.show();
|
|
Packit |
3ff832 |
m_candidates += candidate;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* Use Gtk.Widget.set_margin_start() since gtk 3.12 */
|
|
Packit |
3ff832 |
label.set_padding(8, 0);
|
|
Packit |
3ff832 |
candidate.set_padding(8, 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Make a copy of i to workaround a bug in vala.
|
|
Packit |
3ff832 |
// https://bugzilla.gnome.org/show_bug.cgi?id=628336
|
|
Packit |
3ff832 |
int index = i;
|
|
Packit |
3ff832 |
Gtk.EventBox label_ebox = new Gtk.EventBox();
|
|
Packit |
3ff832 |
label_ebox.set_no_show_all(true);
|
|
Packit |
3ff832 |
label_ebox.button_press_event.connect((w, e) => {
|
|
Packit |
3ff832 |
candidate_clicked(i, e.button, e.state);
|
|
Packit |
3ff832 |
return true;
|
|
Packit |
3ff832 |
});
|
|
Packit |
3ff832 |
label_ebox.add(label);
|
|
Packit |
3ff832 |
labels_vbox.pack_start(label_ebox, false, false, 2);
|
|
Packit |
3ff832 |
m_widgets += label_ebox;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
Gtk.EventBox candidate_ebox = new Gtk.EventBox();
|
|
Packit |
3ff832 |
candidate_ebox.set_no_show_all(true);
|
|
Packit |
3ff832 |
candidate_ebox.button_press_event.connect((w, e) => {
|
|
Packit |
3ff832 |
candidate_clicked(index, e.button, e.state);
|
|
Packit |
3ff832 |
return true;
|
|
Packit |
3ff832 |
});
|
|
Packit |
3ff832 |
candidate_ebox.add(candidate);
|
|
Packit |
3ff832 |
candidates_vbox.pack_start(candidate_ebox, false, false, 2);
|
|
Packit |
3ff832 |
m_widgets += candidate_ebox;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
} else {
|
|
Packit |
3ff832 |
Gtk.EventBox container_ebox = new Gtk.EventBox();
|
|
Packit |
3ff832 |
container_ebox.add_events(Gdk.EventMask.SCROLL_MASK);
|
|
Packit |
3ff832 |
container_ebox.scroll_event.connect(candidate_scrolled);
|
|
Packit |
3ff832 |
add(container_ebox);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
Gtk.Box hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
|
|
Packit |
3ff832 |
container_ebox.add(hbox);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
m_labels = {};
|
|
Packit |
3ff832 |
m_candidates = {};
|
|
Packit |
3ff832 |
m_widgets = {};
|
|
Packit |
3ff832 |
for (int i = 0; i < 16; i++) {
|
|
Packit |
3ff832 |
Gtk.Label label = new Gtk.Label(LABELS[i]);
|
|
Packit |
3ff832 |
label.set_halign(Gtk.Align.START);
|
|
Packit |
3ff832 |
label.set_valign(Gtk.Align.CENTER);
|
|
Packit |
3ff832 |
label.show();
|
|
Packit |
3ff832 |
m_labels += label;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
Gtk.Label candidate = new Gtk.Label("test");
|
|
Packit |
3ff832 |
candidate.set_halign(Gtk.Align.START);
|
|
Packit |
3ff832 |
candidate.set_valign(Gtk.Align.CENTER);
|
|
Packit |
3ff832 |
candidate.show();
|
|
Packit |
3ff832 |
m_candidates += candidate;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
Gtk.Box candidate_hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
|
|
Packit |
3ff832 |
candidate_hbox.show();
|
|
Packit |
3ff832 |
candidate_hbox.pack_start(label, false, false, 2);
|
|
Packit |
3ff832 |
candidate_hbox.pack_start(candidate, false, false, 2);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// Make a copy of i to workaround a bug in vala.
|
|
Packit |
3ff832 |
// https://bugzilla.gnome.org/show_bug.cgi?id=628336
|
|
Packit |
3ff832 |
int index = i;
|
|
Packit |
3ff832 |
Gtk.EventBox ebox = new Gtk.EventBox();
|
|
Packit |
3ff832 |
ebox.set_no_show_all(true);
|
|
Packit |
3ff832 |
ebox.button_press_event.connect((w, e) => {
|
|
Packit |
3ff832 |
candidate_clicked(index, e.button, e.state);
|
|
Packit |
3ff832 |
return true;
|
|
Packit |
3ff832 |
});
|
|
Packit |
3ff832 |
ebox.add(candidate_hbox);
|
|
Packit |
3ff832 |
hbox.pack_start(ebox, false, false, 4);
|
|
Packit |
3ff832 |
m_widgets += ebox;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
hbox.pack_start(new VSeparator(), false, false, 0);
|
|
Packit |
3ff832 |
hbox.pack_start(prev_button, false, false, 0);
|
|
Packit |
3ff832 |
hbox.pack_start(next_button, false, false, 0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|