bug 589601 - Provide a fast bookmarking button in the urlbar, r=Neil
authorRobert Kaiser <kairo@kairo.at>
Mon, 06 Sep 2010 15:31:20 +0200
changeset 6325 831ed4c403f6315fad93864d31cf7c6c2cf88f5d
parent 6324 6c3e40bf58872079f40d506ee2e462d56e98a0dd
child 6326 ba68b04c0ab1e645cb60366dc17587897ab851c2
push idunknown
push userunknown
push dateunknown
reviewersNeil
bugs589601
bug 589601 - Provide a fast bookmarking button in the urlbar, r=Neil
suite/browser/navigator.js
suite/browser/navigator.xul
suite/browser/nsBrowserStatusHandler.js
suite/common/bookmarks/browser-places.js
suite/locales/en-US/chrome/browser/navigator.properties
suite/themes/classic/communicator/bookmarks/bookmark.png
suite/themes/classic/jar.mn
suite/themes/classic/mac/navigator/navigator.css
suite/themes/classic/navigator/navigator.css
suite/themes/modern/communicator/bookmarks/bookmark.png
suite/themes/modern/jar.mn
suite/themes/modern/navigator/navigator.css
--- a/suite/browser/navigator.js
+++ b/suite/browser/navigator.js
@@ -604,16 +604,18 @@ function Startup()
     document.getElementById("textfieldDirection-swap").hidden = false;
   }
 
   // Before and after callbacks for the customizeToolbar code
   getNavToolbox().customizeInit = BrowserToolboxCustomizeInit;
   getNavToolbox().customizeDone = BrowserToolboxCustomizeDone;
   getNavToolbox().customizeChange = BrowserToolboxCustomizeChange;
 
+  PlacesStarButton.init();
+
   PlacesToolbarHelper.init();
 
   // bookmark-all-tabs command
   gBookmarkAllTabsHandler.init();
 
   gBrowser.mPanelContainer.addEventListener("InstallBrowserTheme", LightWeightThemeWebInstaller, false, true);
   gBrowser.mPanelContainer.addEventListener("PreviewBrowserTheme", LightWeightThemeWebInstaller, false, true);
   gBrowser.mPanelContainer.addEventListener("ResetBrowserThemePreview", LightWeightThemeWebInstaller, false, true);
@@ -668,16 +670,18 @@ function WindowFocusTimerCallback(elemen
     }
   }
 }
 
 function Shutdown()
 {
   AddonManager.removeAddonListener(gAddonListener);
 
+  PlacesStarButton.uninit();
+
   // shut down browser access support
   window.browserDOMWindow = null;
 
   try {
     getBrowser().removeProgressListener(window.XULBrowserWindow);
   } catch (ex) {
     // Perhaps we didn't get around to adding the progress listener
   }
--- a/suite/browser/navigator.xul
+++ b/suite/browser/navigator.xul
@@ -319,16 +319,18 @@
                    onerror="gBrowser.addToMissedIconCache(this.src);"
                    tooltiptext="&proxyIcon.tooltip;"/>
           </deck>
           <hbox id="urlbar-icons"
                 class="urlbar-icons">
             <image id="feedsButton" hidden="true" popup="feedsPopup"/>
             <image id="ev-button" hidden="true"
                    onclick="if (event.button == 0) BrowserPageInfo(null, 'securityTab');"/>
+            <image id="star-button"
+                   onclick="PlacesStarButton.onClick(event);"/>
           </hbox>
           <menupopup id="ubhist-popup" class="autocomplete-history-popup"
                      popupalign="topleft" popupanchor="bottomleft"
                      onpopupshowing="createUBHistoryMenu(event.target);"
                      oncommand="executeUrlBarHistoryCommand(event.target);"/>
         </textbox>
       </toolbaritem>
 
--- a/suite/browser/nsBrowserStatusHandler.js
+++ b/suite/browser/nsBrowserStatusHandler.js
@@ -346,16 +346,18 @@ nsBrowserStatusHandler.prototype =
       var userTypedValue = browser.userTypedValue;
       if (userTypedValue === null) {
         URLBarSetURI(aLocation, true);
       } else {
         this.urlBar.value = userTypedValue;
         SetPageProxyState("invalid", null);
       }
 
+      PlacesStarButton.updateState();
+
       this.feedsMenu.setAttribute("disabled", "true");
       this.feedsButton.hidden = true;
       this.feeds = [];
     }
     UpdateBackForwardButtons();
 
     UpdateStatusBarPopupIcon();
   },
