Redo AppWell glow to be based on a based on a .png instead of cairo
Instead of drawing an ellipse, use a hand-drawn .png file which looks a bit less regular and blends better.
This commit is contained in:
parent
11872cfb79
commit
52abf266c0
BIN
data/app-well-glow.png
Normal file
BIN
data/app-well-glow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const Big = imports.gi.Big;
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
@ -11,7 +12,8 @@ const Main = imports.ui.main;
|
|||||||
|
|
||||||
const GLOW_COLOR = new Clutter.Color();
|
const GLOW_COLOR = new Clutter.Color();
|
||||||
GLOW_COLOR.from_pixel(0x4f6ba4ff);
|
GLOW_COLOR.from_pixel(0x4f6ba4ff);
|
||||||
const GLOW_PADDING = 5;
|
const GLOW_PADDING_HORIZONTAL = 3;
|
||||||
|
const GLOW_PADDING_VERTICAL = 3;
|
||||||
|
|
||||||
const APP_ICON_SIZE = 48;
|
const APP_ICON_SIZE = 48;
|
||||||
|
|
||||||
@ -41,8 +43,10 @@ AppIcon.prototype = {
|
|||||||
|
|
||||||
this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
|
this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
|
||||||
|
|
||||||
let nameBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
let nameBox = new Shell.GenericContainer();
|
||||||
x_align: Big.BoxAlignment.CENTER });
|
nameBox.connect('get-preferred-width', Lang.bind(this, this._nameBoxGetPreferredWidth));
|
||||||
|
nameBox.connect('get-preferred-height', Lang.bind(this, this._nameBoxGetPreferredHeight));
|
||||||
|
nameBox.connect('allocate', Lang.bind(this, this._nameBoxAllocate));
|
||||||
this._nameBox = nameBox;
|
this._nameBox = nameBox;
|
||||||
|
|
||||||
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
@ -50,34 +54,58 @@ AppIcon.prototype = {
|
|||||||
line_alignment: Pango.Alignment.CENTER,
|
line_alignment: Pango.Alignment.CENTER,
|
||||||
ellipsize: Pango.EllipsizeMode.END,
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
text: appInfo.get_name() });
|
text: appInfo.get_name() });
|
||||||
nameBox.append(this._name, Big.BoxPackFlags.NONE);
|
nameBox.add_actor(this._name);
|
||||||
if (this._windows.length > 0) {
|
this._glowBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||||
let glow = new Shell.DrawingArea({});
|
let glowPath = GLib.filename_to_uri(Shell.Global.get().imagedir + 'app-well-glow.png', '');
|
||||||
glow.connect('redraw', Lang.bind(this, function (e, tex) {
|
for (let i = 0; i < this._windows.length && i < 3; i++) {
|
||||||
Shell.draw_app_highlight(tex,
|
let glow = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||||
this._windows.length,
|
glowPath, -1, -1);
|
||||||
GLOW_COLOR.red / 255,
|
glow.keep_aspect_ratio = false;
|
||||||
GLOW_COLOR.green / 255,
|
this._glowBox.append(glow, Big.BoxPackFlags.EXPAND);
|
||||||
GLOW_COLOR.blue / 255,
|
|
||||||
GLOW_COLOR.alpha / 255);
|
|
||||||
}));
|
|
||||||
this._name.connect('notify::allocation', Lang.bind(this, function () {
|
|
||||||
let x = this._name.x;
|
|
||||||
let y = this._name.y;
|
|
||||||
let width = this._name.width;
|
|
||||||
let height = this._name.height;
|
|
||||||
// If we're smaller than the allocated box width, pad out the glow a bit
|
|
||||||
// to make it more visible
|
|
||||||
if ((width + GLOW_PADDING * 2) < this._nameBox.width) {
|
|
||||||
width += GLOW_PADDING * 2;
|
|
||||||
x -= GLOW_PADDING;
|
|
||||||
}
|
|
||||||
glow.set_size(width, height);
|
|
||||||
glow.set_position(x, y);
|
|
||||||
}));
|
|
||||||
nameBox.add_actor(glow);
|
|
||||||
glow.lower(this._name);
|
|
||||||
}
|
}
|
||||||
|
this._nameBox.add_actor(this._glowBox);
|
||||||
|
this._glowBox.lower(this._name);
|
||||||
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
|
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxGetPreferredWidth: function (nameBox, forHeight, alloc) {
|
||||||
|
let [min, natural] = this._name.get_preferred_width(forHeight);
|
||||||
|
alloc.min_size = min + GLOW_PADDING_HORIZONTAL * 2;
|
||||||
|
alloc.natural_size = natural + GLOW_PADDING_HORIZONTAL * 2;
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxGetPreferredHeight: function (nameBox, forWidth, alloc) {
|
||||||
|
let [min, natural] = this._name.get_preferred_height(forWidth);
|
||||||
|
alloc.min_size = min + GLOW_PADDING_VERTICAL * 2;
|
||||||
|
alloc.natural_size = natural + GLOW_PADDING_VERTICAL * 2;
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxAllocate: function (nameBox, box, flags) {
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
let [minWidth, naturalWidth] = this._name.get_preferred_width(-1);
|
||||||
|
let [minHeight, naturalHeight] = this._name.get_preferred_height(-1);
|
||||||
|
let availWidth = box.x2 - box.x1;
|
||||||
|
let availHeight = box.y2 - box.y1;
|
||||||
|
let targetWidth = availWidth;
|
||||||
|
let xPadding = 0;
|
||||||
|
if (naturalWidth < availWidth) {
|
||||||
|
xPadding = (availWidth - naturalWidth) / 2;
|
||||||
|
}
|
||||||
|
childBox.x1 = Math.floor(xPadding);
|
||||||
|
childBox.x2 = availWidth;
|
||||||
|
childBox.y1 = GLOW_PADDING_VERTICAL;
|
||||||
|
childBox.y2 = availHeight - GLOW_PADDING_VERTICAL;
|
||||||
|
this._name.allocate(childBox, flags);
|
||||||
|
|
||||||
|
// Now the glow
|
||||||
|
|
||||||
|
if (this._glowBox != null) {
|
||||||
|
let glowPaddingHoriz = Math.max(0, xPadding - GLOW_PADDING_HORIZONTAL);
|
||||||
|
childBox.x1 = Math.floor(glowPaddingHoriz);
|
||||||
|
childBox.x2 = availWidth - glowPaddingHoriz;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.y2 = availHeight;
|
||||||
|
this._glowBox.allocate(childBox, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -146,82 +146,6 @@ shell_draw_clock (ClutterCairoTexture *texture,
|
|||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
draw_glow (cairo_t *cr, double red, double green, double blue, double alpha)
|
|
||||||
{
|
|
||||||
cairo_pattern_t *gradient;
|
|
||||||
|
|
||||||
cairo_save (cr);
|
|
||||||
|
|
||||||
gradient = cairo_pattern_create_radial (0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
|
|
||||||
cairo_pattern_add_color_stop_rgba (gradient, 0.0, red, green, blue, alpha);
|
|
||||||
cairo_pattern_add_color_stop_rgba (gradient, 0.7, red, green, blue, alpha * 0.7);
|
|
||||||
cairo_pattern_add_color_stop_rgba (gradient, 1.0, red, green, blue, alpha * 0.3);
|
|
||||||
cairo_set_source (cr, gradient);
|
|
||||||
|
|
||||||
cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 2.0 * M_PI);
|
|
||||||
cairo_fill (cr);
|
|
||||||
|
|
||||||
cairo_restore (cr);
|
|
||||||
cairo_pattern_destroy (gradient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
shell_draw_app_highlight (ClutterCairoTexture *texture,
|
|
||||||
int num_windows,
|
|
||||||
double red,
|
|
||||||
double green,
|
|
||||||
double blue,
|
|
||||||
double alpha)
|
|
||||||
{
|
|
||||||
cairo_t *cr;
|
|
||||||
guint width, height;
|
|
||||||
|
|
||||||
g_return_if_fail (num_windows > 0);
|
|
||||||
|
|
||||||
clutter_cairo_texture_get_surface_size (texture, &width, &height);
|
|
||||||
|
|
||||||
clutter_cairo_texture_clear (texture);
|
|
||||||
cr = clutter_cairo_texture_create (texture);
|
|
||||||
|
|
||||||
cairo_save (cr);
|
|
||||||
cairo_translate (cr, width / 2.0, height / 2.0);
|
|
||||||
|
|
||||||
if (num_windows == 1)
|
|
||||||
{
|
|
||||||
cairo_scale (cr, width / 2.0, height / 2.0);
|
|
||||||
draw_glow (cr, red, green, blue, alpha);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int num_circles, i;
|
|
||||||
double scale, highlight_width;
|
|
||||||
|
|
||||||
num_circles = num_windows == 2 ? 2 : 3;
|
|
||||||
|
|
||||||
/* The circles will have radius 1.0 (diameter 2.0) and overlap
|
|
||||||
* by 0.2, so the total width of the highlight is:
|
|
||||||
*/
|
|
||||||
highlight_width = 2.0 * num_circles - 0.2 * (num_circles - 1);
|
|
||||||
|
|
||||||
scale = MIN (height / 2.0, width / highlight_width);
|
|
||||||
cairo_scale (cr, scale, scale);
|
|
||||||
|
|
||||||
/* The leftmost circle's left side is at -highlight_width/2, so
|
|
||||||
* its center is that plus 1.
|
|
||||||
*/
|
|
||||||
cairo_translate (cr, -highlight_width / 2.0 + 1.0, 0.0);
|
|
||||||
for (i = 0; i < num_circles; i++)
|
|
||||||
{
|
|
||||||
draw_glow (cr, red, green, blue, alpha);
|
|
||||||
cairo_translate (cr, 1.8, 0.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_restore (cr);
|
|
||||||
cairo_destroy (cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hook_paint_red_border (ClutterActor *actor,
|
hook_paint_red_border (ClutterActor *actor,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
|
@ -17,13 +17,6 @@ void shell_draw_clock (ClutterCairoTexture *texture,
|
|||||||
int hour,
|
int hour,
|
||||||
int minute);
|
int minute);
|
||||||
|
|
||||||
void shell_draw_app_highlight (ClutterCairoTexture *texture,
|
|
||||||
int num_windows,
|
|
||||||
double red,
|
|
||||||
double blue,
|
|
||||||
double green,
|
|
||||||
double alpha);
|
|
||||||
|
|
||||||
guint shell_add_hook_paint_red_border (ClutterActor *actor);
|
guint shell_add_hook_paint_red_border (ClutterActor *actor);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
Loading…
Reference in New Issue
Block a user