[gnome-characters] characterList: Rewrite as a single drawing area
- From: Daiki Ueno <dueno src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-characters] characterList: Rewrite as a single drawing area
- Date: Tue, 10 Feb 2015 08:43:09 +0000 (UTC)
commit 919d5c9647bbb7624e2032dc7b7b3cba22a8403c
Author: Daiki Ueno <dueno src gnome org>
Date: Tue Feb 10 17:34:47 2015 +0900
characterList: Rewrite as a single drawing area
We used to implement it as a list box containing several drawing area.
To make reflow implementation simpler, this consolidate all the
rendering logic into a single place.
https://bugzilla.gnome.org/show_bug.cgi?id=740260
data/org.gnome.Characters.gschema.xml | 2 +-
src/characterList.js | 210 +++++++++++++--------------------
2 files changed, 83 insertions(+), 129 deletions(-)
---
diff --git a/data/org.gnome.Characters.gschema.xml b/data/org.gnome.Characters.gschema.xml
index 1b28f16..ccf6b9d 100644
--- a/data/org.gnome.Characters.gschema.xml
+++ b/data/org.gnome.Characters.gschema.xml
@@ -1,7 +1,7 @@
<schemalist gettext-domain="org.gnome.Characters">
<schema id="org.gnome.Characters" path="/org/gnome/Characters/">
<key name="font" type="s">
- <default>'Cantarell'</default>
+ <default>'Cantarell 100'</default>
<summary>Font to display characters</summary>
<description>
Use the font to render characters on the character list.
diff --git a/src/characterList.js b/src/characterList.js
index eb0a9d2..88fe5ac 100644
--- a/src/characterList.js
+++ b/src/characterList.js
@@ -1,6 +1,6 @@
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
-// Copyright (C) 2014 Daiki Ueno <dueno src gnome org>
+// 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
@@ -30,97 +30,51 @@ const Main = imports.main;
const Util = imports.util;
const BASELINE_OFFSET = 0.85;
-const CELL_SIZE = 0.20;
const CELLS_PER_ROW = 5;
-const CELL_PIXEL_SIZE = 100;
+const CELL_SIZE = 100;
-const CharacterListRowWidget = new Lang.Class({
- Name: 'CharacterListRowWidget',
- Extends: Gtk.DrawingArea,
- Signals: {
- 'character-selected': { param_types: [ GObject.TYPE_STRING ] }
- },
+function getCellSize(fontDescription) {
+ if (fontDescription == null
+ || fontDescription.get_size() == 0)
+ return CELL_SIZE;
+ return fontDescription.get_size() * 2 / Pango.SCALE;
+}
+
+const CharacterListRow = new Lang.Class({
+ Name: 'CharacterListRow',
+ Extends: GObject.Object,
_init: function(params) {
let filtered = Params.filter(params, { characters: null,
- font: null,
- cellWidth: null });
+ fontDescription: null });
params = Params.fill(params, {});
this.parent(params);
this._characters = filtered.characters;
- this._font = filtered.font;
- this._cellWidth = filtered.cellWidth;
- this.add_events(Gdk.EventMask.BUTTON_PRESS_MASK);
- this.get_style_context().add_class('character-list-row');
- },
-
- vfunc_get_preferred_height: function() {
- let [minWidth, natWidth] = this.vfunc_get_preferred_width();
- return this.vfunc_get_preferred_height_for_width(minWidth);
- },
-
- vfunc_get_preferred_height_for_width: function(width) {
- let rowHeight = width * CELL_SIZE;
- return [rowHeight, rowHeight];
- },
-
- vfunc_get_preferred_width: function() {
- return this.vfunc_get_preferred_width_for_height(0);
- },
-
- vfunc_get_preferred_width_for_height: function(height) {
- let rowWidth = CELL_PIXEL_SIZE * CELLS_PER_ROW;
- return [rowWidth, rowWidth];
- },
-
- vfunc_size_allocate: function(allocation) {
- this.parent(allocation);
-
- if (this._cellWidth < 0)
- this._cellWidth = allocation.width * CELL_SIZE;
+ this._fontDescription = filtered.fontDescription;
},
- vfunc_button_press_event: function(event) {
- let allocation = this.get_allocation();
- let cellIndex = Math.floor(event.x / this._cellWidth);
- if (cellIndex < this._characters.length)
- this.emit('character-selected', this._characters[cellIndex]);
- },
-
- vfunc_draw: function(cr) {
- // Use device coordinates directly, since PangoCairo doesn't
- // work well with scaled matrix:
- // https://bugzilla.gnome.org/show_bug.cgi?id=700592
- let allocation = this.get_allocation();
-
- // Clear the canvas.
- // FIXME: Pick the background color from CSS.
- cr.setSourceRGBA(1, 1, 1, 1);
- cr.paint();
- cr.setSourceRGBA(0, 0, 0, 1);
-
+ draw: function(cr, x, y, width, height) {
let layout = PangoCairo.create_layout(cr);
- let description = Pango.FontDescription.from_string(this._font);
- description.set_absolute_size(this._cellWidth / 2 * Pango.SCALE);
- layout.set_font_description(description);
+ layout.set_font_description(this._fontDescription);
// Draw baseline.
// FIXME: Pick the baseline color from CSS.
cr.setSourceRGBA(114.0 / 255.0, 159.0 / 255.0, 207.0 / 255.0, 1.0);
cr.setLineWidth(0.5);
- cr.moveTo(0, BASELINE_OFFSET * allocation.height);
- cr.relLineTo(allocation.width, 0);
+ cr.moveTo(x, y + BASELINE_OFFSET * height);
+ cr.relLineTo(width, 0);
cr.stroke();
cr.setSourceRGBA(0.0, 0.0, 0.0, 1.0);
// Draw characters. Do centering and attach to the baseline.
+ let cellSize = getCellSize(this._fontDescription);
for (let i in this._characters) {
layout.set_text(this._characters[i], -1);
let layoutBaseline = layout.get_baseline() / Pango.SCALE;
let [logicalRect, inkRect] = layout.get_extents();
- cr.moveTo(this._cellWidth * i - logicalRect.x / Pango.SCALE +
- (this._cellWidth - logicalRect.width / Pango.SCALE) / 2,
- BASELINE_OFFSET * allocation.height - layoutBaseline);
+ cr.moveTo(x + cellSize * i - logicalRect.x / Pango.SCALE +
+ (cellSize - logicalRect.width / Pango.SCALE) / 2,
+ y + BASELINE_OFFSET * height - layoutBaseline);
PangoCairo.show_layout(cr, layout);
}
},
@@ -128,7 +82,7 @@ const CharacterListRowWidget = new Lang.Class({
const CharacterListWidget = new Lang.Class({
Name: 'CharacterListWidget',
- Extends: Gtk.Box,
+ Extends: Gtk.DrawingArea,
Signals: {
'character-selected': { param_types: [ GObject.TYPE_STRING ] }
},
@@ -136,7 +90,7 @@ const CharacterListWidget = new Lang.Class({
'font': GObject.ParamSpec.string(
'font', '', '',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
- 'Cantarell')
+ 'Cantarell 100')
},
get font() {
@@ -144,10 +98,19 @@ const CharacterListWidget = new Lang.Class({
},
set font(v) {
- if (v == this._font)
+ let fontDescription = Pango.FontDescription.from_string(v);
+ if (fontDescription.get_size() == 0)
+ fontDescription.set_size(CELL_SIZE);
+
+ fontDescription.set_absolute_size(
+ fontDescription.get_size() / 2 * Pango.SCALE);
+
+ if (this._fontDescription &&
+ fontDescription.equal(this._fontDescription))
return;
this._font = v;
+ this._fontDescription = fontDescription;
if (this._characters) {
this.setCharacters(this._characters);
this.show_all();
@@ -155,13 +118,25 @@ const CharacterListWidget = new Lang.Class({
},
_init: function(params) {
- params = Params.fill(params, { orientation: Gtk.Orientation.VERTICAL,
- homogeneous: true });
+ params = Params.fill(params, {});
this.parent(params);
this.get_style_context().add_class('character-list');
- Main.settings.bind('font', this, 'font', Gio.SettingsBindFlags.DEFAULT);
- this._cellWidth = -1;
this._cellsPerRow = CELLS_PER_ROW;
+ this._font = null;
+ this._fontDescription = null;
+ this._rows = [];
+ Main.settings.bind('font', this, 'font', Gio.SettingsBindFlags.DEFAULT);
+ this.add_events(Gdk.EventMask.BUTTON_PRESS_MASK);
+ },
+
+ vfunc_button_press_event: function(event) {
+ let allocation = this.get_allocation();
+ let cellSize = getCellSize(this._fontDescription);
+ let x = Math.floor(event.x / cellSize);
+ let y = Math.floor(event.y / cellSize);
+ let index = y * this._cellsPerRow + x;
+ if (index < this._characters.length)
+ this.emit('character-selected', this._characters[index]);
},
vfunc_get_preferred_height: function() {
@@ -170,13 +145,7 @@ const CharacterListWidget = new Lang.Class({
},
vfunc_get_preferred_height_for_width: function(width) {
- let height = 0;
- let children = this.get_children();
- for (let index in children) {
- let [minHeight, natHeight] =
- children[index].get_preferred_height_for_width(width);
- height += minHeight;
- }
+ let height = this._rows.length * getCellSize(this._fontDescription);
return [height, height];
},
@@ -185,66 +154,32 @@ const CharacterListWidget = new Lang.Class({
},
vfunc_get_preferred_width_for_height: function(height) {
- let width = 0;
- let children = this.get_children();
- if (children.length == 0)
- width = CELL_PIXEL_SIZE * CELLS_PER_ROW;
- else {
- for (let index in children) {
- let [minWidth, natWidth] =
- children[index].get_preferred_width_for_height(height);
- width = Math.max(width, minWidth);
- }
- }
+ let width = this._cellsPerRow * getCellSize(this._fontDescription);
return [width, width];
},
vfunc_size_allocate: function(allocation) {
this.parent(allocation);
- if (this._cellWidth < 0)
- this._cellWidth = allocation.width * CELL_SIZE;
-
- // Reflow if the number of cells per row has changed.
- let cellsPerRow = Math.floor(allocation.width / this._cellWidth);
+ let cellSize = getCellSize(this._fontDescription);
+ let cellsPerRow = Math.floor(allocation.width / cellSize);
if (cellsPerRow != this._cellsPerRow) {
+ // Reflow if the number of cells per row has changed.
this._cellsPerRow = cellsPerRow;
this.setCharacters(this._characters);
- this.show_all();
- }
-
- // Make each row have the same height.
- let rowHeight = this._cellWidth;
- let children = this.get_children();
- for (let index in children) {
- let child = children[index];
- var childAllocation = child.get_allocation();
- childAllocation.x = allocation.x;
- childAllocation.y = allocation.y + rowHeight * index;
- childAllocation.width = allocation.width;
- childAllocation.height = rowHeight;
- child.size_allocate(childAllocation);
}
},
_createCharacterListRow: function(characters) {
- let rowWidget = new CharacterListRowWidget({
+ let row = new CharacterListRow({
characters: characters,
- font: this._font,
- cellWidth: this._cellWidth
+ fontDescription: this._fontDescription
});
- rowWidget.connect('character-selected',
- Lang.bind(this, function(row, uc) {
- this.emit('character-selected', uc);
- }));
- return rowWidget;
+ return row;
},
setCharacters: function(characters) {
- let children = this.get_children();
- for (let index in children)
- this.remove(children[index]);
-
+ this._rows = [];
this._characters = characters;
if (characters.length == 0)
@@ -254,15 +189,34 @@ const CharacterListWidget = new Lang.Class({
for (; stop <= characters.length; stop++) {
if (stop % this._cellsPerRow == 0) {
let rowCharacters = characters.slice(start, stop);
- let rowWidget = this._createCharacterListRow(rowCharacters);
- this.pack_start(rowWidget, true, true, 0);
+ let row = this._createCharacterListRow(rowCharacters);
+ this._rows.push(row);
start = stop;
}
}
if (start != stop - 1) {
let rowCharacters = characters.slice(start, stop);
- let rowWidget = this._createCharacterListRow(rowCharacters);
- this.pack_start(rowWidget, true, true, 0);
+ let row = this._createCharacterListRow(rowCharacters);
+ this._rows.push(row);
}
},
+
+ vfunc_draw: function(cr) {
+ // Clear the canvas.
+ // FIXME: Pick the background color from CSS.
+ cr.setSourceRGBA(1, 1, 1, 1);
+ cr.paint();
+ cr.setSourceRGBA(0, 0, 0, 1);
+
+ // Use device coordinates directly, since PangoCairo doesn't
+ // work well with scaled matrix:
+ // https://bugzilla.gnome.org/show_bug.cgi?id=700592
+ let allocation = this.get_allocation();
+
+ let cellSize = getCellSize(this._fontDescription);
+ for (let index in this._rows) {
+ this._rows[index].draw(cr, 0, index * cellSize,
+ allocation.width, cellSize);
+ }
+ }
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]