--- a/suite/common/bookmarks/browser-places.js
+++ b/suite/common/bookmarks/browser-places.js
@@ -680,16 +680,95 @@ var PlacesMenuDNDHandler = {
                                 PlacesUtils.bookmarks.DEFAULT_INDEX,
                                 Components.interfaces.nsITreeView.DROP_ON);
     PlacesControllerDragHelper.onDrop(ip, event.dataTransfer);
     event.stopPropagation();
   }
 };
 
 
+var PlacesStarButton = {
+  init: function PSB_init() {
+    try {
+      PlacesUtils.bookmarks.addObserver(this, false);
+    } catch(ex) {
+      Components.utils.reportError("PlacesStarButton.init(): error adding bookmark observer: " + ex);
+    }
+  },
+
+  uninit: function PSB_uninit() {
+    try {
+      PlacesUtils.bookmarks.removeObserver(this);
+    } catch(ex) {}
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsINavBookmarkObserver]),
+
+  _starred: false,
+  _batching: false,
+
+  updateState: function PSB_updateState() {
+    var starIcon = document.getElementById("star-button");
+
+    var uri = gBrowser.currentURI;
+    this._starred = PlacesUtils.getMostRecentBookmarkForURI(uri) != -1 ||
+                    PlacesUtils.getMostRecentFolderForFeedURI(uri) != -1;
+    if (this._starred) {
+      starIcon.setAttribute("starred", "true");
+      starIcon.setAttribute("tooltiptext", gNavigatorBundle.getString("starButtonOn.tooltip"));
+    }
+    else {
+      starIcon.removeAttribute("starred");
+      starIcon.setAttribute("tooltiptext", gNavigatorBundle.getString("starButtonOff.tooltip"));
+    }
+  },
+
+  onClick: function PSB_onClick(aEvent) {
+    if (aEvent.button == 0)
+      PlacesCommandHook.bookmarkCurrentPage(this._starred);
+
+    // don't bubble to the textbox so that the address won't be selected
+    aEvent.stopPropagation();
+  },
+
+  // nsINavBookmarkObserver
+  onBeginUpdateBatch: function PSB_onBeginUpdateBatch() {
+    this._batching = true;
+  },
+
+  onEndUpdateBatch: function PSB_onEndUpdateBatch() {
+    this.updateState();
+    this._batching = false;
+  },
+
+  onItemAdded: function PSB_onItemAdded(aItemId, aFolder, aIndex, aItemType) {
+    if (!this._batching && !this._starred)
+      this.updateState();
+  },
+
+  onBeforeItemRemoved: function() {},
+
+  onItemRemoved: function PSB_onItemRemoved(aItemId, aFolder, aIndex,
+                                            aItemType) {
+    if (!this._batching && this._starred)
+      this.updateState();
+  },
+
+  onItemChanged: function PSB_onItemChanged(aItemId, aProperty,
+                                            aIsAnnotationProperty, aNewValue,
+                                            aLastModified, aItemType) {
+    if (!this._batching && aProperty == "uri")
+      this.updateState();
+  },
+
+  onItemVisited: function() {},
+  onItemMoved: function() {}
+};
+
+
 // This object handles the initialization and uninitialization of the bookmarks
 // toolbar.  updateState is called when the browser window is opened and
 // after closing the toolbar customization dialog.
 let PlacesToolbarHelper = {
   _place: "place:folder=TOOLBAR",
   get _viewElt() {
     return document.getElementById("PlacesToolbar");
   },
--- a/suite/locales/en-US/chrome/browser/navigator.properties
+++ b/suite/locales/en-US/chrome/browser/navigator.properties
@@ -57,16 +57,20 @@ menuOpenAllInTabs.label=Open All in Tabs
 
 # urlbarBindings.xml
 # LOCALIZATION NOTE: This is for the location bar drop-down string:
 #   "Search " + search_engine_name + " for " + user_input
 #   e.g. "Search Google for abc"
 # DO NOT change the %S order when translate, the first %S must be the search engine name.
 searchFor=Search %S for "%S"
 
+# Star button
+starButtonOn.tooltip=Edit this bookmark
+starButtonOff.tooltip=Bookmark this page
+
 # Edit Bookmark UI
 editBookmarkPanel.pageBookmarkedTitle=Page Bookmarked
 editBookmarkPanel.pageBookmarkedDescription=%S will always remember this page for you.
 editBookmarkPanel.bookmarkedRemovedTitle=Bookmark Removed
 editBookmarkPanel.editBookmarkTitle=Edit This Bookmark
 
 # LOCALIZATION NOTE (editBookmark.removeBookmarks.label)
 # Semi-colon list of plural forms. Replacement for #1 is
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..20a3f81a46bce06fc29ad0d162f76ce3d3ba819a
GIT binary patch
literal 2778
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
--- a/suite/themes/classic/jar.mn
+++ b/suite/themes/classic/jar.mn
@@ -53,16 +53,17 @@ classic.jar:
   skin/classic/communicator/dialogs.css                                 (communicator/dialogs.css)
   skin/classic/communicator/communicatorBindings.xml                    (communicator/communicatorBindings.xml)
   skin/classic/communicator/preferences.css                             (communicator/preferences.css)
   skin/classic/communicator/prefpanels.css                              (communicator/prefpanels.css)
   skin/classic/communicator/smileys.css                                 (communicator/smileys.css)
   skin/classic/communicator/tasksOverlay.css                            (communicator/tasksOverlay.css)
   skin/classic/communicator/viewSourceOverlay.css                       (communicator/viewSourceOverlay.css)
   skin/classic/communicator/bookmarks/allBookmarks.png                  (communicator/bookmarks/allBookmarks.png)
+  skin/classic/communicator/bookmarks/bookmark.png                      (communicator/bookmarks/bookmark.png)
   skin/classic/communicator/bookmarks/bookmark-item-dis.png             (communicator/bookmarks/bookmark-item-dis.png)
   skin/classic/communicator/bookmarks/bookmark-item.png                 (communicator/bookmarks/bookmark-item.png)
   skin/classic/communicator/bookmarks/bookmarksManager.css              (communicator/bookmarks/bookmarksManager.css)
   skin/classic/communicator/bookmarks/bookmarksMenu.png                 (communicator/bookmarks/bookmarksMenu.png)
   skin/classic/communicator/bookmarks/bookmarksToolbar.png              (communicator/bookmarks/bookmarksToolbar.png)
   skin/classic/communicator/bookmarks/editBookmarkOverlay.css           (communicator/bookmarks/editBookmarkOverlay.css)
   skin/classic/communicator/bookmarks/livemark-folder.png               (communicator/bookmarks/livemark-folder.png)
   skin/classic/communicator/bookmarks/livemark-item.png                 (communicator/bookmarks/livemark-item.png)
--- a/suite/themes/classic/mac/navigator/navigator.css
+++ b/suite/themes/classic/mac/navigator/navigator.css
@@ -529,16 +529,43 @@ toolbar[mode="text"] #bookmarks-chevron 
 }
 
 #wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box {
   width: 16px;
   height: 16px;
   background: url("chrome://communicator/skin/bookmarks/bookmarksToolbar.png") no-repeat;
 }
 
