Skip to content

Commit

Permalink
Add sorter bar for user scripts addon view.
Browse files Browse the repository at this point in the history
Applies to Firefox 4 only, styled after the bar as it existed pre-beta
11.

Fixes greasemonkey#1293
  • Loading branch information
arantius committed Mar 12, 2011
1 parent 5a3fc10 commit 1e83648
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 61 deletions.
102 changes: 43 additions & 59 deletions content/addons4-overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,11 @@ function init() {
'popupshowing', onContextPopupShowing, false);

window.addEventListener('ViewChanged', onViewChanged, false);
onViewChanged(); // initialize on load as well as when it changes later

var stringBundleService = Components
.classes['@mozilla.org/intl/stringbundle;1']
.getService(Ci.nsIStringBundleService);
var stringBundle = stringBundleService
.createBundle('chrome://greasemonkey/locale/gm-addons.properties');

// Inject this content into an XBL binding (where it can't be overlayed).
sortExecuteOrderButton = document.createElement('button');
sortExecuteOrderButton.setAttribute('checkState', '0');
sortExecuteOrderButton.setAttribute('class', 'sorter');
sortExecuteOrderButton.setAttribute(
'label', stringBundle.GetStringFromName('executionorder'));
sortExecuteOrderButton.setAttribute(
'tooltiptext', stringBundle.GetStringFromName('executionorder.tooltip'));
sortExecuteOrderButton.collapsed = true;
sortersContainer = document.getElementById('list-sorters');
sortersContainer.appendChild(sortExecuteOrderButton);
sortersContainer.addEventListener('click', onSortersClicked, true);
document.getElementById('greasemonkey-sort-bar').addEventListener(
'click', onSortersClicked, false);
applySort();
};

function onContextPopupShowing(aEvent) {
Expand All @@ -96,56 +82,54 @@ function onContextPopupShowing(aEvent) {
}
};

