[gnome-shell] viewSelector: Merge SearchTab into the ViewSelector



commit c267a7a7f9c7c340e60c63aad1bf42923f19f292
Author: Joost Verdoorn <jpverdoorn gmail com>
Date:   Fri Jun 22 00:52:56 2012 +0200

    viewSelector: Merge SearchTab into the ViewSelector
    
    Tabs used to provide an abstraction for a page and the control used to
    activate it. As the latter has now been replaced with external controls
    handled directly in the viewSelector, the abstraction itself doesn't make
    much sense anymore. In preparation of replacing it, move the search
    handling provided by the SearchTab directly in the viewSelector.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=682109

 js/ui/viewSelector.js |  412 +++++++++++++++++++++++--------------------------
 1 files changed, 190 insertions(+), 222 deletions(-)
---
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index 38326a5..0d382a2 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -98,11 +98,33 @@ const ViewTab = new Lang.Class({
 });
 
 
-const SearchTab = new Lang.Class({
-    Name: 'SearchTab',
-    Extends: BaseTab,
+const ViewSelector = new Lang.Class({
+    Name: 'ViewSelector',
+
+    _init : function(searchEntry, showAppsButton) {
+        this.actor = new St.BoxLayout({ name: 'viewSelector',
+                                        vertical: true });
+
+        this._showAppsButton = showAppsButton;
+        this._showAppsButton.connect('notify::checked', Lang.bind(this,
+            function() {
+                if (this._showAppsButton.checked)
+                    this._switchTab(this._appsTab);
+                else
+                    this._switchTab(this._windowsTab);
+            }));
+
+        // The page area holds the tab pages. Every page is given the
+        // area's full allocation, so that the pages would appear on top
+        // of each other if the inactive ones weren't hidden.
+        this._pageArea = new Shell.Stack();
+        this.actor.add(this._pageArea, { x_fill: true,
+                                         y_fill: true,
+                                         expand: true });
+
+        this._tabs = [];
+        this._activeTab = null;
 
-    _init: function(searchEntry) {
         this.active = false;
         this._searchPending = false;
         this._searchTimeoutId = 0;
@@ -111,8 +133,18 @@ const SearchTab = new Lang.Class({
 
         this._entry = searchEntry;
         ShellEntry.addContextMenu(this._entry);
+
         this._text = this._entry.clutter_text;
+        this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
         this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
+        this._text.connect('key-focus-in', Lang.bind(this, function() {
+            this._searchResults.highlightDefault(true);
+        }));
+        this._text.connect('key-focus-out', Lang.bind(this, function() {
+            this._searchResults.highlightDefault(false);
+        }));
+        this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
+        global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
 
         this._inactiveIcon = new St.Icon({ style_class: 'search-entry-icon',
                                            icon_name: 'edit-find',
@@ -123,38 +155,29 @@ const SearchTab = new Lang.Class({
         this._entry.set_secondary_icon(this._inactiveIcon);
 
         this._iconClickedId = 0;
+        this._capturedEventId = 0;
 
-        this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
-        this.parent(new St.Bin() /* Dummy */, this._searchResults.actor, _("Search"), 'edit-find');
-
-        this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
-        this._text.connect('key-press-event', Lang.bind(this, function (o, e) {
-            // We can't connect to 'activate' here because search providers
-            // might want to do something with the modifiers in activateDefault.
-            let symbol = e.get_key_symbol();
-            if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
-                if (this._searchTimeoutId > 0) {
-                    Mainloop.source_remove(this._searchTimeoutId);
-                    this._doSearch();
-                }
-                this._searchResults.activateDefault();
-                return true;
-            }
-            return false;
-        }));
+        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
+        this._windowsTab = new ViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
+        this._addViewTab(this._windowsTab);
 
-        this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
+        let appView = new AppDisplay.AllAppDisplay();
+        this._appsTab = new ViewTab('applications', _("Applications"), appView.actor, 'system-run');
+        this._addViewTab(this._appsTab);
 
-        global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
+        this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
+        this._searchTab = new BaseTab(new St.Bin(), this._searchResults.actor, _("Search"), 'edit-find');
+        this._addTab(this._searchTab);
 
-        this._capturedEventId = 0;
+        // Default search providers
+        // Wanda comes obviously first
+        this.addSearchProvider(new Wanda.WandaSearchProvider());
+        this.addSearchProvider(new AppDisplay.AppSearchProvider());
+        this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
+        this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
 
-        this._text.connect('key-focus-in', Lang.bind(this, function() {
-            this._searchResults.highlightDefault(true);
-        }));
-        this._text.connect('key-focus-out', Lang.bind(this, function() {
-            this._searchResults.highlightDefault(false);
-        }));
+        // Load remote search providers provided by applications
+        RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
 
         // Since the entry isn't inside the results container we install this
         // dummy widget as the last results container child so that we can
@@ -172,10 +195,130 @@ const SearchTab = new Lang.Class({
         this._searchResults.actor.add_actor(this._focusTrap);
 
         global.focus_manager.add_group(this._searchResults.actor);
+
+        Main.overview.connect('item-drag-begin',
+                              Lang.bind(this, this._resetShowAppsButton));
+
+        this._stageKeyPressId = 0;
+        Main.overview.connect('showing', Lang.bind(this,
+            function () {
+                this._resetShowAppsButton();
+                this._stageKeyPressId = global.stage.connect('key-press-event',
+                                                             Lang.bind(this, this._onStageKeyPress));
+            }));
+        Main.overview.connect('hiding', Lang.bind(this,
+            function () {
+                this._resetShowAppsButton();
+                if (this._stageKeyPressId != 0) {
+                    global.stage.disconnect(this._stageKeyPressId);
+                    this._stageKeyPressId = 0;
+                }
+            }));
+
+        // Public constraints which may be used to tie actors' height or
+        // vertical position to the current tab's content; as the content's
+        // height and position depend on the view selector's style properties
+        // (e.g. font size, padding, spacing, ...) it would be extremely hard
+        // and ugly to get these from the outside. While it would be possible
+        // to use position and height properties directly, outside code would
+        // need to ensure that the content is properly allocated before
+        // accessing the properties.
+        this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
+                                                            coordinate: Clutter.BindCoordinate.HEIGHT });
+    },
+
+    show: function() {
+        this._workspacesDisplay.show();
+
+        if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
+            Main.overview.fadeOutDesktop();
+    },
+
+    zoomFromOverview: function() {
+        this._workspacesDisplay.zoomFromOverview();
+
+        if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
+            Main.overview.fadeInDesktop();
     },
 
     hide: function() {
-        this.parent();
+        this._workspacesDisplay.hide();
+    },
+
+    _addTab: function(tab) {
+        tab.page.hide();
+        this._pageArea.add_actor(tab.page);
+        tab.connect('activated', Lang.bind(this, function(tab) {
+            this._switchTab(tab);
+        }));
+    },
+
+    _addViewTab: function(viewTab) {
+        this._tabs.push(viewTab);
+        this._addTab(viewTab);
+    },
+
+    _switchTab: function(tab) {
+        let firstSwitch = this._activeTab == null;
+
+        if (this._activeTab && this._activeTab.visible) {
+            if (this._activeTab == tab)
+                return;
+            this._activeTab.hide();
+        }
+
+        if (tab != this._searchTab) {
+            this._activeTab = tab;
+            if (this._searchTab.visible) {
+                this._searchTab.hide();
+            }
+        }
+
+        // Only fade when switching between tabs,
+        // not when setting the initially selected one.
+        if (!tab.visible)
+            tab.show(!firstSwitch);
+    },
+
+    switchTab: function(id) {
+        for (let i = 0; i < this._tabs.length; i++)
+            if (this._tabs[i].id == id) {
+                this._switchTab(this._tabs[i]);
+                break;
+            }
+    },
+
+    _resetShowAppsButton: function() {
+        this._showAppsButton.checked = false;
+    },
+
+    _onStageKeyPress: function(actor, event) {
+        let modifiers = event.get_state();
+        let symbol = event.get_key_symbol();
+
+        if (symbol == Clutter.Escape) {
+            if (this.active)
+                this.reset();
+            else
+                Main.overview.hide();
+            return true;
+        } else if (Clutter.keysym_to_unicode(symbol) ||
+                   (symbol == Clutter.BackSpace && this.active)) {
+            this.startSearch(event);
+        } else if (!this.active) {
+            if (symbol == Clutter.Tab) {
+                this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
+                return true;
+            } else if (symbol == Clutter.ISO_Left_Tab) {
+                this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
+                return true;
+            }
+        }
+        return false;
+    },
+
+    _searchCancelled: function() {
+        this._switchTab(this._activeTab);
 
         // Leave the entry focused when it doesn't have any text;
         // when replacing a selected search term, Clutter emits
@@ -224,16 +367,6 @@ const SearchTab = new Lang.Class({
         }
     },
 
-    addSearchProvider: function(provider) {
-        this._searchSystem.registerProvider(provider);
-        this._searchResults.createProviderMeta(provider);
-    },
-
-    removeSearchProvider: function(provider) {
-        this._searchSystem.unregisterProvider(provider);
-        this._searchResults.destroyProviderMeta(provider);
-    },
-
     startSearch: function(event) {
         global.stage.set_key_focus(this._text);
         this._text.event(event, false);
@@ -260,14 +393,14 @@ const SearchTab = new Lang.Class({
                         this.reset();
                     }));
             }
-            this._activate();
+            this._switchTab(this._searchTab);
         } else {
             if (this._iconClickedId > 0)
                 this._entry.disconnect(this._iconClickedId);
             this._iconClickedId = 0;
 
             this._entry.set_secondary_icon(this._inactiveIcon);
-            this.emit('search-cancelled');
+            this._searchCancelled();
         }
         if (!this.active) {
             if (this._searchTimeoutId > 0) {
@@ -288,6 +421,15 @@ const SearchTab = new Lang.Class({
                 this.reset();
                 return true;
             }
+        } else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
+            // We can't connect to 'activate' here because search providers
+            // might want to do something with the modifiers in activateDefault.
+            if (this._searchTimeoutId > 0) {
+                Mainloop.source_remove(this._searchTimeoutId);
+                this._doSearch();
+            }
+            this._searchResults.activateDefault();
+            return true;
         } else if (this.active) {
             let arrowNext, nextDirection;
             if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
@@ -338,190 +480,16 @@ const SearchTab = new Lang.Class({
         this._searchResults.doSearch(text);
 
         return false;
-    }
-});
-
-
-const ViewSelector = new Lang.Class({
-    Name: 'ViewSelector',
-
-    _init : function(searchEntry, showAppsButton) {
-        this.actor = new St.BoxLayout({ name: 'viewSelector',
-                                        vertical: true });
-
-        this._showAppsButton = showAppsButton;
-        this._showAppsButton.connect('notify::checked', Lang.bind(this,
-            function() {
-                if (this._showAppsButton.checked)
-                    this._switchTab(this._appsTab);
-                else
-                    this._switchTab(this._windowsTab);
-            }));
-
-        // The page area holds the tab pages. Every page is given the
-        // area's full allocation, so that the pages would appear on top
-        // of each other if the inactive ones weren't hidden.
-        this._pageArea = new Shell.Stack();
-        this.actor.add(this._pageArea, { x_fill: true,
-                                         y_fill: true,
-                                         expand: true });
-
-        this._tabs = [];
-        this._activeTab = null;
-
-        this._searchTab = new SearchTab(searchEntry);
-        this._addTab(this._searchTab);
-
-        this._searchTab.connect('search-cancelled', Lang.bind(this,
-            function() {
-                this._switchTab(this._activeTab);
-            }));
-
-        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
-        this._windowsTab = new ViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
-        this._addViewTab(this._windowsTab);
-
-        let appView = new AppDisplay.AllAppDisplay();
-        this._appsTab = new ViewTab('applications', _("Applications"), appView.actor, 'system-run');
-        this._addViewTab(this._appsTab);
-
-        // Default search providers
-        // Wanda comes obviously first
-        this.addSearchProvider(new Wanda.WandaSearchProvider());
-        this.addSearchProvider(new AppDisplay.AppSearchProvider());
-        this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
-        this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
-        
-        // Load remote search providers provided by applications
-        RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
-
-        Main.overview.connect('item-drag-begin',
-                              Lang.bind(this, this._resetShowAppsButton));
-
-        this._stageKeyPressId = 0;
-        Main.overview.connect('showing', Lang.bind(this,
-            function () {
-                this._resetShowAppsButton();
-                this._stageKeyPressId = global.stage.connect('key-press-event',
-                                                             Lang.bind(this, this._onStageKeyPress));
-            }));
-        Main.overview.connect('hiding', Lang.bind(this,
-            function () {
-                this._resetShowAppsButton();
-                if (this._stageKeyPressId != 0) {
-                    global.stage.disconnect(this._stageKeyPressId);
-                    this._stageKeyPressId = 0;
-                }
-            }));
-
-        // Public constraints which may be used to tie actors' height or
-        // vertical position to the current tab's content; as the content's
-        // height and position depend on the view selector's style properties
-        // (e.g. font size, padding, spacing, ...) it would be extremely hard
-        // and ugly to get these from the outside. While it would be possible
-        // to use position and height properties directly, outside code would
-        // need to ensure that the content is properly allocated before
-        // accessing the properties.
-        this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
-                                                            coordinate: Clutter.BindCoordinate.HEIGHT });
-    },
-
-    show: function() {
-        this._workspacesDisplay.show();
-
-        if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
-            Main.overview.fadeOutDesktop();
-    },
-
-    zoomFromOverview: function() {
-        this._workspacesDisplay.zoomFromOverview();
-
-        if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
-            Main.overview.fadeInDesktop();
-    },
-
-    hide: function() {
-        this._workspacesDisplay.hide();
-    },
-
-    _addTab: function(tab) {
-        tab.page.hide();
-        this._pageArea.add_actor(tab.page);
-        tab.connect('activated', Lang.bind(this, function(tab) {
-            this._switchTab(tab);
-        }));
-    },
-
-    _addViewTab: function(viewTab) {
-        this._tabs.push(viewTab);
-        this._addTab(viewTab);
-    },
-
-    _switchTab: function(tab) {
-        let firstSwitch = this._activeTab == null;
-
-        if (this._activeTab && this._activeTab.visible) {
-            if (this._activeTab == tab)
-                return;
-            this._activeTab.hide();
-        }
-
-        if (tab != this._searchTab) {
-            this._activeTab = tab;
-            if (this._searchTab.visible) {
-                this._searchTab.hide();
-            }
-        }
-
-        // Only fade when switching between tabs,
-        // not when setting the initially selected one.
-        if (!tab.visible)
-            tab.show(!firstSwitch);
-    },
-
-    switchTab: function(id) {
-        for (let i = 0; i < this._tabs.length; i++)
-            if (this._tabs[i].id == id) {
-                this._switchTab(this._tabs[i]);
-                break;
-            }
-    },
-
-    _resetShowAppsButton: function() {
-        this._showAppsButton.checked = false;
-    },
-
-    _onStageKeyPress: function(actor, event) {
-        let modifiers = event.get_state();
-        let symbol = event.get_key_symbol();
-
-        if (symbol == Clutter.Escape) {
-            if (this._searchTab.active)
-                this._searchTab.reset();
-            else
-                Main.overview.hide();
-            return true;
-        } else if (Clutter.keysym_to_unicode(symbol) ||
-                   (symbol == Clutter.BackSpace && this._searchTab.active)) {
-            this._searchTab.startSearch(event);
-        } else if (!this._searchTab.active) {
-            if (symbol == Clutter.Tab) {
-                this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
-                return true;
-            } else if (symbol == Clutter.ISO_Left_Tab) {
-                this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
-                return true;
-            }
-        }
-        return false;
     },
 
     addSearchProvider: function(provider) {
-        this._searchTab.addSearchProvider(provider);
+        this._searchSystem.registerProvider(provider);
+        this._searchResults.createProviderMeta(provider);
     },
 
     removeSearchProvider: function(provider) {
-        this._searchTab.removeSearchProvider(provider);
+        this._searchSystem.unregisterProvider(provider);
+        this._searchResults.destroyProviderMeta(provider);
     }
 });
 Signals.addSignalMethods(ViewSelector.prototype);



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