+/* ::::: star button ::::: */
+
+#star-button {
+  list-style-image: url("chrome://communicator/skin/bookmarks/bookmark.png");
+  -moz-image-region: rect(16px 16px 32px 0px);
+}
+
+#star-button:hover {
+  -moz-image-region: rect(16px 32px 32px 16px);
+}
+
+#star-button:hover:active {
+  -moz-image-region: rect(16px 48px 32px 32px);
+}
+
+#star-button[starred="true"] {
+  -moz-image-region: rect(0px 16px 16px 0px);
+}
+
+#star-button[starred="true"]:hover {
+  -moz-image-region: rect(0px 32px 16px 16px);
+}
+
+#star-button[starred="true"]:hover:active {
+  -moz-image-region: rect(0px 48px 16px 32px);
+}
+
 /* ::::: feeds ::::: */
 
 #feedsMenu {
   list-style-image: url("chrome://communicator/skin/icons/feedIcon16.png") !important;
 }
 
 #feedsButton {
   list-style-image: url("chrome://navigator/skin/btn1/feeds.png");
--- a/suite/themes/classic/navigator/navigator.css
+++ b/suite/themes/classic/navigator/navigator.css
@@ -546,16 +546,43 @@ toolbar[mode="text"] toolbarbutton.chevr
 }
 
 #wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box {
   width: 16px;
   height: 16px;
   background: url("chrome://communicator/skin/bookmarks/bookmarksToolbar.png") no-repeat;
 }
 
+/* ::::: star button ::::: */
+
+#star-button {
+  list-style-image: url("chrome://communicator/skin/bookmarks/bookmark.png");
+  -moz-image-region: rect(16px 16px 32px 0px);
+}
+
+#star-button:hover {
+  -moz-image-region: rect(16px 32px 32px 16px);
+}
+
+#star-button:hover:active {
+  -moz-image-region: rect(16px 48px 32px 32px);
+}
+
+#star-button[starred="true"] {
+  -moz-image-region: rect(0px 16px 16px 0px);
+}
+
+#star-button[starred="true"]:hover {
+  -moz-image-region: rect(0px 32px 16px 16px);
+}
+
+#star-button[starred="true"]:hover:active {
+  -moz-image-region: rect(0px 48px 16px 32px);
+}
+
 /* ::::: feeds ::::: */
 
 #feedsMenu {
   list-style-image: url("chrome://navigator/skin/btn1/feeds.png") !important;
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
 #feedsMenu[_moz-menuactive="true"] {
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6cf22abe443cb4fc6a30cc9e74130354c27bb564
GIT binary patch
literal 2815
zc$@+M3IO$qP)<h;3K|Lk000e1NJLTq001xm001Be1^@s6RMh(%00001b5ch_0Itp)
z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ige*
z5+fE6V6ub&004w(R9JLFZ*6U5Zgc<u0000eLn$CKFfcYCO>cT>Y;0jJZ*pe}L3MO!
zZ*n>yO<{6uZ*Cw$X>(|Aa0*FdZ*Cw&Wpim~ZaN@IV{dL|VPkY}a(N0vZ*FvQX<~JB
zZ*p@w3Lqd&VQzJ0Y#>r)X>Db4ASg{?ZgpjBE>dM_ZDn#mXKi>cWMwHD%H}Qr0159&
zL_t(o!|j)UR8(ae$G`W!_cAjK1H*4nbd+%fD-2mhP(sLD()>|LzfM~x&6SRtx>)U!
zYoaI8QdkoYyJN+g**Pw)>sn-Ny9$e__^U1O2QrR~IuxTYz>LfcGxy$i|7c(bB0&73
z{iElcd(OS*y`T4ezV~^a_qi`HgasYk8=<Z!^TP-&=-}R1bw!!tF8D-sMVacy#@WGO
zb$OYBzd!LFaNPKjEUqpu3*_%ld<YyjZG?O%e}Ce0;JAl>>>bYc;qm8})1Ld!ni~ii
zubCDT=nr$eF4}+XiYtyCCE{QU_TxD+Uh{;PkN01@;)G*Ii7*(S^2n3D{5e+(PsVFr
z^YSVFYgZg{>?m>fXBgkb^@Rn!13Bx~<8onMrp4pHC_fo))L*tzkF%SNijYH+l-9(I
z6aAfkZ`a$9D1}HVR;<p$<-)uiAKpwo&f9EML?9$dZB5MB*WdXyFJ?oc6p|>RWKTJ4
zAHG>=@i-VSf0=rm?QB#;7$hmunwXJ4U<yTPr^0aU7W9P$h+DU%5|V^(1vj(__l1m0
zN{mj4i46wJ-X7=+N|YjM%oJEVZlm}QZz68p7QGK2GcGAHJ|!l06j;{!gH&KRNR;AN
zIU8ZMIk5b>xlq0E+jU-^Y7_2@8<&)rk`fa;0WACNfHmNhfF{FP1StJ+{>pXe3k#6`
zdT}N72xw}z;D)6Qt&#{xl4T$PZi&LwbQXl;&|>XCQQ;<}zh0~#fH(AK1uDQJN_f9`
z0|;SZ>9AqRGmk*Gd}}WC2uwfzT(5wTx@s=ubmhcT+j2A4zPcX&tg3}Fz#lSRfo~d2
z&=(e9*7{wQ43UEgRiRZ9@qBFD&7KKD>Z)ZSrz_J=ZOhGhc}*US*P1~%0+!*>a;pRH
zyt5Ir*6-5y<BdMNBII=C;v1!#i}ZWS(Qxe+SdM@N3yZZA&ptgHx|iO}?Z<!JD}dT>
zs}-8)QK5uG_2$)?HOHz^b>b9)f&<~NP@?vmE8j;Ve^(_05mR^$`)sW<L+Yw!06^`x
zqZOLyd%S$khov8*$=nRyj{_kbZnU(aV9W23p1(`)!#^KVSMBfRwF*u2j8MW+LrGpy
z-B%ZI@tOt1j{{2xuHCZXsqBZKTlIFXm#6z|t(!yYssnqAIQUq(g6LwWCh#g!-)%$6
z+HIAOEnbXilM~R^(S{DY9cfeUMb5hQsDA6^%!L7AsBzoTYHqH#CS|q-A1e<ey4dUl
zUd4HN{i<~<5fK)OE~f*IZWl&JgyN0$TTuPh%Q-%Lg*7SjdhoIGP@;={C4pD*_1!jR
z+zT6Wr=}%C6Rt+5yBm&fH^zjhaNyukT+weRS{M*UYut9G)!h6(3jpm8%y)`L(}^xB
zfe<+^6u*(Vr}P7ysjEkTDiA7#5>=<_du!sn;704!8_ldbwA0JmM5Af151&);Mgf{F
zH$iwF93f~j-^7N^uOa>QV!f9?&#FUPynLHzG;Qpn5<`d_Z69qfsybW+!}Xhx6BdMJ
zVQB8af(7Z&E#I1ZUT`z5S8vp?>d>a%ZB$)R7M(RcE$+121(p>+C_u7atbFBnuVIo_
zi|spi^eMW(?cL4vX*v~U@mbT;();oHg5s?R4hll?ww*)qDOuCgp77=E8B1~>S}+Hr
zB2@VI(Nkb356XA|0JWc&F@5?#xW$;bM4?h!B@sL$;kd^MkrI5DG`Diw_H9`H>s44|
zuFWj1Id1Nlmwl!GE)s4rE?A;aMGwI1|Fmy6o>}l5)|hK^N^6eScg)K^IRL+Mi9!|Y
z!&8wG#+0-uci~fuuz$}d_|4VIqSBh<)gAM)5B;DMOIE9YslwSVG+cCm<CM#i)6}23
zI`GnkW0}iird9%ghVWoVg~<Sb=(LPzFj600U8-=Jg@%ir;JA=w$!XDEKIfU3sd^ti
zz{|6u!6^Cg5v2-eqtI~i7C0_yS#p~8Q&$JpTsTs=CH8@JK726IX&C^FXfR4#k27tP
zrk(H(5H>23Z#<MdeU2;$?>TLhWK0Sat1j6#x0q~<Oc~U(Xpaal{}It?SpXax6{%=E
zl>C&Jmq^B>2(jwY&CM+)3nNoT4#2Z*lcsGXIxPX<$3{ge8xJMt&5;Gs_nbC~pD}K%
z=Y;9{<`$EQktsDj4AE&Bre`8=Ix*hn#s==*IblpfT)6Sw-Sw{h2V4Lo00ICJEDJ~y
z?TLU7PkOGv-8)mqB*euU-`!o|+JC?fKm_0h;PK%lAD;DQ1n=b^9g`3@+4%164_x~X
zw0YNd0qFMOMFIfS+74=Mr)+2l08jv66mq*=5;`44B{uKkqIZmfQuwCN06b+B@|$)^
zxalY=X#wEr75_a?`}1B_>bV$&{JLEdOpc<GCNJ;y&LM$P$v6Fewx81a?8VR~KiYe5
zJpK1Ooh)oh=8B&C*8fzN+$ryS9_ZQUhcd2@^TyLPz0YH3&&Ty6<#*!z*)R5{NB}&d
zh_tz@#9MXc`a5y{g(v1fq7;HCfuTG-dHCZYMf~q~+C}UD08Q#b0KoMlwS6Ko)Rz$X
zE(t*FFCM$(c6)I2vmG;iBQhlKJrAsWwFq{H3)u@(`$S}D0dn#CgY&hMpZcUx4aUx%
zKO6@H;!z5sgo`K3CP@HXZZ|6a`p1;;$@6oD#Zv)pLBjTe)nFI~?OhHmn45~!dC$_}
z*TC4>^AR-mBI^Ha>sK3T!>Nhz$@6m#{$+cHQpS3^Jpx2g07Dooe0p{5aB3oT-m`St
zjLC=$mc!xfhFkE!Um?RkzC8V-H9`73bv8AES0rJ=EQ*%;E&xFKA_cxadKF`5KZwqz
z#=#tLSQ^iLdGcz&?5y;AWjregl7!oCkvzRPYxLoo<_L$S@!Vj%*-*bp9X39n`pXgE
z?*~zmV0Cy9KXDX9E-K$_sNXcW006L?o1j$8#JCI>TI#!?iRYn-=TY~C3EJdeqP@9c
zFehx^8NNAO+Yp|W^`MUDSiwUn>l6g`$;W5KRGhjJ?PxKb8H_hx_-Yd?3(l7Z2SX_%
za8rs7M>i%;j0E)y&o>(`Y#Lku0JJwZfT(66D5)FuhuWcu=Mgx=9}S-yh7$>=#dM~;
z>T=Yahi6TY`!Q~}D6zMlBA5Nx>`_N*Ekj1)TjQloE{{ClKQsgZ3IdNrVeRx_f-VxA
zJf=@12H&PMsY@Y7oPqh!chDxM!J`tu+qvQP30Z7v-Up>ylLC~ybJ_CswT!3~Dd{4^
z?Gw@W%%rJvW+Ft*<NR5}faigsO_RD5F^dwQNnJXUPD#d2%PalYkxwvsYTihA<(SEI
z{>og+gvC>g*fgn2M=AgSFnVg<NCf}@6Bd7$0(wN;jopQS9uYtP`TalIe*u@w^-4!F
RbkzU=002ovPDHLkV1g*JKhFRF
--- a/suite/themes/modern/jar.mn
+++ b/suite/themes/modern/jar.mn
@@ -21,16 +21,17 @@ modern.jar:
   skin/modern/communicator/toolbar.css                             (communicator/toolbar.css)
   skin/modern/communicator/dialogs.css                             (communicator/dialogs.css)
   skin/modern/communicator/helpOverlay.css                         (communicator/helpOverlay.css)
   skin/modern/communicator/smileys.css                             (communicator/smileys.css)
   skin/modern/communicator/communicator.css                        (communicator/communicator.css)
   skin/modern/communicator/aboutSessionRestore.css                 (communicator/aboutSessionRestore.css)
   skin/modern/communicator/viewSourceOverlay.css                   (communicator/viewSourceOverlay.css)
   skin/modern/communicator/bookmarks/allBookmarks.png              (communicator/bookmarks/allBookmarks.png)
+  skin/modern/communicator/bookmarks/bookmark.png                  (communicator/bookmarks/bookmark.png)
   skin/modern/communicator/bookmarks/bookmark-folder-closed.gif    (communicator/bookmarks/bookmark-folder-closed.gif)
   skin/modern/communicator/bookmarks/bookmark-folder-dis.gif       (communicator/bookmarks/bookmark-folder-dis.gif)
   skin/modern/communicator/bookmarks/bookmark-folder-open.gif      (communicator/bookmarks/bookmark-folder-open.gif)
   skin/modern/communicator/bookmarks/bookmark-item-dis.gif         (communicator/bookmarks/bookmark-item-dis.gif)
   skin/modern/communicator/bookmarks/bookmark-item.gif             (communicator/bookmarks/bookmark-item.gif)
   skin/modern/communicator/bookmarks/bookmarks.css                 (communicator/bookmarks/bookmarks.css)
   skin/modern/communicator/bookmarks/bookmarksManager.css          (communicator/bookmarks/bookmarksManager.css)
   skin/modern/communicator/bookmarks/bookmarksMenu.png             (communicator/bookmarks/bookmarksMenu.png)
--- a/suite/themes/modern/navigator/navigator.css
+++ b/suite/themes/modern/navigator/navigator.css
@@ -717,16 +717,43 @@ toolbar[mode="text"] toolbarbutton.chevr
 #ev-button {
   list-style-image: url("chrome://communicator/skin/icons/identity.png");
 }
 
 #popupIcon {
   list-style-image: url("chrome://navigator/skin/icons/popup-blocked.png");
 }
 
+/* ::::: star button ::::: */
+
+#star-button {
+  list-style-image: url("chrome://communicator/skin/bookmarks/bookmark.png");
+  -moz-image-region: rect(16px 16px 32px 0px);
+}
+
+#star-button:hover {
+  -moz-image-region: rect(16px 32px 32px 16px);
+}
+
+#star-button:hover:active {
+  -moz-image-region: rect(16px 48px 32px 32px);
+}
+
+#star-button[starred="true"] {
+  -moz-image-region: rect(0px 16px 16px 0px);
+}
+
+#star-button[starred="true"]:hover {
+  -moz-image-region: rect(0px 32px 16px 16px);
+}
+
+#star-button[starred="true"]:hover:active {
+  -moz-image-region: rect(0px 48px 16px 32px);
+}
+
 /* ::::: feeds ::::: */
 
 #feedsMenu {
   list-style-image: url("chrome://navigator/skin/btn1/feeds.png") !important;
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
 #feedsMenu[_moz-menuactive="true"] {