function onExecuteSortCommand(aEvent) {
// Uncheck all sorters.
var sorters = document.getAnonymousNodes(sortersContainer);
for (var i=0, el=null; el=sorters[i]; i++) {
el.setAttribute('checkState', '0');
function onSortersClicked(aEvent) {
if ('button' != aEvent.target.tagName) return;
var button = aEvent.target;

var checkState = button.getAttribute('checkState');

// Remove checkState from all buttons.
var buttons = document.getElementById('greasemonkey-sort-bar')
.getElementsByTagName('button');
for (var i = 0, el = null; el = buttons[i]; i++) {
el.removeAttribute('checkState');
}
// Check our sorter.
var curState = aEvent.target.getAttribute('checkState');
aEvent.target.setAttribute('checkState', (curState == '1') ? '2' : '1');
// Actually sort the elements.
sortScriptsByExecution();
};

function onSortersClicked(aEvent) {
if (aEvent.target == sortExecuteOrderButton) {
onExecuteSortCommand(aEvent);
// Toggle state of this button.
if ('2' == checkState) {
button.setAttribute('checkState', '1');
} else {
// When a sorter other than ours is clicked, uncheck ours.
sortExecuteOrderButton.setAttribute('checkState', 0);
button.setAttribute('checkState', '2');
}

applySort();
};

function onViewChanged(aEvent) {
// If we _were_ visible (execute sorter is not collapsed) ...
if (!sortExecuteOrderButton.collapsed
// And execute sorter is selected ...
&& (1 == sortExecuteOrderButton.getAttribute('checkState'))
) {
// Deselect us.
sortExecuteOrderButton.setAttribute('checkState', 0);
// Select name.
var sorters = document.getAnonymousNodes(sortersContainer);
sorters[0].setAttribute('checkState', 1);
// Sort by name.
gViewController.currentViewObj.onSortChanged('name', true);
function applySort() {
// Find checked button.
var buttons = document.getElementById('greasemonkey-sort-bar')
.getElementsByTagName('button');
for (var i = 0, button = null; button = buttons[i]; i++) {
if (button.hasAttribute('checkState')) break;
}
// Hide the execute order sorter, when the view is not ours.
sortExecuteOrderButton.collapsed =
'addons://list/user-script' != gViewController.currentViewId;
};

function sortScriptsByExecution() {
var sortService = Cc["@mozilla.org/xul/xul-sort-service;1"].
getService(Ci.nsIXULSortService);
var ascending = '1' != button.getAttribute('checkState');
var sortBy=button.getAttribute('sortBy').split(',');

var chkState = sortExecuteOrderButton.getAttribute('checkState');
if ("1" != chkState && "2" != chkState) return;
var list = document.getElementById('addon-list');
var elements = Array.slice(list.childNodes, 0);
sortElements(elements, sortBy, ascending);
while (list.listChild) list.removeChild(list.lastChild);
elements.forEach(function(el) { list.appendChild(el); });
};

sortService.sort(gListView._listBox, 'executionIndex',
("1" == chkState) ? "ascending" : "descending");
function onViewChanged(aEvent) {
if ('addons://list/user-script' == gViewController.currentViewId) {
document.documentElement.className += ' greasemonkey';
} else {
document.documentElement.className = document.documentElement.className
.replace(/ greasemonkey/g, '');
}
};

function reorderScriptExecution(aAddon, moveBy) {
Expand All @@ -156,7 +140,7 @@ function reorderScriptExecution(aAddon, moveBy) {
setRichlistitemExecutionIndex(addon);
}
// Re-sort the list, with these fixed attributes.
sortScriptsByExecution();
applySort();
// Ensure the selected element is still visible.
var richlistbox = document.getElementById('addon-list');
richlistbox.ensureElementIsVisible(richlistbox.currentItem);
Expand Down
15 changes: 15 additions & 0 deletions content/addons4-overlay.xul
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0"?>

<?xml-stylesheet href="chrome://greasemonkey/skin/addons4.css" type="text/css"?>
<?xml-stylesheet href="chrome://greasemonkey/content/third-party/addons4.css" type="text/css"?>

<!DOCTYPE overlay [
<!ENTITY % greasemonkeyDTD SYSTEM "chrome://greasemonkey/locale/greasemonkey.dtd">
Expand Down Expand Up @@ -59,4 +60,18 @@
/>
</menupopup>

<vbox id="list-view">
<hbox id="greasemonkey-sort-bar" class="view-header"
pack="end" insertbefore="addon-list"
>
<button label="&Sort.Status;" tooltiptext="&Sort.ByStatus;"
class="sorter" sortBy="uiState,name"
checkState="2"/>
<button label="&Sort.Name;" tooltiptext="&Sort.ByName;"
class="sorter" sortBy="name"/>
<button label="&Sort.Execution;" tooltiptext="&Sort.ByExecution;"
class="sorter" sortBy="executionIndex"/>
</hbox>
</vbox>

</overlay>
54 changes: 54 additions & 0 deletions content/third-party/addons4.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Extension Manager UI.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Blair McBride <bmcbride@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

/* Derived from: chrome://mozapps/skin/extensions/extensions.css
* Firefox 4.0b10
*/

.sorter[checkState="1"],
.sorter[checkState="2"] {
background-color: rgba(194, 200, 206, 0.4);
box-shadow: 1px 1px 2px #B6BBC4 inset;
}

.sorter[checkState="1"] {
list-style-image: url("chrome://global/skin/arrow/arrow-dn.gif");
}

.sorter[checkState="2"] {
list-style-image: url("chrome://global/skin/arrow/arrow-up.gif");
}
6 changes: 6 additions & 0 deletions locale/en-US/gm-addons.dtd
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
<!ENTITY NewScript.accesskey "C">
<!ENTITY Show "Show Containing Folder">
<!ENTITY Show.accesskey "S">
<!ENTITY Sort.ByStatus "Sort by status">
<!ENTITY Sort.Status "Status">
<!ENTITY Sort.ByName "Sort by name">
<!ENTITY Sort.Name "Name">
<!ENTITY Sort.ByExecution "Sort by execution order">
<!ENTITY Sort.Execution "Execution Order">
<!ENTITY SortScripts "Sort Scripts">
<!ENTITY SortScripts.accesskey "S">
<!ENTITY UninstallCancel "Cancel Uninstall">
Expand Down
12 changes: 10 additions & 2 deletions skin/addons4.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
list-style-image: url(chrome://greasemonkey/skin/icon_medium.png);
}

.addon.addon-view[type="user-script"] .details.button-link {
display: none !important;
.addon.addon-view[type="user-script"] .details.button-link {
display: none !important;
}

#greasemonkey-sort-bar {
display: none;
}

page.greasemonkey #greasemonkey-sort-bar {
display: -moz-box;
}

0 comments on commit 1e83648

Please sign in to comment.