Add a results pane in the overlay

Display the results pane above the workspaces. The results pane is somewhat
transparent and has a blue gradient background. The dash pane is slightly
transparent and also has a blue gradient background.

The results pane shows up when a More control is clicked. It disappears when
a Less control is clicked, an area outside of the dash area is clicked,
an item starts being dragged, or the overlay mode is exited.

Add shell_global_create_horizontal_gradient() to shell-global.[ch]
This commit is contained in:
Marina Zhurakhinskaya 2009-06-08 19:04:52 -04:00 committed by Colin Walters
parent 837683004d
commit 1154a1e8d7
3 changed files with 235 additions and 65 deletions

View File

@ -33,17 +33,13 @@ const DASH_MIN_WIDTH = 250;
const DASH_SECTION_PADDING_TOP = 6; const DASH_SECTION_PADDING_TOP = 6;
const DASH_SECTION_SPACING = 6; const DASH_SECTION_SPACING = 6;
const DASH_COLUMNS = 1; const DASH_COLUMNS = 1;
const DETAILS_CORNER_RADIUS = 5; const DASH_CORNER_RADIUS = 5;
const DETAILS_BORDER_WIDTH = 1;
const DETAILS_PADDING = 6;
// This is the height of section components other than the item display. // This is the height of section components other than the item display.
const DASH_SECTION_MISC_HEIGHT = (LABEL_HEIGHT + DASH_SECTION_SPACING) * 2 + DASH_SECTION_PADDING_TOP; const DASH_SECTION_MISC_HEIGHT = (LABEL_HEIGHT + DASH_SECTION_SPACING) * 2 + DASH_SECTION_PADDING_TOP;
const DASH_SEARCH_BG_COLOR = new Clutter.Color(); const DASH_SEARCH_BG_COLOR = new Clutter.Color();
DASH_SEARCH_BG_COLOR.from_pixel(0xffffffff); DASH_SEARCH_BG_COLOR.from_pixel(0xffffffff);
const DASH_TEXT_COLOR = new Clutter.Color(); const DASH_TEXT_COLOR = new Clutter.Color();
DASH_TEXT_COLOR.from_pixel(0xffffffff); DASH_TEXT_COLOR.from_pixel(0xffffffff);
const DETAILS_BORDER_COLOR = new Clutter.Color();
DETAILS_BORDER_COLOR.from_pixel(0xffffffff);
// Time for initial animation going into overlay mode // Time for initial animation going into overlay mode
const ANIMATION_TIME = 0.25; const ANIMATION_TIME = 0.25;
@ -73,12 +69,10 @@ const WORKSPACE_GRID_PADDING = 12;
const COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN = 3; const COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN = 3;
const ROWS_FOR_WORKSPACES_REGULAR_SCREEN = 6; const ROWS_FOR_WORKSPACES_REGULAR_SCREEN = 6;
const WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN = 4 - 0.25;
const EXPANDED_DASH_COLUMNS_REGULAR_SCREEN = 2; const EXPANDED_DASH_COLUMNS_REGULAR_SCREEN = 2;
const COLUMNS_FOR_WORKSPACES_WIDE_SCREEN = 4; const COLUMNS_FOR_WORKSPACES_WIDE_SCREEN = 4;
const ROWS_FOR_WORKSPACES_WIDE_SCREEN = 8; const ROWS_FOR_WORKSPACES_WIDE_SCREEN = 8;
const WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN = 5 - 0.25;
const EXPANDED_DASH_COLUMNS_WIDE_SCREEN = 3; const EXPANDED_DASH_COLUMNS_WIDE_SCREEN = 3;
// A multi-state; PENDING is used during animations // A multi-state; PENDING is used during animations
@ -86,6 +80,34 @@ const STATE_ACTIVE = true;
const STATE_PENDING_INACTIVE = false; const STATE_PENDING_INACTIVE = false;
const STATE_INACTIVE = false; const STATE_INACTIVE = false;
// The dash has a slightly transparent blue background with a gradient.
const DASH_LEFT_COLOR = new Clutter.Color();
DASH_LEFT_COLOR.from_pixel(0x324c6faa);
const DASH_MIDDLE_COLOR = new Clutter.Color();
DASH_MIDDLE_COLOR.from_pixel(0x324c6fbb);
const DASH_RIGHT_COLOR = new Clutter.Color();
DASH_RIGHT_COLOR.from_pixel(0x324c6fcc);
// The results pane has a somewhat transparent blue background with a gradient.
const RESULTS_LEFT_COLOR = new Clutter.Color();
RESULTS_LEFT_COLOR.from_pixel(0x324c6fcc);
const RESULTS_MIDDLE_COLOR = new Clutter.Color();
RESULTS_MIDDLE_COLOR.from_pixel(0x324c6fdd);
const RESULTS_RIGHT_COLOR = new Clutter.Color();
RESULTS_RIGHT_COLOR.from_pixel(0x324c6fee);
const RESULTS_BORDER_COLOR = new Clutter.Color();
RESULTS_BORDER_COLOR.from_pixel(0x213b5dff);
const RESULTS_BORDER_WIDTH = 2;
const SHADOW_COLOR = new Clutter.Color();
SHADOW_COLOR.from_pixel(0x00000033);
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
const SHADOW_WIDTH = 6;
let wideScreen = false; let wideScreen = false;
let displayGridColumnWidth = null; let displayGridColumnWidth = null;
let displayGridRowHeight = null; let displayGridRowHeight = null;
@ -136,31 +158,51 @@ Dash.prototype = {
_init : function() { _init : function() {
let me = this; let me = this;
let asideXFactor = wideScreen ? WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN : WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN;
this._expandedDashColumns = wideScreen ? EXPANDED_DASH_COLUMNS_WIDE_SCREEN : EXPANDED_DASH_COLUMNS_REGULAR_SCREEN; this._expandedDashColumns = wideScreen ? EXPANDED_DASH_COLUMNS_WIDE_SCREEN : EXPANDED_DASH_COLUMNS_REGULAR_SCREEN;
this._width = displayGridColumnWidth; this._width = displayGridColumnWidth;
this._displayWidth = this._width - DASH_PAD;
this._expandedWidth = displayGridColumnWidth * asideXFactor; this._displayWidth = displayGridColumnWidth - DASH_PAD * 2;
this._resultsWidth = displayGridColumnWidth;
// this figures out the additional width we can give to the display in the 'More' mode, let bottomHeight = DASH_PAD;
// assuming that we want to keep the columns the same width in both modes
this._additionalWidth = (this._width / DASH_COLUMNS) *
(this._expandedDashColumns - DASH_COLUMNS);
let bottomHeight = displayGridRowHeight / 2;
let global = Shell.Global.get(); let global = Shell.Global.get();
let previewWidth = this._expandedWidth - this._width - let resultsHeight = global.screen_height - Panel.PANEL_HEIGHT - DASH_PAD - bottomHeight;
this._additionalWidth - DASH_SECTION_SPACING;
let previewHeight = global.screen_height - Panel.PANEL_HEIGHT - DASH_PAD - bottomHeight;
this.actor = new Clutter.Group(); this.actor = new Clutter.Group();
this.actor.height = global.screen_height; this.actor.height = global.screen_height;
let dashPane = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x: 0,
y: Panel.PANEL_HEIGHT + DASH_PAD,
width: this._width + SHADOW_WIDTH,
height: global.screen_height - Panel.PANEL_HEIGHT - DASH_PAD - bottomHeight});
let dashBackground = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
width: this._width,
height: global.screen_height - Panel.PANEL_HEIGHT - DASH_PAD - bottomHeight,
corner_radius: DASH_CORNER_RADIUS,
border: RESULTS_BORDER_WIDTH,
border_color: RESULTS_BORDER_COLOR });
dashPane.append(dashBackground, Big.BoxPackFlags.EXPAND);
let dashLeft = global.create_horizontal_gradient(DASH_LEFT_COLOR,
DASH_MIDDLE_COLOR);
let dashRight = global.create_horizontal_gradient(DASH_MIDDLE_COLOR,
DASH_RIGHT_COLOR);
let dashShadow = global.create_horizontal_gradient(SHADOW_COLOR,
TRANSPARENT_COLOR);
dashShadow.set_width(SHADOW_WIDTH);
dashBackground.append(dashLeft, Big.BoxPackFlags.EXPAND);
dashBackground.append(dashRight, Big.BoxPackFlags.EXPAND);
dashPane.append(dashShadow, Big.BoxPackFlags.NONE);
this.actor.add_actor(dashPane);
this._appsSection = new Big.Box({ x: DASH_PAD, this._appsSection = new Big.Box({ x: DASH_PAD,
y: Panel.PANEL_HEIGHT + DASH_PAD, y: Panel.PANEL_HEIGHT + DASH_PAD,
padding_top: DASH_SECTION_PADDING_TOP, padding_top: DASH_SECTION_PADDING_TOP,
@ -220,18 +262,38 @@ Dash.prototype = {
this._docsDisplayControlBox = new Big.Box({x_align: Big.BoxAlignment.CENTER}); this._docsDisplayControlBox = new Big.Box({x_align: Big.BoxAlignment.CENTER});
this._docsDisplayControlBox.append(this._docDisplay.displayControl, Big.BoxPackFlags.NONE); this._docsDisplayControlBox.append(this._docDisplay.displayControl, Big.BoxPackFlags.NONE);
this._details = new Big.Box({ x: this._width + this._additionalWidth + DASH_SECTION_SPACING, this._resultsPane = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x: this._width,
y: Panel.PANEL_HEIGHT + DASH_PAD, y: Panel.PANEL_HEIGHT + DASH_PAD,
width: previewWidth, width: this._resultsWidth + SHADOW_WIDTH,
height: previewHeight, height: resultsHeight });
corner_radius: DETAILS_CORNER_RADIUS,
border: DETAILS_BORDER_WIDTH, let resultsBackground = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
border_color: DETAILS_BORDER_COLOR, width: this._resultsWidth,
padding: DETAILS_PADDING}); height: resultsHeight,
this._appDisplay.setAvailableDimensionsForItemDetails(previewWidth - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2, corner_radius: DASH_CORNER_RADIUS,
previewHeight - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2); border: RESULTS_BORDER_WIDTH,
this._docDisplay.setAvailableDimensionsForItemDetails(previewWidth - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2, border_color: RESULTS_BORDER_COLOR });
previewHeight - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2);
this._resultsPane.append(resultsBackground, Big.BoxPackFlags.EXPAND);
let resultsLeft = global.create_horizontal_gradient(RESULTS_LEFT_COLOR,
RESULTS_MIDDLE_COLOR);
let resultsRight = global.create_horizontal_gradient(RESULTS_MIDDLE_COLOR,
RESULTS_RIGHT_COLOR);
let resultsShadow = global.create_horizontal_gradient(SHADOW_COLOR,
TRANSPARENT_COLOR);
resultsShadow.set_width(SHADOW_WIDTH);
resultsBackground.append(resultsLeft, Big.BoxPackFlags.EXPAND);
resultsBackground.append(resultsRight, Big.BoxPackFlags.EXPAND);
this._resultsPane.append(resultsShadow, Big.BoxPackFlags.NONE);
this._resultsText = new Clutter.Text({ color: DASH_TEXT_COLOR,
font_name: "Sans 12",
x: DASH_SECTION_SPACING,
y: 0 });
this._resultsPane.add_actor(this._resultsText);
/* Proxy the activated signals */ /* Proxy the activated signals */
this._appDisplay.connect('activated', function(appDisplay) { this._appDisplay.connect('activated', function(appDisplay) {
@ -291,6 +353,12 @@ Dash.prototype = {
hide: function() { hide: function() {
this._appsContent.hide(); this._appsContent.hide();
this._docDisplay.hide(); this._docDisplay.hide();
this.unsetMoreMode();
},
unsetMoreMode: function() {
this._unsetMoreAppsMode();
this._unsetMoreDocsMode();
}, },
// Ensures that one of the displays has the selection if neither owns it after the // Ensures that one of the displays has the selection if neither owns it after the
@ -309,31 +377,66 @@ Dash.prototype = {
} }
}, },
// Updates the applications section display and the 'More...' or 'Less...' control associated with it // Sets the 'More' mode for browsing applications.
// depending on the current mode. This function must only be called once after the 'More' mode has been _setMoreAppsMode: function() {
// changed, which is ensured by _setMoreAppsMode() and _unsetMoreAppsMode() functions. if (this._moreAppsMode)
_updateAppsSection: function() { return;
if (this._moreAppsMode) {
// Subtract one from columns since we are displaying menus this._unsetMoreDocsMode();
this._appDisplay.setExpanded(true, this._displayWidth, this._additionalWidth, this._moreAppsMode = true;
this._itemDisplayHeight + DASH_SECTION_MISC_HEIGHT,
this._expandedDashColumns - 1); this.actor.add_actor(this._resultsPane);
this._moreAppsLink.setText("Less..."); this._moreAppsLink.setText("Less...");
this._appsSection.insert_after(this._appsDisplayControlBox, this._appsContent, Big.BoxPackFlags.NONE);
this.actor.add_actor(this._details); this._resultsText.text = "Application Results";
this._details.append(this._appDisplay.selectedItemDetails, Big.BoxPackFlags.NONE);
} else { this.emit('more-activated');
this._appDisplay.setExpanded(false, this._displayWidth, 0, },
this._appsSectionDefaultHeight - DASH_SECTION_MISC_HEIGHT,
DASH_COLUMNS); // Unsets the 'More' mode for browsing applications.
_unsetMoreAppsMode: function() {
if (!this._moreAppsMode)
return;
this._moreAppsMode = false;
this.actor.remove_actor(this._resultsPane);
this._moreAppsLink.setText("More..."); this._moreAppsLink.setText("More...");
this._appsSection.remove_actor(this._appsDisplayControlBox);
this.actor.remove_actor(this._details); this.emit('less-activated');
this._details.remove_all(); },
}
this._moreAppsLink.actor.show(); // Sets the 'More' mode for browsing documents.
_setMoreDocsMode: function() {
if (this._moreDocsMode)
return;
this._unsetMoreAppsMode();
this._moreDocsMode = true;
this.actor.add_actor(this._resultsPane);
this._moreDocsLink.setText("Less...");
this._resultsText.text = "Document Results";
this.emit('more-activated');
},
// Unsets the 'More' mode for browsing documents.
_unsetMoreDocsMode: function() {
if (!this._moreDocsMode)
return;
this._moreDocsMode = false;
this.actor.remove_actor(this._resultsPane);
this._moreDocsLink.setText("More...");
this.emit('less-activated');
} }
}; };
Signals.addSignalMethods(Dash.prototype); Signals.addSignalMethods(Dash.prototype);
function Overlay() { function Overlay() {
@ -376,6 +479,13 @@ Overlay.prototype = {
background.y = -global.screen_height * (4 * BACKGROUND_SCALE - 3) / 6; background.y = -global.screen_height * (4 * BACKGROUND_SCALE - 3) / 6;
this._group.add_actor(background); this._group.add_actor(background);
this._transparentBackground = new Clutter.Rectangle({ color: TRANSPARENT_COLOR,
width: global.screen_width,
height: global.screen_height - Panel.PANEL_HEIGHT,
y: Panel.PANEL_HEIGHT,
reactive: true });
this._group.add_actor(this._transparentBackground);
// Draw a semitransparent rectangle over the background for readability. // Draw a semitransparent rectangle over the background for readability.
let backOver = new Clutter.Rectangle({ color: ROOT_OVERLAY_COLOR, let backOver = new Clutter.Rectangle({ color: ROOT_OVERLAY_COLOR,
width: global.screen_width, width: global.screen_width,
@ -390,6 +500,7 @@ Overlay.prototype = {
this._dash = new Dash(); this._dash = new Dash();
this._group.add_actor(this._dash.actor); this._group.add_actor(this._dash.actor);
this._workspaces = null; this._workspaces = null;
this._buttonEventHandlerId = null;
this._dash.connect('activated', function(dash) { this._dash.connect('activated', function(dash) {
// TODO - have some sort of animation/effect while // TODO - have some sort of animation/effect while
// transitioning to the new app. We definitely need // transitioning to the new app. We definitely need
@ -398,25 +509,34 @@ Overlay.prototype = {
}); });
this._dash.connect('more-activated', function(dash) { this._dash.connect('more-activated', function(dash) {
if (me._workspaces != null) { if (me._workspaces != null) {
let asideXFactor = wideScreen ? WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN : WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN; me._transparentBackground.raise_top();
me._dash.actor.raise_top();
let workspacesX = displayGridColumnWidth * asideXFactor + WORKSPACE_GRID_PADDING; me._buttonEventHandlerId = me._transparentBackground.connect('button-release-event', function(background) {
me._workspaces.addButton.hide(); me._dash.unsetMoreMode();
me._workspaces.updatePosition(workspacesX, null); return true;
});
} }
}); });
this._dash.connect('less-activated', function(dash) { this._dash.connect('less-activated', function(dash) {
if (me._workspaces != null) { if (me._workspaces != null) {
let workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING; me._transparentBackground.lower_bottom();
me._workspaces.addButton.show(); me._transparentBackground.disconnect(me._buttonEventHandlerId);
me._workspaces.updatePosition(workspacesX, null);
} }
}); });
}, },
//// Draggable target interface //// //// Draggable target interface ////
// Unsets the expanded display mode if a GenericDisplayItem is being
// dragged over the overlay, i.e. as soon as it starts being dragged.
// This closes the additional panes and allows the user to place
// the item on any workspace.
handleDragOver : function(source, actor, x, y, time) { handleDragOver : function(source, actor, x, y, time) {
if (source instanceof GenericDisplay.GenericDisplayItem) {
this._dash.unsetMoreMode();
return true;
}
return false; return false;
}, },

View File

@ -933,6 +933,53 @@ shell_global_create_vertical_gradient (ClutterColor *top,
return texture; return texture;
} }
/**
* shell_global_create_horizontal_gradient:
* @left: the color at the top
* @right: the color at the bottom
*
* Creates a vertical gradient actor.
*
* Return value: (transfer none): a #ClutterCairoTexture actor with the
* gradient. The texture actor is floating, hence (transfer none).
*/
ClutterCairoTexture *
shell_global_create_horizontal_gradient (ClutterColor *left,
ClutterColor *right)
{
ClutterCairoTexture *texture;
cairo_t *cr;
cairo_pattern_t *pattern;
/* Draw the gradient on an 8x8 pixel texture. Because the gradient is drawn
* from the uppermost to the lowermost row, after stretching 1/16 of the
* texture height has the top color and 1/16 has the bottom color. The 8
* pixel width is chosen for reasons related to graphics hardware internals.
*/
texture = CLUTTER_CAIRO_TEXTURE (clutter_cairo_texture_new (8, 8));
cr = clutter_cairo_texture_create (texture);
pattern = cairo_pattern_create_linear (0, 0, 8, 0);
cairo_pattern_add_color_stop_rgba (pattern, 0,
left->red / 255.,
left->green / 255.,
left->blue / 255.,
left->alpha / 255.);
cairo_pattern_add_color_stop_rgba (pattern, 1,
right->red / 255.,
right->green / 255.,
right->blue / 255.,
right->alpha / 255.);
cairo_set_source (cr, pattern);
cairo_paint (cr);
cairo_pattern_destroy (pattern);
cairo_destroy (cr);
return texture;
}
/* /*
* Updates the global->root_pixmap actor with the root window's pixmap or fails * Updates the global->root_pixmap actor with the root window's pixmap or fails
* with a warning. * with a warning.

View File

@ -76,6 +76,9 @@ void shell_global_reexec_self (ShellGlobal *global);
ClutterCairoTexture *shell_global_create_vertical_gradient (ClutterColor *top, ClutterCairoTexture *shell_global_create_vertical_gradient (ClutterColor *top,
ClutterColor *bottom); ClutterColor *bottom);
ClutterCairoTexture *shell_global_create_horizontal_gradient (ClutterColor *left,
ClutterColor *right);
ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global); ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global);
void shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture, void shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture,