[gnome-shell/overlay-design02] Add a results pane in the overlay



commit 98530afd8773fae1cb8b20cd631261b7b426743b
Author: Marina Zhurakhinskaya <marinaz redhat com>
Date:   Mon Jun 8 19:04:52 2009 -0400

    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]
---
 js/ui/overlay.js   |  250 ++++++++++++++++++++++++++++++++++++++--------------
 src/shell-global.c |   47 ++++++++++
 src/shell-global.h |    3 +
 3 files changed, 235 insertions(+), 65 deletions(-)

diff --git a/js/ui/overlay.js b/js/ui/overlay.js
index 90ca901..4c73ec7 100644
--- a/js/ui/overlay.js
+++ b/js/ui/overlay.js
@@ -33,17 +33,13 @@ const DASH_MIN_WIDTH = 250;
 const DASH_SECTION_PADDING_TOP = 6;
 const DASH_SECTION_SPACING = 6;
 const DASH_COLUMNS = 1;
-const DETAILS_CORNER_RADIUS = 5;
-const DETAILS_BORDER_WIDTH = 1;
-const DETAILS_PADDING = 6;
+const DASH_CORNER_RADIUS = 5;
 // 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_SEARCH_BG_COLOR = new Clutter.Color();
 DASH_SEARCH_BG_COLOR.from_pixel(0xffffffff);
 const DASH_TEXT_COLOR = new Clutter.Color();
 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
 const ANIMATION_TIME = 0.25;
@@ -73,12 +69,10 @@ const WORKSPACE_GRID_PADDING = 12;
 
 const COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN = 3;
 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 COLUMNS_FOR_WORKSPACES_WIDE_SCREEN = 4;
 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;
 
 // A multi-state; PENDING is used during animations
@@ -86,6 +80,34 @@ const STATE_ACTIVE = true;
 const STATE_PENDING_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 displayGridColumnWidth = null;
 let displayGridRowHeight = null;
