%PDF- %PDF-
| Direktori : /usr/share/org.gnome.Characters/ |
| Current File : //usr/share/org.gnome.Characters/org.gnome.Characters.src.gresource |
GVariant � (
Ե ����� L � � �Xp� � v � � KFv� � L � � {W�y � v � 8( KP� 8( L <( @( ��$0 @( L H( L( Q�8\ L( v `( )y ���� )y L 4y 8y �l~ 8y v Py 0� �(�
0� v 8� V� H9 V�
v h� J� ж�U J�
v X� � �� � v � �� / characterDialog.js � /* exported CharacterDialog */
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
// Copyright (C) 2014-2015 Daiki Ueno <dueno@src.gnome.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
const { Adw, Gc, Gdk, Gio, GObject, Gtk, Pango } = imports.gi;
const Util = imports.util;
var CharacterDialog = GObject.registerClass({
Signals: {
'character-copied': { param_types: [GObject.TYPE_STRING] },
},
Template: 'resource:///org/gnome/Characters/character_dialog.ui',
InternalChildren: [
'characterStack', 'navigationView',
'characterLabel', 'missingLabel',
'detailRow', 'detailLabel',
'seeAlsoRow', 'relatedPage', 'relatedListbox',
'toastOverlay',
],
}, class CharacterDialog extends Adw.Window {
_init(character, fontDescription) {
super._init();
this._cancellable = new Gio.Cancellable();
this._fontDescription = fontDescription;
const actions = new Gio.SimpleActionGroup();
Util.initActions(actions, [
{ name: 'copy', activate: this._copyCharacter.bind(this) },
]);
this.insert_action_group('character', actions);
this._relatedPage.connect('hidden', () => {
this._populateRelatedPage();
});
this._setCharacter(character);
}
_finishSearch(result) {
this._related = result;
this._seeAlsoRow.visible = result.len > 0;
if (!this._relatedPage.get_mapped())
this._populateRelatedPage();
}
_populateRelatedPage() {
this._relatedListbox.remove_all();
for (let index = 0; index < this._related.len; index++) {
let uc = Gc.search_result_get(this._related, index);
let name = Gc.character_name(uc);
if (name === null)
continue;
let row = new Adw.ActionRow();
row.set_title(Util.capitalize(name));
row.add_prefix(new Gtk.Label({
label: uc,
valign: Gtk.Align.CENTER,
halign: Gtk.Align.CENTER,
width_request: 45,
}));
row.connect('activated', () => {
this._setCharacter(uc);
this._navigationView.pop();
});
row.set_activatable(true);
this._relatedListbox.append(row);
}
}
_setCharacter(uc) {
this._character = uc;
let name = Gc.character_name(this._character);
if (name !== null)
name = Util.capitalize(name);
if (Gc.character_is_composite(uc)) {
this._detailRow.hide();
if (name === null)
name = _('Unknown character name');
} else {
let codePoint = Util.toCodePoint(this._character);
let codePointHex = codePoint.toString(16).toUpperCase();
this._detailLabel.label = 'U+%04s'.format(codePointHex);
this._detailRow.show();
if (name === null)
name = 'U+%04s'.format(codePointHex);
}
this.title = name ? name : '';
this._characterLabel.label = this._character;
let pangoContext = this._characterLabel.get_pango_context();
pangoContext.set_font_description(this._fontDescription);
var pangoLayout = Pango.Layout.new(pangoContext);
pangoLayout.set_text(this._character, -1);
if (pangoLayout.get_unknown_glyphs_count() === 0) {
this._characterStack.visible_child_name = 'character';
} else {
var fontFamily = this._fontDescription.get_family();
// TRANSLATORS: the first variable is a character, the second is a font
this._missingLabel.label = _('%s is not included in %s').format(name, fontFamily);
this._characterStack.visible_child_name = 'missing';
}
this._cancellable.cancel();
this._cancellable.reset();
let criteria = Gc.SearchCriteria.new_related(this._character);
let context = new Gc.SearchContext({ criteria });
context.search(
-1,
this._cancellable,
(ctx, res) => {
try {
let result = ctx.search_finish(res);
this._finishSearch(result);
} catch (e) {
log(`Failed to search related: ${e.message}`);
}
});
this._seeAlsoRow.visible = false;
}
_copyCharacter() {
let display = Gdk.Display.get_default();
let clipboard = display.get_clipboard();
clipboard.set(this._character);
this.emit('character-copied', this._character);
const toast = new Adw.Toast({
title: _('Character copied to clipboard'),
timeout: 2,
});
this._toastOverlay.add_toast(toast);
}
});
(uuay)js/
main.js p /* exported main settings */
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
// Copyright (c) 2013 Giovanni Campagna <scampa.giovanni@gmail.com>
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the GNOME Foundation nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
pkg.initGettext();
pkg.initFormat();
pkg.require({
'Gdk': '4.0',
'Gio': '2.0',
'GLib': '2.0',
'GObject': '2.0',
'Gtk': '4.0',
'Adw': '1',
'GnomeDesktop': '4.0',
});
const { GLib, Gio, GObject, Adw } = imports.gi;
const { CharactersView } = imports.charactersView;
const { Sidebar } = imports.sidebar;
const { MainWindow } = imports.window;
const Util = imports.util;
const SearchProvider = imports.searchProvider;
var settings = null;
var MyApplication = GObject.registerClass({
}, class MyApplication extends Adw.Application {
_init() {
super._init({
application_id: pkg.name,
flags: Gio.ApplicationFlags.FLAGS_NONE,
resource_base_path: '/org/gnome/Characters',
});
GLib.set_application_name(_('Characters'));
this._searchProvider = new SearchProvider.SearchProvider(this);
}
get window() {
return this._appwindow;
}
_onQuit() {
this.quit();
}
vfunc_startup() {
super.vfunc_startup();
this.get_style_manager().set_color_scheme(Adw.ColorScheme.PREFER_LIGHT);
Util.initActions(this, [
{ name: 'quit', activate: this._onQuit },
]);
this.set_accels_for_action('app.quit', ['<Primary>q']);
this.set_accels_for_action('win.find', ['<Primary>f']);
this.set_accels_for_action('win.show-help-overlay', ['<Primary>question']);
settings = Util.getSettings('org.gnome.Characters',
'/org/gnome/Characters/');
if (this.get_flags() & Gio.ApplicationFlags.IS_SERVICE)
this.set_inactivity_timeout(10000);
log('Characters Application started');
}
vfunc_dbus_register(connection, path) {
const searchProviderPath = `${path}/SearchProvider`;
super.vfunc_dbus_register(connection, searchProviderPath);
this._searchProvider.export(connection, searchProviderPath);
return true;
}
vfunc_activate() {
if (!this._appwindow)
this._appwindow = new MainWindow(this);
if (pkg.name.endsWith('Devel'))
this._appwindow.add_css_class('devel');
this._appwindow.present();
log('Characters Application activated');
}
vfunc_shutdown() {
log('Characters Application exiting');
super.vfunc_shutdown();
}
});
function main(argv) {
GObject.type_ensure(CharactersView.$gtype);
GObject.type_ensure(Sidebar.$gtype);
return new MyApplication().run(argv);
}
(uuay)org/ gnome/ charactersView.js �P /* exported CharactersView */
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
// Copyright (C) 2014-2015 Daiki Ueno <dueno@src.gnome.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
const { Gc, Gdk, Gio, GLib, GnomeDesktop, GObject, Gtk, Pango, Graphene } = imports.gi;
Gio._promisify(Gc.SearchContext.prototype, 'search', 'search_finish');
const Util = imports.util;
const BASELINE_OFFSET = 0.85;
const CELLS_PER_ROW = 5;
const NUM_ROWS = 5;
const NUM_COLUMNS = 3;
const CELL_SIZE = 50;
function getCellSize(fontDescription) {
if (fontDescription === null || fontDescription.get_size() === 0)
return CELL_SIZE;
return fontDescription.get_size() * 2 / Pango.SCALE;
}
const CharacterListRow = GObject.registerClass({
}, class CharacterListRow extends GObject.Object {
_init(characters, fontDescription, overlayFontDescription) {
super._init({});
this._baseGlyphRect = null;
this._characters = characters;
this._fontDescription = fontDescription;
this._overlayFontDescription = overlayFontDescription;
}
snapshot(snapshot, x, y, pangoContext, styleContext) {
let layout = Pango.Layout.new(pangoContext);
layout.set_font_description(this._fontDescription);
// Draw characters. Do centering and attach to the baseline.
let cellSize = getCellSize(this._fontDescription);
for (let i in this._characters) {
let character = this._characters[i];
let cellRect = new Gdk.Rectangle({
x: x + cellSize * i,
y,
width: cellSize,
height: cellSize,
});
layout.set_text(character, -1);
snapshot.save();
if (Gc.character_is_invisible(character)) {
this._drawBoundingBox(snapshot, layout, styleContext, cellRect);
this._drawCharacterName(snapshot, pangoContext, styleContext, cellRect, character);
} else if (layout.get_unknown_glyphs_count() === 0) {
let layoutBaseline = layout.get_baseline();
let logicalRect = layout.get_extents()[0];
snapshot.translate(new Graphene.Point({
x: x + cellSize * i - logicalRect.x / Pango.SCALE + (cellSize - logicalRect.width / Pango.SCALE) / 2,
y: y + BASELINE_OFFSET * cellSize - layoutBaseline / Pango.SCALE,
}));
let textColor = styleContext.get_color();
snapshot.append_layout(layout, textColor);
} else {
this._drawBoundingBox(snapshot, layout, styleContext, cellRect);
this._drawCharacterName(snapshot, pangoContext, styleContext, cellRect, character);
}
snapshot.restore();
}
}
_computeBoundingBox(layout, cellRect) {
let shapeRect;
let layoutBaseline;
if (layout.get_unknown_glyphs_count() === 0) {
let inkRect = layout.get_extents()[1];
layoutBaseline = layout.get_baseline();
shapeRect = inkRect;
} else {
// If the character cannot be rendered with the current
// font settings, show a rectangle calculated from the
// base glyphs ('AA').
if (this._baseGlyphRect === null) {
layout.set_text('AA', -1);
let baseInkRect = layout.get_extents()[1];
this._baseGlyphLayoutBaseline = layout.get_baseline();
this._baseGlyphRect = baseInkRect;
}
layoutBaseline = this._baseGlyphLayoutBaseline;
shapeRect = new Pango.Rectangle({
x: this._baseGlyphRect.x,
y: this._baseGlyphRect.y,
width: this._baseGlyphRect.width,
height: this._baseGlyphRect.height,
});
}
shapeRect.x = cellRect.x - shapeRect.x / Pango.SCALE + (cellRect.width - shapeRect.width / Pango.SCALE) / 2;
shapeRect.y = cellRect.y + BASELINE_OFFSET * cellRect.height - layoutBaseline / Pango.SCALE;
shapeRect.width /= Pango.SCALE;
shapeRect.height /= Pango.SCALE;
return shapeRect;
}
_drawBoundingBox(snapshot, pangoLayout, styleContext, cellRect) {
snapshot.save();
let shapeRect = this._computeBoundingBox(pangoLayout, cellRect);
let borderWidth = 1;
let boxBgColor = styleContext.get_color();
boxBgColor.alpha = 0.05;
snapshot.append_color(boxBgColor,
new Graphene.Rect({
origin: new Graphene.Point({
x: shapeRect.x - borderWidth * 2,
y: shapeRect.y - borderWidth * 2,
}),
size: new Graphene.Size({
width: shapeRect.width + borderWidth * 2,
height: shapeRect.height + borderWidth * 2,
}),
}),
);
snapshot.restore();
}
_drawCharacterName(snapshot, pangoContext, styleContext, cellRect, uc) {
snapshot.save();
let layout = Pango.Layout.new(pangoContext);
layout.set_width(cellRect.width * Pango.SCALE * 0.8);
layout.set_height(cellRect.height * Pango.SCALE * 0.8);
layout.set_wrap(Pango.WrapMode.WORD);
layout.set_ellipsize(Pango.EllipsizeMode.END);
layout.set_alignment(Pango.Alignment.CENTER);
layout.set_font_description(this._overlayFontDescription);
let name = Gc.character_name(uc);
let text = name === null ? _('Unassigned') : Util.capitalize(name);
layout.set_text(text, -1);
let logicalRect = layout.get_extents()[0];
snapshot.translate(new Graphene.Point({
x: cellRect.x - logicalRect.x / Pango.SCALE + (cellRect.width - logicalRect.width / Pango.SCALE) / 2,
y: cellRect.y - logicalRect.y / Pango.SCALE + (cellRect.height - logicalRect.height / Pango.SCALE) / 2,
}));
let textColor = styleContext.get_color();
snapshot.append_layout(layout, textColor);
snapshot.restore();
}
});
var CharactersView = GObject.registerClass({
Signals: {
'character-selected': { param_types: [GObject.TYPE_STRING] },
},
Properties: {
'vscroll-policy': GObject.ParamSpec.override('vscroll-policy', Gtk.Scrollable),
'vadjustment': GObject.ParamSpec.override('vadjustment', Gtk.Scrollable),
'hscroll-policy': GObject.ParamSpec.override('hscroll-policy', Gtk.Scrollable),
'hadjustment': GObject.ParamSpec.override('hadjustment', Gtk.Scrollable),
'loading': GObject.ParamSpec.boolean(
'loading',
'Loading', 'Whether the category is still loading',
GObject.ParamFlags.READWRITE,
false,
),
'baseline': GObject.ParamSpec.boolean(
'baseline',
'Baseline', 'Whether to draw a baseline or not',
GObject.ParamFlags.READWRITE,
true,
),
},
Implements: [Gtk.Scrollable],
}, class CharactersView extends Gtk.Widget {
_init() {
super._init({
vadjustment: new Gtk.Adjustment(),
hadjustment: new Gtk.Adjustment(),
overflow: Gtk.Overflow.HIDDEN,
});
this._scripts = [];
this._scriptsLoaded = false;
let context = this.get_pango_context();
this._fontDescription = context.get_font_description();
this._fontDescription.set_size(CELL_SIZE * Pango.SCALE);
this._selectedCharacter = null;
this._characters = [];
this._searchContext = null;
this._cancellable = new Gio.Cancellable();
this._cancellable.connect(() => {
this._searchContext = null;
this._characters = [];
});
this._cellsPerRow = CELLS_PER_ROW;
this._numRows = NUM_ROWS;
this._rows = [];
/*
this.drag_source_set(Gdk.ModifierType.BUTTON1_MASK,
null,
Gdk.DragAction.COPY);
this.drag_source_add_text_targets();
*/
const gestureClick = new Gtk.GestureClick();
gestureClick.connect('pressed', this.onButtonPress.bind(this));
gestureClick.connect('released', this.onButtonRelease.bind(this));
this.add_controller(gestureClick);
}
get fontDescription() {
return this._fontDescription;
}
get vadjustment() {
return this._vadjustment;
}
set vadjustment(adj) {
adj.connect('value-changed', () => {
this.queue_draw();
});
this._vadjustment = adj;
}
get hadjustment() {
return this._hadjustment;
}
set hadjustment(adj) {
adj.connect('value-changed', () => {
this.queue_draw();
});
this._hadjustment = adj;
}
/*
vfunc_drag_begin(context) {
let cellSize = getCellSize(this._fontDescription);
this._dragSurface = new Cairo.ImageSurface(Cairo.Format.ARGB32,
cellSize,
cellSize);
let cr = new Cairo.Context(this._dragSurface);
cr.setSourceRGBA(1.0, 1.0, 1.0, 1.0);
cr.paint();
cr.setSourceRGBA(0.0, 0.0, 0.0, 1.0);
let row = this._createCharacterListRow([this._character]);
row.draw(cr, 0, 0, cellSize, cellSize, this.get_style_context());
Gtk.drag_set_icon_surface(context, this._dragSurface, 0, 0);
}
vfunc_drag_data_get(context, data, info, time) {
if (this._character !== null)
data.set_text(this._character, -1);
}
*/
onButtonPress(_gesture, _nPress, x, y) {
let hadj = this.get_hadjustment();
let vadj = this.get_vadjustment();
let cellSize = getCellSize(this._fontDescription);
x = Math.min(this._cellsPerRow - 1, Math.floor((x + hadj.get_value() - this._offsetX) / cellSize));
y = Math.floor((y + vadj.get_value()) / cellSize);
let index = y * this._cellsPerRow + Math.max(0, x);
if (index < this._characters.length)
this._selectedCharacter = this._characters[index];
else
this._selectedCharacter = null;
}
onButtonRelease() {
if (this._selectedCharacter)
this.emit('character-selected', this._selectedCharacter);
}
vfunc_measure(orientation, _forSize) {
if (orientation === Gtk.Orientation.HORIZONTAL) {
let cellSize = getCellSize(this._fontDescription);
let minWidth = NUM_COLUMNS * cellSize;
let natWidth = Math.max(this._cellsPerRow, NUM_COLUMNS) * cellSize;
return [minWidth, natWidth, -1, -1];
} else {
let height = Math.max(this._rows.length, this._numRows) *
getCellSize(this._fontDescription);
return [height, height, -1, -1];
}
}
vfunc_snapshot(snapshot) {
let vadj = this.get_vadjustment();
let styleContext = this.get_style_context();
let pangoContext = this.get_pango_context();
let cellSize = getCellSize(this._fontDescription);
let scrollPos = Math.floor(vadj.get_value());
let start = Math.max(0, Math.floor(scrollPos / cellSize));
let end = Math.min(this._rows.length, Math.ceil((scrollPos + vadj.get_page_size()) / cellSize));
let offsetY = scrollPos % cellSize;
snapshot.translate(new Graphene.Point({ x: 0, y: -offsetY }));
let borderColor = styleContext.lookup_color('borders')[1];
let allocatedWidth = this.get_allocation().width;
this._offsetX = (allocatedWidth - cellSize * this._cellsPerRow) / 2;
for (let index = start; index < end; index++) {
let y = (index - start) * cellSize;
// Draw baseline.
if (this.baseline) {
snapshot.append_color(borderColor, new Graphene.Rect({
origin: new Graphene.Point({ x: 0, y: y + BASELINE_OFFSET * cellSize }),
size: new Graphene.Size({ width: allocatedWidth, height: 1.0 }),
}));
}
this._rows[index].snapshot(snapshot, this._offsetX, y, pangoContext, styleContext);
}
}
vfunc_size_allocate(width, height, baseline) {
super.vfunc_size_allocate(width, height, baseline);
let cellSize = getCellSize(this._fontDescription);
let cellsPerRow = Math.floor(width / cellSize);
if (cellsPerRow !== this._cellsPerRow) {
// Reflow if the number of cells per row has changed.
this._cellsPerRow = cellsPerRow;
this._reflow();
}
let maxHeight = Math.floor((this._rows.length + BASELINE_OFFSET) * cellSize);
let maxWidth = cellsPerRow * cellSize;
let hadj = this.get_hadjustment();
let vadj = this.get_vadjustment();
vadj.configure(vadj.get_value(), 0.0, maxHeight, 0.1 * height, 0.9 * height, Math.min(height, maxHeight));
hadj.configure(hadj.get_value(), 0.0, maxWidth, 0.1 * width, 0.9 * width, Math.min(width, maxWidth));
}
_createCharacterListRow(characters) {
var context = this.get_pango_context();
var overlayFontDescription = context.get_font_description();
overlayFontDescription.set_size(overlayFontDescription.get_size() * 0.8);
let row = new CharacterListRow(characters, this._fontDescription, overlayFontDescription);
return row;
}
setFontDescription(fontDescription) {
this._fontDescription = fontDescription;
}
_reflow() {
this._rows = [];
let start = 0, stop = 1;
for (; stop <= this._characters.length; stop++) {
if (stop % this._cellsPerRow === 0) {
let rowCharacters = this._characters.slice(start, stop);
let row = this._createCharacterListRow(rowCharacters);
this._rows.push(row);
start = stop;
}
}
if (start !== stop - 1) {
let rowCharacters = this._characters.slice(start, stop);
let row = this._createCharacterListRow(rowCharacters);
this._rows.push(row);
}
}
setCharacters(characters) {
this._characters = characters;
this._reflow();
this.queue_resize();
}
_addSearchResult(result) {
const characters = Util.searchResultToArray(result);
this.setCharacters(this._characters.concat(characters));
}
async _searchWithContext(context) {
try {
let result = await context.search(Number.MAX_SAFE_INTEGER, this._cancellable);
this._addSearchResult(result);
} catch (e) {
log(`Failed to search: ${e.message}`);
}
}
async searchByCategory(category) {
this._characters = [];
// whether to draw a baseline or not
this.baseline = category <= Gc.Category.LETTER_LATIN;
if (category === Gc.Category.LETTER_LATIN) {
if (!this._scriptsLoaded)
await this.populateScripts(); // we run the search once the scripts are loaded
await this._searchByScripts();
return;
}
let criteria = Gc.SearchCriteria.new_category(category);
this._searchContext = new Gc.SearchContext({ criteria });
await this._searchWithContext(this._searchContext);
}
async searchByKeywords(keywords) {
const criteria = Gc.SearchCriteria.new_keywords(keywords);
this._searchContext = new Gc.SearchContext({
criteria,
flags: Gc.SearchFlag.WORD,
});
await this._searchWithContext(this._searchContext);
return this._characters.length;
}
async _searchByScripts() {
var criteria = Gc.SearchCriteria.new_scripts(this.scripts);
this._searchContext = new Gc.SearchContext({ criteria });
await this._searchWithContext(this._searchContext);
}
cancelSearch() {
this._cancellable.cancel();
this._cancellable.reset();
}
// / Specific to GC_CATEGORY_LETTER_LATIN
get scripts() {
return this._scripts;
}
// / Populate the "scripts" based on the current locale
// / and the input-sources settings.
async populateScripts() {
this.loading = true;
let settings =
Util.getSettings('org.gnome.desktop.input-sources',
'/org/gnome/desktop/input-sources/');
if (settings) {
let sources = settings.get_value('sources').deep_unpack();
let hasIBus = sources.some((current, _index, _array) => {
return current[0] === 'ibus';
});
if (hasIBus)
await this._ensureIBusLanguageList(sources);
else
this._finishBuildScriptList(sources);
}
}
async _ensureIBusLanguageList(sources) {
if (this._ibusLanguageList !== null)
return;
this._ibusLanguageList = {};
// Don't assume IBus is always available.
let ibus;
try {
ibus = imports.gi.IBus;
} catch (e) {
this._finishBuildScriptList(sources);
return;
}
Gio._promisify(ibus.Bus.prototype, 'list_engines_async', 'list_engines_async_finish');
ibus.init();
let bus = new ibus.Bus();
if (bus.is_connected()) {
let engines = await bus.list_engines_async(-1, null);
try {
for (let j in engines) {
let engine = engines[j];
let language = engine.get_language();
if (language !== null)
this._ibusLanguageList[engine.get_name()] = language;
}
} catch (e) {
log(`Failed to list engines: ${e.message}`);
}
}
this._finishBuildScriptList(sources);
}
_finishBuildScriptList(sources) {
let xkbInfo = new GnomeDesktop.XkbInfo();
let languages = [];
for (let i in sources) {
let [type, id] = sources[i];
switch (type) {
case 'xkb':
// FIXME: Remove this check once gnome-desktop gets the
// support for that.
if (xkbInfo.get_languages_for_layout) {
languages = languages.concat(
xkbInfo.get_languages_for_layout(id));
}
break;
case 'ibus':
if (id in this._ibusLanguageList)
languages.push(this._ibusLanguageList[id]);
break;
}
}
// Add current locale language to languages.
languages.push(Gc.get_current_language());
let allScripts = [];
for (let i in languages) {
let language = GnomeDesktop.normalize_locale(languages[i]);
if (language === null)
continue;
let scripts = Gc.get_scripts_for_language(languages[i]);
for (let j in scripts) {
let script = scripts[j];
// Exclude Latin and Han, since Latin is always added
// at the top and Han contains too many characters.
if ([GLib.UnicodeScript.LATIN, GLib.UnicodeScript.HAN].indexOf(script) >= 0)
continue;
if (allScripts.indexOf(script) >= 0)
continue;
allScripts.push(script);
}
}
allScripts.unshift(GLib.UnicodeScript.LATIN);
this._scripts = allScripts;
this._scriptsLoaded = true;
this.loading = false;
this._searchByScripts();
}
});
(uuay)Characters/ searchProvider.js � /* exported SearchProvider */
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
// Copyright (c) 2013 Giovanni Campagna <scampa.giovanni@gmail.com>
// Copyright (C) 2015 Daiki Ueno <dueno@src.gnome.org>
//
// Gnome Weather is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// Gnome Weather is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with Gnome Weather; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
const { Gc, Gio, GLib, GObject } = imports.gi;
const ByteArray = imports.byteArray;
const Util = imports.util;
const MAX_SEARCH_RESULTS = 20;
const SearchProviderInterface = ByteArray.toString(Gio.resources_lookup_data('/org/gnome/shell/ShellSearchProvider2.xml', 0).toArray());
var SearchProvider = GObject.registerClass({
Name: 'CharactersSearchProvider',
}, class SearchProvider extends GObject.Object {
_init(application) {
this._app = application;
this._impl = Gio.DBusExportedObject.wrapJSObject(SearchProviderInterface, this);
this._cancellable = new Gio.Cancellable();
}
export(connection, path) {
return this._impl.export(connection, path);
}
unexport(connection) {
return this._impl.unexport_from_connection(connection);
}
_runQuery(keywords, invocation) {
this._app.hold();
this._cancellable.cancel();
this._cancellable.reset();
let upper = keywords.map(x => x.toUpperCase());
let criteria = Gc.SearchCriteria.new_keywords(upper);
let context = new Gc.SearchContext({ criteria, flags: Gc.SearchFlag.WORD });
context.search(
MAX_SEARCH_RESULTS,
this._cancellable,
(_source, res, _userData) => {
let characters = [];
try {
let result = context.search_finish(res);
characters = Util.searchResultToArray(result);
} catch (e) {
log(`Failed to search by keywords: ${e.message}`);
}
invocation.return_value(new GLib.Variant('(as)', [characters]));
this._app.release();
});
}
GetInitialResultSetAsync(params, invocation) {
this._runQuery(params[0], invocation);
}
GetSubsearchResultSetAsync(params, invocation) {
this._runQuery(params[1], invocation);
}
GetResultMetas(identifiers) {
this._app.hold();
let ret = [];
for (let i = 0; i < identifiers.length; i++) {
let character = identifiers[i];
let name = Gc.character_name(character);
if (name === null)
name = _('Unknown character name');
else
name = Util.capitalize(name);
let summary = '';
if (!Gc.character_is_composite(character)) {
let codePoint = Util.toCodePoint(character);
let codePointHex = codePoint.toString(16).toUpperCase();
summary = _('U+%s').format(codePointHex);
}
let iconData = Util.characterToIconData(character);
if (!iconData)
continue;
ret.push({
name: new GLib.Variant('s', name),
id: new GLib.Variant('s', identifiers[i]),
description: new GLib.Variant('s', summary),
clipboardText: new GLib.Variant('s', character),
'icon-data': iconData,
});
}
this._app.release();
return ret;
}
ActivateResult(_id, _terms, _timestamp) {
log('activating result');
const notification = Gio.Notification.new(_('Character copied'));
notification.set_body(_('Character was copied successfully'));
this._app.send_notification(null, notification);
}
LaunchSearch(terms, timestamp) {
this._app.activate();
const window = this._app.window;
window.setSearchKeywords(terms);
window.present_with_time(timestamp);
}
});
(uuay)util.js /* exported capitalize getSettings initActions searchResultToArray toCodePoint characterToIconData */
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
// Copyright (c) 2013 Giovanni Campagna <scampa.giovanni@gmail.com>
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the GNOME Foundation nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
const { Gc, Gio, Gdk, GLib, Graphene, Gsk, Gtk, PangoCairo, Pango } = imports.gi;
const System = imports.system;
function initActions(actionMap, simpleActionEntries, context) {
simpleActionEntries.forEach(({ name, parameterType, state, activate }) => {
let action = new Gio.SimpleAction({
name,
parameter_type: parameterType || null,
state: state || null,
});
context = context || actionMap;
if (activate)
action.connect('activate', activate.bind(context));
actionMap.add_action(action);
});
}
function getSettings(schemaId, path) {
const GioSSS = Gio.SettingsSchemaSource;
let schemaSource;
if (!pkg.moduledir.startsWith('resource://')) {
// Running from the source tree
schemaSource = GioSSS.new_from_directory(pkg.pkgdatadir, GioSSS.get_default(), false);
} else {
schemaSource = GioSSS.get_default();
}
let schemaObj = schemaSource.lookup(schemaId, true);
if (!schemaObj) {
log(`Missing GSettings schema ${schemaId}`);
System.exit(1);
}
if (path === undefined)
return new Gio.Settings({ settings_schema: schemaObj });
else
return Gio.Settings.new_full(schemaObj, null, path);
}
function capitalizeWord(w) {
if (w.length > 0)
return w[0].toUpperCase() + w.slice(1).toLowerCase();
return w;
}
function capitalize(s) {
return s.split(/\s+/).map(w => {
let acronyms = ['CJK'];
if (acronyms.indexOf(w) > -1)
return w;
let prefixes = ['IDEOGRAPH-', 'SELECTOR-'];
for (let index in prefixes) {
let prefix = prefixes[index];
if (w.startsWith(prefix))
return capitalizeWord(prefix) + w.slice(prefix.length);
}
return capitalizeWord(w);
}).join(' ');
}
function toCodePoint(s) {
let codePoint = s.charCodeAt(0);
if (codePoint >= 0xD800 && codePoint <= 0xDBFF) {
let high = codePoint;
let low = s.charCodeAt(1);
codePoint = 0x10000 + (high - 0xD800) * 0x400 + (low - 0xDC00);
}
return codePoint;
}
function searchResultToArray(result) {
let characters = [];
for (let index = 0; index < result.len; index++) {
const c = Gc.search_result_get(result, index);
if (c.trim().length)
characters.push(c);
}
return characters;
}
function characterToIconData(character) {
let size = 48.0;
if (!character || !character.trim().length)
return null;
const fontMap = PangoCairo.FontMap.get_default();
const context = fontMap.create_context();
const layout = Pango.Layout.new(context);
layout.set_text(character, -1);
let white = new Gdk.RGBA({ red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0 });
let [textWidth, textHeight] = layout.get_pixel_size();
let textSize = Math.max(textWidth, textHeight);
const snapshot = Gtk.Snapshot.new();
let originX = (textSize - textWidth) / 2.0;
let originY = (textSize - textHeight) / 2.0;
let origin = new Graphene.Point({ x: originX, y: originY });
let ratio = size / textSize;
snapshot.scale(ratio, ratio);
snapshot.save();
snapshot.translate(origin);
snapshot.append_layout(layout, white);
snapshot.restore();
const node = snapshot.to_node();
// The snapshot may contain no nodes if there's nothing to render, like in
// case of a layout that only contains invisible chars:
// https://gitlab.gnome.org/GNOME/gtk/-/issues/5747
if (!node)
return null;
let renderer = Gsk.GLRenderer.new();
try {
renderer.realize(null);
} catch (e) {
renderer = new Gsk.CairoRenderer();
renderer.realize(null);
}
let rect = new Graphene.Rect({
origin: new Graphene.Point({ x: 0.0, y: 0.0 }),
size: new Graphene.Size({ width: size, height: size }),
});
const texture = renderer.render_texture(node, rect);
renderer.unrealize();
const textureDownloader = new Gdk.TextureDownloader(texture);
textureDownloader.set_format(Gdk.MemoryFormat.R8G8B8A8);
const [bytes, stride] = textureDownloader.download_bytes();
return GLib.Variant.new_tuple([
new GLib.Variant('i', texture.get_width()),
new GLib.Variant('i', texture.get_height()),
new GLib.Variant('i', stride),
new GLib.Variant('b', /* has alpha */ true),
new GLib.Variant('i', /* bits per sample */ 8),
new GLib.Variant('i', /* channels */ 4),
GLib.Variant.new_from_bytes(
GLib.VariantType.new('ay'), bytes, true),
]);
}
(uuay)sidebarRow.js � /* exported SidebarRow */
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
// Copyright (C) 2014-2017 Daiki Ueno <dueno@src.gnome.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
const { Gc, GObject, Gtk } = imports.gi;
var SidebarRow = GObject.registerClass({
Properties: {
'title': GObject.ParamSpec.string(
'title',
'Category title', 'Category title',
GObject.ParamFlags.READWRITE,
'',
),
'category': GObject.ParamSpec.enum(
'category',
'Category', 'Category',
GObject.ParamFlags.READWRITE,
Gc.Category.$gtype,
Gc.Category.NONE,
),
'icon-name': GObject.ParamSpec.string(
'icon-name',
'Category Icon Name', 'Category Icon Name',
GObject.ParamFlags.READWRITE,
'',
),
},
}, class SidebarRow extends Gtk.ListBoxRow {
_init() {
super._init({
accessible_role: Gtk.AccessibleRole.ROW,
});
let hbox = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
margin_top: 12,
margin_bottom: 12,
margin_start: 6,
margin_end: 6,
spacing: 12,
});
let image = new Gtk.Image();
this.bind_property('icon-name', image, 'icon-name',
GObject.BindingFlags.DEFAULT | GObject.BindingFlags.SYNC_CREATE,
);
image.set_icon_size(Gtk.IconSize.LARGE_TOOLBAR);
hbox.append(image);
let label = new Gtk.Label({ halign: Gtk.Align.START });
this.bind_property('title', label, 'label',
GObject.BindingFlags.DEFAULT | GObject.BindingFlags.SYNC_CREATE,
);
// Because bind_property doesn't work with transform functions
// TODO: is this really needed?
this.connect('notify::title', row => {
row.tooltip_text = _('%s Sidebar Row').format(row.title);
});
hbox.append(label);
this.set_child(hbox);
}
get title() {
return this._title || '';
}
set title(title) {
this._title = title;
}
get category() {
return this._category || Gc.Category.NONE;
}
set category(value) {
this._category = value;
}
});
(uuay)sidebar.js � /* exported Sidebar */
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
// Copyright (C) 2014-2017 Daiki Ueno <dueno@src.gnome.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
const { Adw, GObject } = imports.gi;
const { SidebarRow } = imports.sidebarRow;
var Sidebar = GObject.registerClass({
Template: 'resource:///org/gnome/Characters/sidebar.ui',
InternalChildren: [
'list',
'recentRow', 'emojiSmileysRow', 'emojiPeopleRow', 'emojiAnimalsRow',
'emojiFoodRow', 'emojiActivitiesRow', 'emojiTravelRow',
'emojiObjectsRow', 'emojiSymbolsRow', 'emojiFlagsRow',
'lettersPunctuationRow', 'lettersArrowsRow',
'lettersBulletsRow', 'lettersPicturesRow',
'lettersCurrencyRow', 'lettersMathRow', 'lettersLatinRow',
],
}, class Sidebar extends Adw.Bin {
_init() {
GObject.type_ensure(SidebarRow.$gtype);
super._init({});
this.lastSelectedRow = null;
}
/**
* Restore the latest selected item
*/
restoreSelection() {
if (this.lastSelectedRow)
this._list.select_row(this.lastSelectedRow);
}
rowByName(name) {
switch (name) {
case 'smileys':
return this._emojiSmileysRow;
case 'people':
return this._emojiPeopleRow;
case 'animals':
return this._emojiAnimalsRow;
case 'food':
return this._emojiFoodRow;
case 'activities':
return this._emojiActivitesRow;
case 'travel':
return this._emojiTravelRow;
case 'objects':
return this._emojiObjectsRow;
case 'symbols':
return this._emojiSymbolsRow;
case 'flags':
return this._emojiFlagsRow;
case 'punctuation':
return this._lettersPunctuationRow;
case 'arrows':
return this._lettersArrowsRow;
case 'bullets':
return this._lettersBulletsRow;
case 'pictures':
return this._lettersPicturesRow;
case 'currency':
return this._lettersCurrencyRow;
case 'math':
return this._lettersMathRow;
case 'latin':
return this._lettersLatinRow;
default:
return this._recentRow;
}
}
selectRowByName(name) {
let row = this.rowByName(name);
this._list.select_row(row);
}
unselectAll() {
this._list.unselect_all();
}
get list() {
return this._list;
}
});
(uuay)window.js�&