aboutsummaryrefslogtreecommitdiff
path: root/lib/main.vala
diff options
context:
space:
mode:
authorWilliam Hua <william.hua@canonical.com>2013-05-08 16:10:34 -0400
committerWilliam Hua <william.hua@canonical.com>2013-05-08 16:10:34 -0400
commitcf460ebb707e5f1b984bd7639e46dfd061c5c375 (patch)
tree27e66b6f64740644fe954dbf3b7578fae62878ec /lib/main.vala
parentc121830a02e1367b54c8b71d1341e935e96d03fa (diff)
downloadayatana-indicator-keyboard-cf460ebb707e5f1b984bd7639e46dfd061c5c375.tar.gz
ayatana-indicator-keyboard-cf460ebb707e5f1b984bd7639e46dfd061c5c375.tar.bz2
ayatana-indicator-keyboard-cf460ebb707e5f1b984bd7639e46dfd061c5c375.zip
Fix icon rendering.
Diffstat (limited to 'lib/main.vala')
-rw-r--r--lib/main.vala184
1 files changed, 170 insertions, 14 deletions
diff --git a/lib/main.vala b/lib/main.vala
index 759b8cbb..f65eef48 100644
--- a/lib/main.vala
+++ b/lib/main.vala
@@ -13,6 +13,8 @@ public class Indicator.Keyboard.Service : Object {
private Menu sources_menu;
private Icon[] icons;
+ private string[] icon_strings;
+ private uint[] icon_string_subscripts;
[DBus (visible = false)]
public Service (bool force) {
@@ -50,10 +52,12 @@ public class Indicator.Keyboard.Service : Object {
}
[DBus (visible = false)]
- protected virtual Icon create_icon (string text) {
+ protected virtual Icon create_icon (string text, uint subscript) {
const int W = 20;
const int H = 20;
const double R = 2.0;
+ const double TEXT_SIZE = 12.0;
+ const double SUBSCRIPT_SIZE = 10.0;
Pango.FontDescription description;
var style = get_style_context ();
@@ -72,19 +76,44 @@ public class Indicator.Keyboard.Service : Object {
context.set_source_rgba (colour.red, colour.green, colour.blue, colour.alpha);
context.fill ();
-
context.set_operator (Cairo.Operator.CLEAR);
- var layout = Pango.cairo_create_layout (context);
- layout.set_alignment (Pango.Alignment.CENTER);
- layout.set_font_description (description);
- layout.set_text (text, -1);
- Pango.cairo_update_layout (context, layout);
- int width;
- int height;
- layout.get_pixel_size (out width, out height);
- context.translate ((W - width) / 2, (H - height) / 2);
- Pango.cairo_layout_path (context, layout);
- context.fill ();
+
+ var text_layout = Pango.cairo_create_layout (context);
+ text_layout.set_alignment (Pango.Alignment.CENTER);
+ description.set_absolute_size (Pango.units_from_double (TEXT_SIZE));
+ text_layout.set_font_description (description);
+ text_layout.set_text (text, -1);
+ Pango.cairo_update_layout (context, text_layout);
+ int text_width;
+ int text_height;
+ text_layout.get_pixel_size (out text_width, out text_height);
+
+ if (subscript > 1) {
+ var subscript_layout = Pango.cairo_create_layout (context);
+ subscript_layout.set_alignment (Pango.Alignment.CENTER);
+ description.set_absolute_size (Pango.units_from_double (SUBSCRIPT_SIZE));
+ subscript_layout.set_font_description (description);
+ subscript_layout.set_text (@"$subscript", -1);
+ Pango.cairo_update_layout (context, subscript_layout);
+ int subscript_width;
+ int subscript_height;
+ subscript_layout.get_pixel_size (out subscript_width, out subscript_height);
+
+ context.identity_matrix ();
+ context.translate ((W - (text_width + subscript_width)) / 2, (H - text_height) / 2);
+ Pango.cairo_layout_path (context, text_layout);
+ context.fill ();
+
+ context.identity_matrix ();
+ context.translate ((W + (text_width - subscript_width)) / 2, (H + text_height) / 2 - subscript_height);
+ Pango.cairo_layout_path (context, subscript_layout);
+ context.fill ();
+ } else {
+ context.identity_matrix ();
+ context.translate ((W - text_width) / 2, (H - text_height) / 2);
+ Pango.cairo_layout_path (context, text_layout);
+ context.fill ();
+ }
var buffer = new ByteArray ();
@@ -97,6 +126,130 @@ public class Indicator.Keyboard.Service : Object {
}
[DBus (visible = false)]
+ private string abbreviate_display_name (string display_name) {
+ string abbreviation = null;
+
+ if (display_name != null) {
+ char letters[2];
+ var index = 0;
+
+ for (var i = 0; i < display_name.length && index < 2; i++) {
+ if (display_name[i].isupper ()) {
+ letters[index++] = display_name[i];
+ }
+ }
+
+ if (index < 2) {
+ index = 0;
+
+ for (var i = 0; i < display_name.length && index < 2; i++) {
+ if (display_name[i].isalpha () && (i == 0 || !display_name[i - 1].isalpha ())) {
+ letters[index++] = display_name[i++].toupper ();
+ }
+ }
+
+ if (index < 2) {
+ index = 0;
+
+ for (var i = 0; i < display_name.length && index < 2; i++) {
+ if (display_name[i].isalpha ()) {
+ letters[index++] = display_name[i];
+ }
+ }
+ }
+ }
+
+ if (index == 1) {
+ abbreviation = @"$(letters[0])";
+ } else if (index == 2) {
+ abbreviation = @"$(letters[0])$(letters[1])";
+ }
+ }
+
+ return abbreviation;
+ }
+
+ [DBus (visible = false)]
+ private uint get_icon_string_subscript (uint index) {
+ uint icon_string_subscript = 0;
+ Variant array = null;
+
+ if (this.icon_string_subscripts == null) {
+ this.source_settings.get ("sources", "@a(ss)", out array);
+ this.icon_string_subscripts = new uint[array.n_children ()];
+ }
+
+ if (index < this.icon_string_subscripts.length) {
+ icon_string_subscript = this.icon_string_subscripts[index];
+
+ if (icon_string_subscript == 0) {
+ this.icon_string_subscripts[index] = 1;
+
+ for (var i = (int) index - 1; i >= 0 && this.icon_string_subscripts[index] == 1; i--) {
+ if (get_icon_string (i) == get_icon_string (index)) {
+ this.icon_string_subscripts[index] = get_icon_string_subscript (i) + 1;
+ }
+ }
+
+ icon_string_subscript = this.icon_string_subscripts[index];
+ }
+ }
+
+ return icon_string_subscript;
+ }
+
+ [DBus (visible = false)]
+ private string get_icon_string (uint index) {
+ string icon_string = null;
+ Variant array = null;
+
+ if (this.icon_strings == null) {
+ this.source_settings.get ("sources", "@a(ss)", out array);
+ this.icon_strings = new string[array.n_children ()];
+ }
+
+ if (index < this.icon_strings.length) {
+ icon_string = this.icon_strings[index];
+
+ if (icon_string == null) {
+ if (array == null) {
+ this.source_settings.get ("sources", "@a(ss)", out array);
+ }
+
+ string type;
+ string name;
+
+ array.get_child (index, "(ss)", out type, out name);
+
+ if (type == "xkb") {
+ string display_name;
+ string layout_name;
+
+ this.xkb_info.get_layout_info (name, out display_name, null, out layout_name, null);
+
+ if (display_name == null) {
+ var language = Xkl.get_language_name (layout_name);
+ var country = Xkl.get_country_name (layout_name);
+
+ if (language != null && country != null) {
+ display_name = @"$language ($country)";
+ } else if (language != null) {
+ display_name = language;
+ } else if (country != null) {
+ display_name = country;
+ }
+ }
+
+ this.icon_strings[index] = abbreviate_display_name (display_name);
+ icon_string = this.icon_strings[index];
+ }
+ }
+ }
+
+ return icon_string;
+ }
+
+ [DBus (visible = false)]
private Icon get_icon (uint index) {
Icon icon = null;
Variant array = null;
@@ -120,7 +273,7 @@ public class Indicator.Keyboard.Service : Object {
array.get_child (index, "(ss)", out type, out name);
if (type == "xkb") {
- this.icons[index] = create_icon (name);
+ this.icons[index] = create_icon (get_icon_string (index), get_icon_string_subscript (index));
} else if (type == "ibus") {
var ibus = get_ibus ();
string[] names = { name, null };
@@ -330,7 +483,10 @@ public class Indicator.Keyboard.Service : Object {
[DBus (visible = false)]
private void handle_changed_sources (string key) {
+ this.icon_string_subscripts = null;
+ this.icon_strings = null;
this.icons = null;
+
update_sources_menu ();
update_indicator_action ();
}