@@ -136,31 +158,51 @@ Dash.prototype = {
     _init : function() {
         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._width = displayGridColumnWidth;
-        this._displayWidth = this._width - DASH_PAD;
-
-        this._expandedWidth = displayGridColumnWidth * asideXFactor;
 
-        // this figures out the additional width we can give to the display in the 'More' mode,
-        // assuming that we want to keep the columns the same width in both modes
-        this._additionalWidth = (this._width / DASH_COLUMNS) *
-                                (this._expandedDashColumns - DASH_COLUMNS);
+        this._displayWidth = displayGridColumnWidth - DASH_PAD * 2;
+        this._resultsWidth = displayGridColumnWidth;  
 
-        let bottomHeight = displayGridRowHeight / 2;
+        let bottomHeight = DASH_PAD;
 
         let global = Shell.Global.get();
 
-        let previewWidth = this._expandedWidth - this._width -
-                           this._additionalWidth - DASH_SECTION_SPACING;
-
-        let previewHeight = global.screen_height - Panel.PANEL_HEIGHT - DASH_PAD - bottomHeight;
+        let resultsHeight = global.screen_height - Panel.PANEL_HEIGHT - DASH_PAD - bottomHeight;
 
         this.actor = new Clutter.Group();
         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,
                                           y: Panel.PANEL_HEIGHT + DASH_PAD,
                                           padding_top: DASH_SECTION_PADDING_TOP,
@@ -220,19 +262,39 @@ Dash.prototype = {
         this._docsDisplayControlBox = new Big.Box({x_align: Big.BoxAlignment.CENTER});
         this._docsDisplayControlBox.append(this._docDisplay.displayControl, Big.BoxPackFlags.NONE);
 
-        this._details = new Big.Box({ x: this._width + this._additionalWidth + DASH_SECTION_SPACING,
-                                      y: Panel.PANEL_HEIGHT + DASH_PAD,
-                                      width: previewWidth,
-                                      height: previewHeight,
-                                      corner_radius: DETAILS_CORNER_RADIUS,
-                                      border: DETAILS_BORDER_WIDTH,
-                                      border_color: DETAILS_BORDER_COLOR,
-                                      padding: DETAILS_PADDING});
-        this._appDisplay.setAvailableDimensionsForItemDetails(previewWidth - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2,
-                                                              previewHeight - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2);
-        this._docDisplay.setAvailableDimensionsForItemDetails(previewWidth - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2,
-                                                              previewHeight - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2);
- 
+        this._resultsPane = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
+                                          x: this._width,
+                                          y: Panel.PANEL_HEIGHT + DASH_PAD,
+                                          width: this._resultsWidth + SHADOW_WIDTH,
+                                          height: resultsHeight });
+
+        let resultsBackground = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
+                                              width: this._resultsWidth,
+                                              height: resultsHeight,
+                                              corner_radius: DASH_CORNER_RADIUS,
+                                              border: RESULTS_BORDER_WIDTH,
+                                              border_color: RESULTS_BORDER_COLOR });
+
+        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 */
         this._appDisplay.connect('activated', function(appDisplay) {
             me.emit('activated');
@@ -291,6 +353,12 @@ Dash.prototype = {
     hide: function() {
         this._appsContent.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
@@ -308,32 +376,67 @@ Dash.prototype = {
             }
         }
     },
+
+    // Sets the 'More' mode for browsing applications.
+    _setMoreAppsMode: function() {
+        if (this._moreAppsMode)
+            return;
+
+        this._unsetMoreDocsMode();
+        this._moreAppsMode = true;
+
+        this.actor.add_actor(this._resultsPane);
+
+        this._moreAppsLink.setText("Less...");
+
+        this._resultsText.text = "Application Results";
  
-    // Updates the applications section display and the 'More...' or 'Less...' control associated with it
-    // depending on the current mode. This function must only be called once after the 'More' mode has been
-    // changed, which is ensured by _setMoreAppsMode() and _unsetMoreAppsMode() functions. 
-    _updateAppsSection: function() {
-        if (this._moreAppsMode) {
-            // Subtract one from columns since we are displaying menus
-            this._appDisplay.setExpanded(true, this._displayWidth, this._additionalWidth,
-                                         this._itemDisplayHeight + DASH_SECTION_MISC_HEIGHT,
-                                         this._expandedDashColumns - 1);
-            this._moreAppsLink.setText("Less...");
-            this._appsSection.insert_after(this._appsDisplayControlBox, this._appsContent, Big.BoxPackFlags.NONE);
-            this.actor.add_actor(this._details);
-            this._details.append(this._appDisplay.selectedItemDetails, Big.BoxPackFlags.NONE);
-        } else {
-            this._appDisplay.setExpanded(false, this._displayWidth, 0,
-                                         this._appsSectionDefaultHeight - DASH_SECTION_MISC_HEIGHT,
-                                         DASH_COLUMNS);
-            this._moreAppsLink.setText("More...");
-            this._appsSection.remove_actor(this._appsDisplayControlBox);
-            this.actor.remove_actor(this._details);
-            this._details.remove_all();
-        }
-        this._moreAppsLink.actor.show();
-    }
+        this.emit('more-activated');
+    },
+
+    // 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.emit('less-activated');
+    },   
+ 
+    // 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);
 
 function Overlay() {
@@ -376,6 +479,13 @@ Overlay.prototype = {
         background.y = -global.screen_height * (4 * BACKGROUND_SCALE - 3) / 6;
         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.
         let backOver = new Clutter.Rectangle({ color: ROOT_OVERLAY_COLOR,
                                                width: global.screen_width,
@@ -390,6 +500,7 @@ Overlay.prototype = {
         this._dash = new Dash();
         this._group.add_actor(this._dash.actor);
         this._workspaces = null;
+        this._buttonEventHandlerId = null;
         this._dash.connect('activated', function(dash) {
             // TODO - have some sort of animation/effect while
             // transitioning to the new app.  We definitely need
@@ -398,25 +509,34 @@ Overlay.prototype = {
         });
         this._dash.connect('more-activated', function(dash) {
             if (me._workspaces != null) {
-                let asideXFactor = wideScreen ? WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN : WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN;  
-        
-                let workspacesX = displayGridColumnWidth * asideXFactor + WORKSPACE_GRID_PADDING;
-                me._workspaces.addButton.hide();
-                me._workspaces.updatePosition(workspacesX, null);
+                me._transparentBackground.raise_top();
+                me._dash.actor.raise_top();
+                me._buttonEventHandlerId = me._transparentBackground.connect('button-release-event', function(background) {
+                    me._dash.unsetMoreMode();
+                    return true;
+                }); 
             }    
         });
         this._dash.connect('less-activated', function(dash) {
             if (me._workspaces != null) {
-                let workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
-                me._workspaces.addButton.show();
-                me._workspaces.updatePosition(workspacesX, null);
+                me._transparentBackground.lower_bottom();  
+                me._transparentBackground.disconnect(me._buttonEventHandlerId);  
             }
         });
     },
 
     //// 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) {
+        if (source instanceof GenericDisplay.GenericDisplayItem) {
+            this._dash.unsetMoreMode();
+            return true;
+        }
+  
         return false;
     },
 
diff --git a/src/shell-global.c b/src/shell-global.c
index f3a4185..1dffc29 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -921,6 +921,53 @@ shell_global_create_vertical_gradient (ClutterColor *top,
   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
  * with a warning.
diff --git a/src/shell-global.h b/src/shell-global.h
index 0d43169..a05a729 100644
--- a/src/shell-global.h
+++ b/src/shell-global.h
@@ -76,6 +76,9 @@ void shell_global_reexec_self (ShellGlobal *global);
 ClutterCairoTexture *shell_global_create_vertical_gradient (ClutterColor *top,
 							    ClutterColor *bottom);
 
+ClutterCairoTexture *shell_global_create_horizontal_gradient (ClutterColor *left,
+							      ClutterColor *right);
+
 ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global);
 
 void shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]