[Pkg-mozext-commits] [tree-style-tab] 01/04: Imported Upstream version 0.16.2016021602
Ximin Luo
infinity0 at debian.org
Sat Feb 20 23:28:44 UTC 2016
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch master
in repository tree-style-tab.
commit 0c2052b93a816b197a1af7024c0f1afe39527deb
Author: Ximin Luo <infinity0 at debian.org>
Date: Sat Feb 20 22:45:32 2016 +0100
Imported Upstream version 0.16.2016021602
---
META-INF/manifest.mf | 203 +++++----
META-INF/mozilla.rsa | Bin 4189 -> 4189 bytes
META-INF/mozilla.sf | 4 +-
content/treestyletab/bookmarksOverlay.js | 488 +-------------------
content/treestyletab/bookmarksOverlayEditable.js | 123 +++--
content/treestyletab/config.xul | 1 +
content/treestyletab/license.txt | 2 +-
content/treestyletab/treestyletab.css | 12 +
content/treestyletab/treestyletab.js | 8 +-
content/treestyletab/treestyletab.xul | 4 +-
content/treestyletab/windowHelper.js | 147 +++---
content/treestyletab/windowHelperHacks.js | 2 +-
defaults/preferences/treestyletab.js | 21 +-
install.rdf | 7 +-
locale/cs/treestyletab/treestyletab.dtd | 4 +-
locale/da-DK/treestyletab/treestyletab.dtd | 4 +-
locale/de-DE/treestyletab/license.txt | 5 +-
locale/de-DE/treestyletab/treestyletab.dtd | 274 ++++++-----
locale/en-US/treestyletab/treestyletab.dtd | 3 +-
locale/es-ES/treestyletab/treestyletab.dtd | 4 +-
locale/fr-FR/treestyletab/treestyletab.dtd | 4 +-
locale/it-IT/treestyletab/treestyletab.dtd | 4 +-
locale/ja/treestyletab/treestyletab.dtd | 3 +-
locale/pl/treestyletab/treestyletab.dtd | 4 +-
locale/ru/treestyletab/treestyletab.dtd | 12 +-
locale/sv-SE/treestyletab/treestyletab.dtd | 4 +-
locale/zh-CN/treestyletab/treestyletab.dtd | 4 +-
locale/zh-TW/treestyletab/treestyletab.dtd | 4 +-
modules/autoHide.js | 90 +++-
modules/base.js | 395 ++++------------
modules/bookmark.js | 504 +++++++++++++++++++++
modules/browser.js | 326 +++++++++----
modules/browserUIShowHideObserver.js | 57 ++-
modules/constants.js | 18 +
modules/contentBridge.js | 15 +-
modules/fullTooltip.js | 71 ++-
modules/fullscreenObserver.js | 10 +-
modules/groupTab.js | 32 +-
modules/pseudoTreeBuilder.js | 66 ++-
modules/tabAttributesObserver.js | 11 +-
...ttributesObserver.js => tabContentsObserver.js} | 96 ++--
modules/tabbarDNDObserver.js | 96 ++--
modules/utils.js | 370 ++++++++++++++-
modules/window.js | 141 +++++-
skin/classic/treestyletab/group.css | 13 +-
skin/classic/treestyletab/license.txt | 2 +-
skin/classic/treestyletab/metal/base.css | 68 ++-
skin/classic/treestyletab/pseudo-tree.css | 30 +-
skin/classic/treestyletab/sidebar/sidebar.css | 48 +-
skin/classic/treestyletab/square/base.css | 17 +
skin/classic/treestyletab/square/vertigo.css | 18 +
skin/classic/treestyletab/ui-base.css | 10 +
treestyletab.update.rdf | 30 ++
53 files changed, 2426 insertions(+), 1463 deletions(-)
diff --git a/META-INF/manifest.mf b/META-INF/manifest.mf
index d30ab74..9e2f63f 100644
--- a/META-INF/manifest.mf
+++ b/META-INF/manifest.mf
@@ -2,8 +2,8 @@ Manifest-Version: 1.0
Name: install.rdf
Digest-Algorithms: MD5 SHA1
-MD5-Digest: CAt8kfQijgwV0VrebcRR4g==
-SHA1-Digest: taJHxkigk8GxKRBvwYWA7GbI25k=
+MD5-Digest: GhhEUrydTwg3fyzdRVE7Hw==
+SHA1-Digest: IA2smyD8Ao/QqmYTFfcSGOwW370=
Name: chrome.manifest
Digest-Algorithms: MD5 SHA1
@@ -15,6 +15,11 @@ Digest-Algorithms: MD5 SHA1
MD5-Digest: b26p1vuhLB2vYtkJ0EpFZg==
SHA1-Digest: T9f7i8A7iAz/ElpA361lLRpnbWc=
+Name: treestyletab.update.rdf
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: P0m8CTDmPTu3ahll/DOucQ==
+SHA1-Digest: Fj8WbLoHt0uNXjyC/5Nt63948rA=
+
Name: components/AboutGroup.js
Digest-Algorithms: MD5 SHA1
MD5-Digest: D+AXOvn4yNMXf8GhIKbFrA==
@@ -22,8 +27,8 @@ SHA1-Digest: XLM7zjvCkIi09SoAGOVOZdeQofY=
Name: content/treestyletab/bookmarksOverlay.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: sLs6Xz86OV6NK6RJVHgEvA==
-SHA1-Digest: pmX3AWu0z9RzIeDgImy8NfP1UIA=
+MD5-Digest: w3yRAETKAdZTGAbBG3Em7Q==
+SHA1-Digest: wihCEtZ16DVkz+waXI6bdMxzAdI=
Name: content/treestyletab/bookmarksOverlay.xul
Digest-Algorithms: MD5 SHA1
@@ -37,8 +42,8 @@ SHA1-Digest: /V6d117O8c9Qgt7NoCuVRN2bOF0=
Name: content/treestyletab/bookmarksOverlayEditable.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: aRKA2Ooi+mTYX9yfoZnEqg==
-SHA1-Digest: DtU1d+Is7rWbs3c/rzdEje7a8Tk=
+MD5-Digest: u6u3KPfJJdx4eWOpykXXAA==
+SHA1-Digest: zh1Sx8pycIsT2yk/kjw3eBA9cTk=
Name: content/treestyletab/bookmarksOverlayEditable.xul
Digest-Algorithms: MD5 SHA1
@@ -57,8 +62,8 @@ SHA1-Digest: LSm4XQfNAqRWieDG2oKRk54Rrh8=
Name: content/treestyletab/config.xul
Digest-Algorithms: MD5 SHA1
-MD5-Digest: QaUI+njq/1aPa0LBOt69hw==
-SHA1-Digest: RikaDXmgEw6M/cVHItWilEShkAA=
+MD5-Digest: NZY8ITSUeWciGsIYiwKgaA==
+SHA1-Digest: n3WFwTJN9dYOliz5YDpjd13YJh4=
Name: content/treestyletab/content-utils-autohide.js
Digest-Algorithms: MD5 SHA1
@@ -82,8 +87,8 @@ SHA1-Digest: dVIKETt9CnpIKynmf5iCpf1jDNo=
Name: content/treestyletab/license.txt
Digest-Algorithms: MD5 SHA1
-MD5-Digest: ks0H9N1HwtHOGFBceqqXLA==
-SHA1-Digest: EeTFV+ifwWkwaWvQiix88l8YDtw=
+MD5-Digest: LPKF3jz0aUCOORAZxF3CBw==
+SHA1-Digest: 9pCMihCjV7sRiu2H4IKuovx68LM=
Name: content/treestyletab/multipletabConfigOverlay.xul
Digest-Algorithms: MD5 SHA1
@@ -97,13 +102,13 @@ SHA1-Digest: dUnh9cVls70LC0cO+AzOTyJ+7Bc=
Name: content/treestyletab/treestyletab.css
Digest-Algorithms: MD5 SHA1
-MD5-Digest: Mm0SnlWa87xf7i6PZskaSA==
-SHA1-Digest: V8ChvaXQTQoL7PWPnqUSUybFakY=
+MD5-Digest: Y+LtIloCWi9BRp0tIr38/Q==
+SHA1-Digest: hY2iyFgCqbULOeYkM7FS3NnkQMc=
Name: content/treestyletab/treestyletab.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: rAQdu8NF3MYvlInTA/rnZA==
-SHA1-Digest: mdGLj3IkGat9NH80/KPUwZIx3zc=
+MD5-Digest: 6E9tmEesiujXo1RfuXj+tw==
+SHA1-Digest: NWhDnh0jSiQ+8Yn2qWWKZl+smqA=
Name: content/treestyletab/treestyletab.xml
Digest-Algorithms: MD5 SHA1
@@ -112,18 +117,18 @@ SHA1-Digest: yI4r2a9JmBDqDI8qcvvn6R1wG4M=
Name: content/treestyletab/treestyletab.xul
Digest-Algorithms: MD5 SHA1
-MD5-Digest: a1axHz8ImoVUaGIhA0wOzA==
-SHA1-Digest: xdVcooRj2CkN5RnELJyfUbvKzZ0=
+MD5-Digest: gzxBjw2xe+IkDHQVK1ojcA==
+SHA1-Digest: 9lVQdUME2zPBCECRLZrK2fGxEFY=
Name: content/treestyletab/windowHelper.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: JOMK+8toiBUS/M03riElHw==
-SHA1-Digest: cyjdZyq02U3zrD87OG+gxvTnJZM=
+MD5-Digest: r4uLpCypKvERzfkcDWZU0A==
+SHA1-Digest: 2eJCf+fAYOKLzjm/CMJlBLS73Oc=
Name: content/treestyletab/windowHelperHacks.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: vVo8T1auXVrfm43DVwFlQQ==
-SHA1-Digest: NGxQoWrIDKS8RhPZk6DbEXVcDbY=
+MD5-Digest: tIusMKnymHkV00GpE4vqNg==
+SHA1-Digest: 7ALqU8yWobS7ys5FjKr+tlBz+VY=
Name: content/treestyletab/res/bookmarkMultipleTabs.xul
Digest-Algorithms: MD5 SHA1
@@ -203,8 +208,8 @@ SHA1-Digest: q0mYa40sk7KoHzdmK6voR/OuGF8=
Name: defaults/preferences/treestyletab.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: lPwzD9NItQEv3PUa7RZRJQ==
-SHA1-Digest: soqONodaywdE4m2JsBSw7OW91Pw=
+MD5-Digest: vXg0XUNA6dpDy6LBjdxO8g==
+SHA1-Digest: b9nv5QEmT1sZj/o8+K7DnzAHGqg=
Name: locale/cs/treestyletab/license.txt
Digest-Algorithms: MD5 SHA1
@@ -213,8 +218,8 @@ SHA1-Digest: AmPIaBSAXJtd03ZD/LGrxu3FN3Y=
Name: locale/cs/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: GFjhguaDXqBoU6EmEPralw==
-SHA1-Digest: 6Bnzxn4B1BUNCsB4R1/jkfcDiqw=
+MD5-Digest: S1c7sGxI5L45WTemrDpN2Q==
+SHA1-Digest: r5pt9I98GQbtwLsN9lrvKzVaIWU=
Name: locale/cs/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -228,8 +233,8 @@ SHA1-Digest: vjay7k00E2Dhmo0XsTlEeFTRPXI=
Name: locale/da-DK/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: 2qQbuzytrLI3gR1RShTh3g==
-SHA1-Digest: Wq4dH3SqSOEhXLAI4XjO8ovAGLc=
+MD5-Digest: MGcs5SmhA0RFaLZ+jMuBpg==
+SHA1-Digest: E1K4ntc3dnYJnNyyqCGIFgZn59c=
Name: locale/da-DK/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -238,13 +243,13 @@ SHA1-Digest: ST1q6G8rHvDj78R+2ob8U7WMBdo=
Name: locale/de-DE/treestyletab/license.txt
Digest-Algorithms: MD5 SHA1
-MD5-Digest: P1OFa2/VTsD9tBpI1qCeSA==
-SHA1-Digest: CQr1mkH//MpqNCWbLou/CJX2aDk=
+MD5-Digest: Bl+6HAZa3Dp3iHyhd2VYIg==
+SHA1-Digest: JdQfP7XjmROHYlyQEMxiYImBB38=
Name: locale/de-DE/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: 8k+CsLwHHSe1I54khQTQ9w==
-SHA1-Digest: vfifHgKnlz1ZfkGFHQWClnbOnlg=
+MD5-Digest: g5xm6kv8MCM9UpFM67F6EA==
+SHA1-Digest: uFn6iFBt/WujKnMH1Txp8N810NY=
Name: locale/de-DE/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -258,8 +263,8 @@ SHA1-Digest: /vNGGzRR58QK5AOQjlorkE5GCAI=
Name: locale/en-US/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: iDLxSpuoKKNs699XnahdWA==
-SHA1-Digest: 4VWXkPnDg6Y/as5jndUQ2Crv3Eo=
+MD5-Digest: 79tbzrCYB/x0bdBOiDfs7w==
+SHA1-Digest: Ll5LFDQhfOdJg8EMWUO/QAZdG78=
Name: locale/en-US/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -273,8 +278,8 @@ SHA1-Digest: OeORv30Cbr8ylQKVbM0O9Y5n+4Y=
Name: locale/es-ES/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: OUTcy4zd5Vxuzcu5FXhgGA==
-SHA1-Digest: dq3ViTmc3yQeagUUn6jn1AJqh5g=
+MD5-Digest: FZ8qygxK89diULrqTjwkUA==
+SHA1-Digest: /ALFGxPRT17mrwhASIWhTTVggq8=
Name: locale/es-ES/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -288,8 +293,8 @@ SHA1-Digest: eSqlFr5OnT5gIpY1PF7f/E3bHas=
Name: locale/fr-FR/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: Xv5frYQruWKmsjywNOTj9A==
-SHA1-Digest: SNvJsrIA10cSSO0a+nb2zs3i9Ck=
+MD5-Digest: N6bDJ3SzgVZe1UlTgRFwsg==
+SHA1-Digest: PXpG4+Xyjn3jjJJDZemJaFQeQNA=
Name: locale/fr-FR/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -303,8 +308,8 @@ SHA1-Digest: DqBJQrV8f3tss7fKSnCdeXNIxYs=
Name: locale/it-IT/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: +EEwXCEjVyEwhfddMukiTQ==
-SHA1-Digest: 3z666pwEzH6Tee/hDX1shLrntFE=
+MD5-Digest: lQk7kY4EANS4K8T/ikjJLQ==
+SHA1-Digest: L5MogwLPip1K4gUGbiazhgzLKhg=
Name: locale/it-IT/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -318,8 +323,8 @@ SHA1-Digest: /vNGGzRR58QK5AOQjlorkE5GCAI=
Name: locale/ja/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: mkOJ40PDsuMqvNxtpJJjOA==
-SHA1-Digest: FfRIjSw0qEiGxdFlwQ//fQkptg4=
+MD5-Digest: FkeegJj5UPAbmhnKhVcf3A==
+SHA1-Digest: FdMi4A/WAXHC4XUZ+xyzLSPg0hs=
Name: locale/ja/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -333,8 +338,8 @@ SHA1-Digest: JwRGjnhAsrasY46ktL+EtP3fxDI=
Name: locale/pl/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: KFVWmQdcJ9pGREtXLoODOg==
-SHA1-Digest: i5B0DPl6SfjGK6eXQY2b9QIAFOc=
+MD5-Digest: H9KOrshnfLwdtj7W5L+61g==
+SHA1-Digest: eqB5I2Nq/aUMmXlWRW2lU+ZKVTo=
Name: locale/pl/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -348,8 +353,8 @@ SHA1-Digest: Ewz5/CWtInQDfBCQoje+iGZbjEE=
Name: locale/ru/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: PfBvTn8K+gNIHmvd/dGkDg==
-SHA1-Digest: fsTj+hUNX9NzIOCW4Z15gFW0Dik=
+MD5-Digest: dWGYPSeZ5341VaTF1/MdXA==
+SHA1-Digest: pK3SDZcLZCbCfqnVARH8M+RP84c=
Name: locale/ru/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -363,8 +368,8 @@ SHA1-Digest: Zfn4AKRpBe4E44Sg1HIuoxFmif0=
Name: locale/sv-SE/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: sAP3Nk44J3lDruqer4GpDQ==
-SHA1-Digest: V/BXP1zzBS4VWaFmWr67FUKcQ4w=
+MD5-Digest: V6/Vd3aktzj4JZvOwOdXsw==
+SHA1-Digest: ngGCi/Hn1Kgd+plJuY2vZmD4ZdA=
Name: locale/sv-SE/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -378,8 +383,8 @@ SHA1-Digest: CxdX2iIT5cw2WR+1eMh9AA78n+U=
Name: locale/zh-CN/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: p/wDbKOmcTNUKMPVJJ6m0w==
-SHA1-Digest: hRTFekXYZAHKfuy0jZMKnwMjwg4=
+MD5-Digest: KnhHB+1luU5RevlomI6QFw==
+SHA1-Digest: 8bj+cDEDY+yjEXy7IO/5PnxL9js=
Name: locale/zh-CN/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -393,8 +398,8 @@ SHA1-Digest: XVqJMKhADCM73LtM7OFthNdECYo=
Name: locale/zh-TW/treestyletab/treestyletab.dtd
Digest-Algorithms: MD5 SHA1
-MD5-Digest: wOiKXRdEV9+7hWwqWu7suQ==
-SHA1-Digest: QsZ16EOh4Nq8UKRGsln0l3WiX8Q=
+MD5-Digest: sYDn/nP1GsBXhSJ7A+lIQA==
+SHA1-Digest: 693d8xo1yzJWXJEr3aJvNW/1kRI=
Name: locale/zh-TW/treestyletab/treestyletab.properties
Digest-Algorithms: MD5 SHA1
@@ -403,53 +408,58 @@ SHA1-Digest: 820CmLC9fE1O0AAZaeKrzW0ER0g=
Name: modules/autoHide.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: WSRRLknoma7O3S9aJkSOKw==
-SHA1-Digest: lGdnY8ofd14V1AMwdEOp8dKjAPc=
+MD5-Digest: 9qFptUgYah+iSy44QE8Naw==
+SHA1-Digest: OHvqXa79X2rOIFUeOsIEN78zno4=
Name: modules/base.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: VOevY6uJ0ZCSWIiIZmzO2Q==
-SHA1-Digest: +L7wNk9LzQHZUw9OPQZSEg1NilY=
+MD5-Digest: 1TiyG9rY3cIybESDkUrR5g==
+SHA1-Digest: 1S8UA0ZVJI817ysQG2J4cT9Qoy0=
+
+Name: modules/bookmark.js
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: +NLpHc0+GiT0lSzGiJtlNA==
+SHA1-Digest: GYZNPm63Yrhqkide8fT3TyXFJvw=
Name: modules/browser.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: QGVmf085jGnv2mcc5Hq06A==
-SHA1-Digest: 2QUA4g3DDsXPc/PmD9FT42CGRac=
+MD5-Digest: mGAY2Pmq1BEh2fg63QWAaA==
+SHA1-Digest: RyyoaY7u1toldesei3wwQ9hQkoM=
Name: modules/browserUIShowHideObserver.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: 1jGa2nmHU/8r438jcy8bxA==
-SHA1-Digest: 0ye5nfvkIj6pI35yGQAEL7xtJ+k=
+MD5-Digest: dNk/UnlE0F8L4dJZICP6Nw==
+SHA1-Digest: D84Jbg20wtUqqgG4pWCgF9ZdVaw=
Name: modules/constants.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: EHGxOf4hgnxhSn5EG9Q3ig==
-SHA1-Digest: uk+B7UWHZ+SGcCrBuSYDEi+lwBE=
+MD5-Digest: BZIM6ulqOhpQxI0KmT/J4Q==
+SHA1-Digest: ZQ/tn2EH7qOR5Pmaez8DZaeyVXo=
Name: modules/contentBridge.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: 8EkTrdJ8nAxYO+81/mRYig==
-SHA1-Digest: PjTvEP1WjiDk/FgiOz5XVHKr/+E=
+MD5-Digest: AxdjgF9qLoOy1Dwpm94DKQ==
+SHA1-Digest: F+2KHUcbSxqlW4FbdoKCOM9Viyo=
Name: modules/fullscreenObserver.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: dA4uF/PyD4eIAjQaZ1RIIQ==
-SHA1-Digest: ENKlU1ETpeEMx47y4xvTsSltvtw=
+MD5-Digest: TKVwSD0v1bAX/oWKo8OerA==
+SHA1-Digest: cc6D7hos4bGfa5ReVduq0YkLnWI=
Name: modules/fullTooltip.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: OTHa0q1gsOZFgz5uOQOE0Q==
-SHA1-Digest: SAU4UbMLDt9SVI9lrj/dfSoXe4k=
+MD5-Digest: FoqOnzIGy6E7x19QU0hQFQ==
+SHA1-Digest: 90q+tMYpgfjZ5gI8NgtY/zurn8E=
Name: modules/groupTab.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: NL5i97YRH+b+XpG22i8tIA==
-SHA1-Digest: qefrneMChMj4kmaCaq19QCg/BqM=
+MD5-Digest: mLv7QoeDW18xj5Qr0oFy3Q==
+SHA1-Digest: Q5YR/wKCEBtik8DUl+kY7AFfd8c=
Name: modules/pseudoTreeBuilder.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: KsauIXOH18MRG4mEplXZfw==
-SHA1-Digest: 7EaG3t5WJWOobr8LTS9nX/ulAoI=
+MD5-Digest: lOXZb5hQEp7AKAt5nQPr8A==
+SHA1-Digest: jFpw99/71Tjjz9Yg81LVDPqWJPM=
Name: modules/ReferenceCounter.js
Digest-Algorithms: MD5 SHA1
@@ -458,13 +468,18 @@ SHA1-Digest: KwYUQNA0W5ensPrOgCQeR2NRGm4=
Name: modules/tabAttributesObserver.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: ASIvZ3RBvp7ujNIxUhHjhA==
-SHA1-Digest: E3qycu7EJPrhOGIYeCcsiHlDq/A=
+MD5-Digest: GnqU1In8Jw/2jscAyXXGyg==
+SHA1-Digest: a4KpeD2z5f3xYaa//UQGtAA5+j0=
Name: modules/tabbarDNDObserver.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: Af1MrXXUChYdrEcE83+ljA==
-SHA1-Digest: jzjPtaYbneiJQrIL86DEi8H0qCQ=
+MD5-Digest: SVM/EuTv3Ybu8nxvHnuC2Q==
+SHA1-Digest: jKHCxKjOpz2CQJK2gzwifuh+Uec=
+
+Name: modules/tabContentsObserver.js
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: Mx8Cw+iPLWSjkNjv10xCXg==
+SHA1-Digest: XZJFvYTu9pPIFV+zY9hH2IJsTKM=
Name: modules/tabpanelDNDObserver.js
Digest-Algorithms: MD5 SHA1
@@ -478,13 +493,13 @@ SHA1-Digest: QRODHmwaRkX+b/zrhPVckxz7kf4=
Name: modules/utils.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: Evsu0Jey/gxHQtysi3qW9w==
-SHA1-Digest: z+FPUT6tjjGfA52pyzkH0LPYwB0=
+MD5-Digest: MPLBmR6Rg3wF6+6R5yAEZw==
+SHA1-Digest: 1jMd3iV7CwXwLgjmhzjCJ2Sd5BM=
Name: modules/window.js
Digest-Algorithms: MD5 SHA1
-MD5-Digest: 2YhxOObDBT3JeYp0wn4Y9Q==
-SHA1-Digest: VhNri9EbLd5snZIeuxlX5G5CuIM=
+MD5-Digest: /T5G3EZnKKl1v+Gs2/xLsg==
+SHA1-Digest: mjDJSrMcZLOjZk+pWIxl91kXSw4=
Name: modules/lib/animationManager.js
Digest-Algorithms: MD5 SHA1
@@ -573,13 +588,13 @@ SHA1-Digest: DvaxcjAmPsnt7a1LFCcI+kZ8O4U=
Name: skin/classic/treestyletab/group.css
Digest-Algorithms: MD5 SHA1
-MD5-Digest: 90uxLtKKwShXcpxAlDs44A==
-SHA1-Digest: z7qNzCAhtrmIXtkGllbGhDnXKDg=
+MD5-Digest: BjIr5GS7yRoBH6Ki7jcDzg==
+SHA1-Digest: 5BZvSzT495FHylk38Y/+5t82t5E=
Name: skin/classic/treestyletab/license.txt
Digest-Algorithms: MD5 SHA1
-MD5-Digest: YNMSU+FEmPbD4l7BlE+1eg==
-SHA1-Digest: SkZhMKbeatV48RFx9AROoyuLalc=
+MD5-Digest: Tc+NDhBc7EP4cr5OqQGQyQ==
+SHA1-Digest: TLhlpxf44EXADPU56xRsRroxdo4=
Name: skin/classic/treestyletab/Linux-base.css
Digest-Algorithms: MD5 SHA1
@@ -598,8 +613,8 @@ SHA1-Digest: qeeZLagzbORE5b8b1TAxnZVS998=
Name: skin/classic/treestyletab/pseudo-tree.css
Digest-Algorithms: MD5 SHA1
-MD5-Digest: vladq5shyYibE7GNT5fh0Q==
-SHA1-Digest: oS++SxHpJBVwPdVbO7VHkoGDom4=
+MD5-Digest: YpzbGadA5uvjsoP1UfTk1g==
+SHA1-Digest: lRJLbWJTt07wa9FVOvoH+717+po=
Name: skin/classic/treestyletab/tmp.css
Digest-Algorithms: MD5 SHA1
@@ -613,8 +628,8 @@ SHA1-Digest: /CcGFdIzQT8ebf8twW9s6P1rRRI=
Name: skin/classic/treestyletab/ui-base.css
Digest-Algorithms: MD5 SHA1
-MD5-Digest: f7hWW6ka4HhJp2x4iDlIrw==
-SHA1-Digest: SBpgkKqiRMt63i0rHc+TUMJoo1o=
+MD5-Digest: 4J55NfuxfInmG+yrwyWLXg==
+SHA1-Digest: 3R9fRWUS30aMN2OlqohDOhKrTnY=
Name: skin/classic/treestyletab/WINNT-base.css
Digest-Algorithms: MD5 SHA1
@@ -633,8 +648,8 @@ SHA1-Digest: OeNgpLNuSgMsZsZ2yp1YXdy3Fg8=
Name: skin/classic/treestyletab/metal/base.css
Digest-Algorithms: MD5 SHA1
-MD5-Digest: VOvt6P5FBvR/oN9iUdQxtQ==
-SHA1-Digest: i2FdF8PL0OCo1dgAI9S+zJmcKn8=
+MD5-Digest: TNk9iR8Q3ipTt8YGmNsffQ==
+SHA1-Digest: 1PFGo316AmQuindR0mhEfcHIq2I=
Name: skin/classic/treestyletab/metal/Darwin.css
Digest-Algorithms: MD5 SHA1
@@ -738,13 +753,13 @@ SHA1-Digest: VNJPj9nckqPyRb2Ff3HWiGPQE58=
Name: skin/classic/treestyletab/sidebar/sidebar.css
Digest-Algorithms: MD5 SHA1
-MD5-Digest: xgizmjMioe0U8jjR60gvCA==
-SHA1-Digest: cb+98YrSrq/rVbSDoYhKTVwMKQw=
+MD5-Digest: KDhvyIF+hdzOv2Y+0HhMyg==
+SHA1-Digest: Hat43VvEtekC4PdBU3rxCdoK6hE=
Name: skin/classic/treestyletab/square/base.css
Digest-Algorithms: MD5 SHA1
-MD5-Digest: 7elXQXx/AV+21AEq+84dAw==
-SHA1-Digest: T7j8PUzg8peCmHWYmY26cyrDi2w=
+MD5-Digest: 86fdJZscRoUZHtV5iyvicw==
+SHA1-Digest: Le6rdBYbmghJePZWLTxtaPwFTqk=
Name: skin/classic/treestyletab/square/Darwin.css
Digest-Algorithms: MD5 SHA1
@@ -803,8 +818,8 @@ SHA1-Digest: uJCYdd6cnRl0V0Vt+sFUFWmD4oE=
Name: skin/classic/treestyletab/square/vertigo.css
Digest-Algorithms: MD5 SHA1
-MD5-Digest: x5bWTAcM++UPB3EJFA3J3A==
-SHA1-Digest: 08KztOOzgQ0M+D/3ayVlOxnPaw4=
+MD5-Digest: YLJ7vvT+Tx9/UICfK4wVJQ==
+SHA1-Digest: kb6KoccqQfUIWkC1Dt3Ma3P7jAQ=
Name: skin/classic/treestyletab/twisty/twisty-modern-b-l.png
Digest-Algorithms: MD5 SHA1
diff --git a/META-INF/mozilla.rsa b/META-INF/mozilla.rsa
index 8a26cc4..3979352 100644
Binary files a/META-INF/mozilla.rsa and b/META-INF/mozilla.rsa differ
diff --git a/META-INF/mozilla.sf b/META-INF/mozilla.sf
index 36df67f..ad31b7f 100644
--- a/META-INF/mozilla.sf
+++ b/META-INF/mozilla.sf
@@ -1,4 +1,4 @@
Signature-Version: 1.0
-MD5-Digest-Manifest: T08tnhNEZ1g5FL/L2ZxHZg==
-SHA1-Digest-Manifest: iNKONgCoicdK/P5/AHA1K9bV7zQ=
+MD5-Digest-Manifest: oVOnv2S1lDvsplClJaljyQ==
+SHA1-Digest-Manifest: qt6nGW08/CsBc6g0DFWFIZjhT2s=
diff --git a/content/treestyletab/bookmarksOverlay.js b/content/treestyletab/bookmarksOverlay.js
index 91e51d0..bedc225 100644
--- a/content/treestyletab/bookmarksOverlay.js
+++ b/content/treestyletab/bookmarksOverlay.js
@@ -1,221 +1,14 @@
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
+Components.utils.import('resource://treestyletab-modules/bookmark.js', {});
XPCOMUtils.defineLazyModuleGetter(this,
'TreeStyleTabUtils', 'resource://treestyletab-modules/utils.js');
(function() {
let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {});
let { inherit } = Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm', {});
-var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
-
- get BookmarksService() {
- if (!this._BookmarksService) {
- this._BookmarksService = Components
- .classes['@mozilla.org/browser/nav-bookmarks-service;1']
- .getService(Components.interfaces.nsINavBookmarksService);
- }
- return this._BookmarksService;
- },
- _BookmarksService : null,
-
-
- beginAddBookmarksFromTabs : function TSTBMService_beginAddBookmarksFromTabs(aTabs) /* PUBLIC API */
- {
- if (this._observing) return;
- this._observing = true;
-
- aTabs = this.cleanUpTabsArray(aTabs);
-
- this._addingBookmarks = [];
- this._addingBookmarkTreeStructure = aTabs.map(function(aTab) {
- var parent = this.getParentTab(aTab);
- return aTabs.indexOf(parent);
- }, this);
-
- this.BookmarksService.addObserver(this, false);
- },
-
- endAddBookmarksFromTabs : function TSTBMService_endAddBookmarksFromTabs() /* PUBLIC API */
- {
- if (!this._observing) return;
- this._observing = false;
-
- this.BookmarksService.removeObserver(this);
- this.handleNewBookmarksFromTabs(this._addingBookmarks, this._addingBookmarkTreeStructure);
- this._addingBookmarks = [];
- this._addingBookmarkTreeStructure = [];
- },
-
- handleNewBookmarksFromTabs : function TSTBMService_handleNewBookmarksFromTabs(aBookarmks, aTreeStructure)
- {
- // this is adding bookmark folder from tabs, so ignroe the first item!
- if (
- aBookarmks.length == aTreeStructure.length+1 &&
- this.BookmarksService.getItemType(aBookarmks[0].id) == this.BookmarksService.TYPE_FOLDER
- ) {
- aBookarmks.shift();
- }
- else if (aBookarmks.length != aTreeStructure.length) {
- return;
- }
-
- for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
- {
- let item = aBookarmks[i];
- item.position = this.BookmarksService.getItemIndex(item.id);
- }
- aBookarmks.sort(function(aA, aB) {
- return aA.position - aB.position;
- });
-
- for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
- {
- let item = aBookarmks[i];
- if (this.BookmarksService.getItemType(item.id) != this.BookmarksService.TYPE_BOOKMARK)
- continue;
-
- let uri = this.BookmarksService.getBookmarkURI(item.id);
- if (/^about:treestyletab-group\b/.test(uri.spec)) {
- let title = this.BookmarksService.getItemTitle(item.id);
- let folderId = this.BookmarksService.createFolder(item.parent, title, item.position);
- this.BookmarksService.removeItem(item.id);
- item.id = folderId;
- item.isFolder = true;
- }
-
- let index = aTreeStructure[i];
- let parent = index > -1 ? aBookarmks[index] : null ;
- if (parent && (parent.folder || parent).isFolder) {
- let folder = parent.isFolder ? parent : parent.folder ;
- this.BookmarksService.moveItem(item.id, folder.id, -1);
- item.folder = folder;
- }
- if (parent && !parent.isFolder) {
- PlacesUtils.setAnnotationsForItem(item.id, [{
- name : this.kPARENT,
- value : parent ? parent.id : -1,
- expires : PlacesUtils.annotations.EXPIRE_NEVER
- }]);
- }
- }
- },
-
- bookmarkTabSubtree : function TSTBMService_bookmarkTabSubtree(aTabOrTabs)
- {
- var tabs = aTabOrTabs;
- if (!Array.isArray(tabs)) {
- tabs = [aTabOrTabs];
- }
-
- var folderName = (this.isGroupTab(tabs[0], true) || tabs.length == 1) ?
- tabs[0].label :
- null ;
-
- var b = this.getTabBrowserFromChild(tabs[0]);
- var bookmarkedTabs = [];
- for (let i = 0, maxi = tabs.length; i < maxi; i++)
- {
- let tab = tabs[i];
- if (!this.isGroupTab(tab, i == 0)) bookmarkedTabs.push(tab);
- bookmarkedTabs = bookmarkedTabs.concat(b.treeStyleTab.getDescendantTabs(tab));
- }
-
- this.beginAddBookmarksFromTabs(bookmarkedTabs);
- try {
- window['piro.sakura.ne.jp'].bookmarkMultipleTabs.addBookmarkFor(bookmarkedTabs, folderName);
- }
- catch(e) {
- }
- this.endAddBookmarksFromTabs();
- },
- bookmarkTabSubTree : function() { return this.bookmarkTabSubtree.apply(this, arguments); }, // obsolete, for backward compatibility
-
- getParentItem : function TSTBMService_getParentItem(aId)
- {
- if (aId < 0) return -1;
- var annotations = PlacesUtils.getAnnotationsForItem(aId);
- for (let i in annotations)
- {
- if (annotations[i].name != this.kPARENT) continue;
- return parseInt(annotations[i].value);
- }
- return -1;
- },
-
- getTreeStructureFromItems : function TSTBMService_getTreeStructureFromItems(aIDs, aDefaultParentID)
- {
- /* this returns a result same to getTreeStructureFromTabs().
- [A] => -1 (parent is not in this tree)
- [B] => 0 (parent is 1st item in this tree)
- [C] => 0 (parent is 1st item in this tree)
- [D] => 2 (parent is 2nd in this tree)
- [E] => -1 (parent is not in this tree, and this creates another tree)
- [F] => 0 (parent is 1st item in this another tree)
- */
- if (aDefaultParentID === void(0))
- aDefaultParentID = -1;
-
- /* Get array of parents. The index becomes to -1,
- if there is NO PARENT or the parent is THE TAB ITSELF. */
- var treeStructure = aIDs.map(function(aId, aIndex) {
- let id = this.getParentItem(aId);
- let index = aIDs.indexOf(id);
- return index >= aIndex ? aDefaultParentID : index ;
- }, this);
-
- /* Correct patterns like:
- [TabA]
- [TabB] - this has no parent
- [TabC] - TabA's child
- to:
- [TabA]
- [TabB]
- [TabC]
- */
- treeStructure = treeStructure.reverse();
- treeStructure = treeStructure.map(function(aPosition, aIndex) {
- if (aIndex > 0 &&
- aIndex < treeStructure.length-1 &&
- aPosition < 0) {
- aPosition = treeStructure[aIndex-1];
- }
- return aPosition;
- });
- treeStructure = treeStructure.reverse();
-
- return this.cleanUpTreeStructureArray(treeStructure, aDefaultParentID);
- },
-
- // based on PlacesUtils.getURLsForContainerNode()
- getItemIdsForContainerNode : function TSTBMService_getItemIdsForContainerNode(aNode)
- {
- var ids = [];
- if (!aNode || !PlacesUtils.nodeIsContainer(aNode)) return ids;
-
- var root = aNode;
- if ('getContainerNodeWithOptions' in PlacesUtils) {
- root = PlacesUtils.getContainerNodeWithOptions(root, false, true);
- }
- var oldViewer = root.parentResult.viewer;
- var wasOpen = root.containerOpen;
- if (!wasOpen) {
- if (oldViewer)
- root.parentResult.viewer = null;
- root.containerOpen = true;
- }
- for (let i = 0, maxi = root.childCount; i < maxi; ++i)
- {
- let child = root.getChild(i);
- if (PlacesUtils.nodeIsURI(child)) ids.push(child.itemId || -1);
- }
- if (!wasOpen) {
- root.containerOpen = false;
- if (oldViewer)
- root.parentResult.viewer = oldViewer;
- }
- return ids;
- },
+var TreeStyleTabBookmarksUIService = inherit(TreeStyleTabService, {
preInit : function TSTBMService_preInit()
{
window.addEventListener('load', this, false);
@@ -231,250 +24,35 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
window.addEventListener('unload', this, false);
ReferenceCounter.add('window,unload,TSTBMService,false');
- if (!('PlacesUIUtils' in window)) return;
-
- if (!PlacesUIUtils.__treestyletab__done) {
- var ns = Components.utils.import('resource:///modules/PlacesUIUtils.jsm', {});
- var sv = this;
- with (ns) {
-
- {
- let method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU__openTabset) ?
- 'TU__openTabset' :
- '_openTabset';
- TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
- var patched = eval(aName+' = '+aSource.replace(
- /(function[^\(]*\([^\)]+)(\))/,
- '$1, aFolderTitle$2'
- ).replace(
- '{',
- '{ var TSTTreeStructure = null, TSTPreviousTabs, TSTTreeStructureApplied = true, TSTOpenGroupBookmarkBehavior;'
- ).replace(
- 'var urls = [];',
- '$& var ids = [];'
- ).replace(
- 'urls.push(item.uri);',
- 'if (item.uri) { $& ids.push(item.id); }'
- ).replace(
- 'this.markPageAsTyped(item.uri);',
- 'if (item.uri) { $& }'
- ).replace(
- /(browserWindow\.(?:getBrowser\(\)|gBrowser)\.loadTabs\([^;]+\);)/,
- 'var TSTResult = browserWindow.TreeStyleTabBookmarksService.handleTabsOpenProcess(where, aEvent, browserWindow, ids, urls, aFolderTitle);\n' +
- 'TSTTreeStructure = TSTResult.treeStructure;\n' +
- 'TSTPreviousTabs = TSTResult.previousTabs;\n' +
- 'TSTTreeStructureApplied = TSTResult.treeStructureApplied;\n' +
- 'TSTOpenGroupBookmarkBehavior = TSTResult.behavior;\n' +
- 'if (typeof replaceCurrentTab != "undefined")\n' +
- ' replaceCurrentTab = TSTResult.replaceCurrentTab;\n' +
- '$1'
- ).replace(
- /(\}\)?)$/,
- ' if (TSTTreeStructure && TSTPreviousTabs) {\n' +
- ' let tabs = browserWindow.TreeStyleTabService.getNewTabsFromPreviousTabsInfo(browserWindow.gBrowser, TSTPreviousTabs);\n' +
- ' if (!TSTTreeStructureApplied)\n' +
- ' browserWindow.TreeStyleTabService.applyTreeStructureToTabs(tabs, TSTTreeStructure, TSTOpenGroupBookmarkBehavior & browserWindow.TreeStyleTabBookmarksService.kGROUP_BOOKMARK_EXPAND_ALL_TREE);\n' +
- ' if (!loadInBackground) {\n' +
- ' browserWindow.setTimeout(function() {\n' +
- ' browserWindow.gBrowser.treeStyleTab.scrollToTabs(tabs);\n' +
- ' }, browserWindow.gBrowser.treeStyleTab.collapseDuration); // start scroll after expanding animation is finished\n' +
- ' }\n' +
- ' }\n' +
- '$1'
- ));
- if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
- window[method] = patched;
- return patched;
- }, 'TreeStyleTab');
- }
-
- {
- let method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU_openContainerNodeInTabs) ?
- 'TU_openContainerNodeInTabs' :
- 'openContainerNodeInTabs';
- TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
- var patched = eval(aName+' = '+aSource.replace(
- /(this\._openTabset\([^\)]+)(\))/,
- '{\n' +
- ' let w = "_getTopBrowserWin" in this ?\n' +
- ' this._getTopBrowserWin() :\n' +
- ' "_getCurrentActiveWin" in this ?\n' +
- ' this._getCurrentActiveWin() :\n' +
- ' window;\n' +
- ' let nodes = w.TreeStyleTabBookmarksService.getItemIdsForContainerNode(aNode);\n' +
- ' for (let i in nodes) {\n' +
- ' urlsToOpen[i].id = nodes[i];\n' +
- ' }\n' +
- '}\n' +
- '$1, aNode.title$2'
- ));
- if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
- window[method] = patched;
- return patched;
- }, 'TreeStyleTab');
- }
-
- {
- let method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU_openURINodesInTabs) ?
- 'TU_openURINodesInTabs' :
- 'openURINodesInTabs';
- TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
- var patched = eval(aName+' = '+aSource.replace(
- '{',
- '{\n' +
- ' var TSTBS, TSTUtils;\n' +
- ' {\n'+
- ' let w = "_getTopBrowserWin" in this ?\n' +
- ' this._getTopBrowserWin() :\n' +
- ' "_getCurrentActiveWin" in this ?\n' +
- ' this._getCurrentActiveWin() :\n' +
- ' window;\n' +
- ' TSTBS = w.TreeStyleTabBookmarksService;\n' +
- ' TSTUtils = w.TreeStyleTabUtils;\n' +
- ' PlacesUtils = w.PlacesUtils;\n' +
- ' }'
- ).replace(
- 'uri: aNodes[i].uri,',
- 'id: aNodes[i].itemId, $&'
- ).replace(
- /(this\._openTabset\([^\)]+)(\))/,
- '$1,\n' +
- ' TSTUtils.treeBundle\n' +
- ' .getFormattedString(\n' +
- ' PlacesUtils.nodeIsBookmark(aNodes[0]) ?\n' +
- ' "openSelectedPlaces.bookmarks" :\n' +
- ' "openSelectedPlaces.history",\n' +
- ' [aNodes[0].title, aNodes.length]\n' +
- ' )\n' +
- '$2'
- ));
- if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
- window[method] = patched;
- return patched;
- }, 'TreeStyleTab');
- }
-
- PlacesUIUtils.__treestyletab__done = true;
-
- } // end of with
- }
-
if ('PlacesCommandHook' in window && 'bookmarkCurrentPages' in PlacesCommandHook) {
// Bookmark All Tabs
- TreeStyleTabUtils.doPatching(PlacesCommandHook.bookmarkCurrentPages, 'PlacesCommandHook.bookmarkCurrentPages', function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- '{',
- '{\n' +
- ' TreeStyleTabBookmarksService.beginAddBookmarksFromTabs((function() {\n' +
- ' var tabs = [];\n' +
- ' var seen = {};\n' +
- ' var allTabs = getBrowser().mTabContainer.childNodes;\n' +
- ' for (let i = 0, maxi = allTabs.length; i < maxi; i++)\n' +
- ' {\n' +
- ' let tab = allTabs[i];\n' +
- ' let uri = tab.linkedBrowser.currentURI.spec;\n' +
- ' if (uri in seen) continue;\n' +
- ' seen[uri] = true;\n' +
- ' tabs.push(tab);\n' +
- ' }\n' +
- ' return tabs;\n' +
- ' })());\n' +
- ' try {'
- ).replace(
- /(\}\)?)$/,
- ' }\n' +
- ' catch(e) {\n' +
- ' }\n' +
- ' TreeStyleTabBookmarksService.endAddBookmarksFromTabs();\n' +
- '$1'
- ));
- }, 'TreeStyleTab');
- }
- },
- handleTabsOpenProcess : function TSTBMService_handleTabsOpenProcess(aWhere, aEvent, aBrowserWindow, aIDs, aURLs, aFolderTitle)
- {
- var result = {
- behavior : undefined,
- treeStructure : undefined,
- previousTabs : undefined,
- treeStructureApplied : false
- };
- if (
- aEvent.type != 'drop' &&
- aWhere.indexOf('tab') != 0 &&
- aEvent.target.id != 'placesContext_openContainer:tabs' &&
- aEvent.target.id != 'placesContext_openLinks:tabs' &&
- aEvent.target != aEvent.target.parentNode._endOptOpenAllInTabs &&
- aEvent.target.getAttribute('openInTabs') != 'true'
- )
- return result;
-
- var sv = aBrowserWindow.TreeStyleTabBookmarksService;
- result.behavior = sv.openGroupBookmarkBehavior();
- if (result.behavior & sv.kGROUP_BOOKMARK_SUBTREE) {
- let treeStructure = result.behavior & sv.kGROUP_BOOKMARK_DONT_RESTORE_TREE_STRUCTURE ?
- null :
- sv.getTreeStructureFromItems(aIDs) ;
- if (treeStructure) {
- let parentTabs = treeStructure.filter(function(aParent) {
- return aParent < 0;
- });
- let haveMultipleTrees = parentTabs.length != treeStructure.length;
- if (result.behavior & sv.kGROUP_BOOKMARK_USE_DUMMY) {
- let parentCount = 0;
- let childCount = 0;
- for (let i in treeStructure) {
- if (treeStructure[i] == -1)
- parentCount++;
- else
- childCount++;
- }
- if (
- parentCount > 1 &&
- (
- result.behavior & sv.kGROUP_BOOKMARK_USE_DUMMY_FORCE ||
- // when there is any orphan, then all of parents and orphans should be grouped under a dummy tab.
- childCount < parentCount
- )
- ) {
- aIDs.unshift(-1);
- treeStructure = sv.getTreeStructureFromItems(aIDs, 0);
- aURLs.unshift(sv.getGroupTabURI({
- title: aFolderTitle,
- temporary: TreeStyleTabUtils.getTreePref('openGroupBookmark.temporaryGroup')
- }));
+ PlacesCommandHook.__treestyletab__bookmarkCurrentPages = PlacesCommandHook.bookmarkCurrentPages;
+ PlacesCommandHook.bookmarkCurrentPages = function(...aArgs) {
+ TreeStyleTabBookmarksService.beginAddBookmarksFromTabs((function() {
+ var tabs = [];
+ var seen = {};
+ var allTabs = gBrowser.mTabContainer.childNodes;
+ for (let i = 0, maxi = allTabs.length; i < maxi; i++)
+ {
+ let tab = allTabs[i];
+ let uri = tab.linkedBrowser.currentURI.spec;
+ if (uri in seen)
+ continue;
+ seen[uri] = true;
+ tabs.push(tab);
}
+ return tabs;
+ })());
+ try {
+ return this.__treestyletab__bookmarkCurrentPages.apply(this, aArgs);
}
- else if (!haveMultipleTrees) {
- // make the first item parent.
- treeStructure = treeStructure.map(function(aParent, aIndex) {
- if (aIndex == 0)
- return aParent;
- if (aParent < 0)
- return 0;
- return aParent;
- });
+ finally {
+ TreeStyleTabBookmarksService.endAddBookmarksFromTabs();
}
- }
-
- result.treeStructure = treeStructure;
- result.previousTabs = aBrowserWindow.TreeStyleTabService.getTabsInfo(aBrowserWindow.gBrowser);
-
- if (TreeStyleTabUtils.getTreePref('compatibility.TMP') &&
- 'TMP_Places' in aBrowserWindow &&
- 'openGroup' in aBrowserWindow.TMP_Places) {
- result.treeStructureApplied = false;
- }
- else {
- sv.readyToOpenNewTabGroup(null, treeStructure, result.behavior & sv.kGROUP_BOOKMARK_EXPAND_ALL_TREE);
- result.treeStructureApplied = true;
- }
+ };
}
- return result;
},
-
-
destroy : function TSTBMService_destroy()
{
window.removeEventListener('unload', this, false);
@@ -483,22 +61,6 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
ReferenceCounter.remove('window,EVENT_TYPE_TABS_DROP,TSTBMService,false');
},
- // observer for nsINavBookmarksService
- onItemAdded : function TSTBMService_onItemAdded(aID, aFolderID, aPosition)
- {
- this._addingBookmarks.push({
- id : aID,
- parent : aFolderID
- });
- },
- onItemRemoved : function TSTBMService_onItemRemoved(aID, aFolderID, aPosition) {},
- onItemMoved : function TSTBMService_onItemMoved(aID, aFolderID, aPosition) {},
- onItemChanged : function TSTBMService_onItemChanged(aID, aChange, aIsAnnotation, aNewValue) {},
- onItemVisited : function TSTBMService_onItemVisited(aID, aHistoryID, aDate) {},
- onBeginUpdateBatch : function TSTBMService_onBeginUpdateBatch() {},
- onEndUpdateBatch : function TSTBMService_onEndUpdateBatch() {},
-
-
_onTabsDrop : function TSTBMService_onTabsDrop(aEvent)
{
var tabs = aEvent.detail.tabs;
@@ -533,7 +95,7 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
});
-TreeStyleTabBookmarksService.preInit();
+TreeStyleTabBookmarksUIService.preInit();
-window.TreeStyleTabBookmarksService = TreeStyleTabBookmarksService;
+window.TreeStyleTabBookmarksUIService = TreeStyleTabBookmarksUIService;
})();
diff --git a/content/treestyletab/bookmarksOverlayEditable.js b/content/treestyletab/bookmarksOverlayEditable.js
index aa5b429..38f89f0 100644
--- a/content/treestyletab/bookmarksOverlayEditable.js
+++ b/content/treestyletab/bookmarksOverlayEditable.js
@@ -1,11 +1,21 @@
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this,
'TreeStyleTabUtils', 'resource://treestyletab-modules/utils.js');
+XPCOMUtils.defineLazyModuleGetter(this,
+ 'TreeStyleTabBookmarksService', 'resource://treestyletab-modules/bookmark.js');
(function() {
let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {});
let { inherit } = Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm', {});
-var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService, {
+
+function log(...aArgs) {
+ TreeStyleTabUtils.log.apply(TreeStyleTabUtils, ['bookmark'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ TreeStyleTabUtils.logWithStackTrace.apply(TreeStyleTabUtils, ['bookmark'].concat(aArgs));
+}
+
+var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksUIService, {
instantApply : false,
canceled : false,
@@ -44,7 +54,8 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
init : function TSTBMEditable_init()
{
- if (this.isCreatingMultipleBookmarksInFolder) return;
+ if (this.isCreatingMultipleBookmarksInFolder)
+ return;
// main browser window
if ('StarUI' in window) {
@@ -56,7 +67,7 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
StarUI.__treestyletab__quitEditMode = StarUI.__treestyletab__quitEditMode || StarUI.quitEditMode;
StarUI.quitEditMode = function(...args) {
- TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);
+ TreeStyleTabBookmarksServiceEditable.saveParentFor(gEditItemOverlay.itemId);
return this.__treestyletab__quitEditMode.apply(this, args);
};
@@ -69,12 +80,37 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
// Bookmarks Property dialog
if ('BookmarkPropertiesPanel' in window) {
- TreeStyleTabUtils.doPatching(BookmarkPropertiesPanel._endBatch, 'BookmarkPropertiesPanel._endBatch', function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- /(PlacesUtils\.transactionManager\.endBatch\([^)]*\);)/,
- '$1 TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId, true);'
- ));
- }, 'TreeStyleTab');
+ BookmarkPropertiesPanel.__treestyletab__onDialogAccept = BookmarkPropertiesPanel.onDialogAccept;
+ BookmarkPropertiesPanel.onDialogAccept = function(...aArgs) {
+ try {
+ TreeStyleTabBookmarksServiceEditable.saveParentFor(gEditItemOverlay.itemId, true);
+ }
+ catch(e) {
+ log(e);
+ }
+ return this.__treestyletab__onDialogAccept.apply(this, aArgs);
+ };
+
+ BookmarkPropertiesPanel.__treestyletab__endBatch = BookmarkPropertiesPanel._endBatch;
+ BookmarkPropertiesPanel._endBatch = function(...aArgs) {
+ var id = this.__treestyletab__itemId || gEditItemOverlay.itemId;
+ log('BookmarkPropertiesPanel._endBatch for '+id);
+ var batching = this._batching;
+ var result = this.__treestyletab__endBatch.apply(this, aArgs);
+ if (id >= 0 && !batching && !this._batching) {
+ this._batching = true;
+ try {
+ TreeStyleTabBookmarksServiceEditable.saveParentFor(id, true);
+ }
+ catch(e) {
+ log(e);
+ }
+ finally {
+ this._batching = false;
+ }
+ }
+ return result;
+ };
}
// Places Organizer (Library)
@@ -119,42 +155,24 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
document.getElementById('treestyletab-parent-label').setAttribute('value', TreeStyleTabUtils.treeBundle.getString('bookmarkProperty.parent.label'));
this.blankItem.setAttribute('label', TreeStyleTabUtils.treeBundle.getString('bookmarkProperty.parent.blank.label'));
- if (Services.vc.compare(Services.appinfo.platformVersion, '40') >= 0) {
- // for Firefox 40 and later, after Bug 951651
- TreeStyleTabUtils.doPatching(gEditItemOverlay.initPanel, 'gEditItemOverlay.initPanel', function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- /(\}\)?)$/,
- ' TreeStyleTabBookmarksServiceEditable.parentRow.collapsed = this._element("keywordRow").collapsed && this._element("folderRow").collapsed;\n' +
- ' if (!TreeStyleTabBookmarksServiceEditable.parentRow.collapsed)\n' +
- ' TreeStyleTabBookmarksServiceEditable.initParentMenuList();\n' +
- '$1'
- ));
- }, 'TreeStyleTab');
- }
- else {
- // for Firefox 39 and olders
- TreeStyleTabUtils.doPatching(gEditItemOverlay.initPanel, 'gEditItemOverlay.initPanel', function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- 'if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {',
- '$& TreeStyleTabBookmarksServiceEditable.initParentMenuList();'
- ));
- }, 'TreeStyleTab');
-
- TreeStyleTabUtils.doPatching(gEditItemOverlay._showHideRows, 'gEditItemOverlay._showHideRows', function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- /(\}\)?)$/,
- ' TreeStyleTabBookmarksServiceEditable.parentRow.collapsed = this._element("keywordRow").collapsed && this._element("folderRow").collapsed;\n' +
- '$1'
- ));
- }, 'TreeStyleTab');
- }
-
- TreeStyleTabUtils.doPatching(gEditItemOverlay.onItemMoved, 'gEditItemOverlay.onItemMoved', function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- '{',
- '$& if (aNewParent == this._getFolderIdFromMenuList()) TreeStyleTabBookmarksServiceEditable.initParentMenuList();'
- ));
- }, 'TreeStyleTab');
+ gEditItemOverlay.__treestyletab__initPanel = gEditItemOverlay.initPanel;
+ gEditItemOverlay.initPanel = function(...aArgs) {
+ var result = this.__treestyletab__initPanel.apply(this, aArgs);
+ TreeStyleTabBookmarksServiceEditable.parentRow.collapsed = (
+ this._element('keywordRow').collapsed &&
+ this._element('folderRow').collapsed
+ );
+ if (!TreeStyleTabBookmarksServiceEditable.parentRow.collapsed)
+ TreeStyleTabBookmarksServiceEditable.initParentMenuList();
+ return result;
+ };
+
+ gEditItemOverlay.__treestyletab__onItemMoved = gEditItemOverlay.onItemMoved;
+ gEditItemOverlay.onItemMoved = function(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex, aItemType, ...aArgs) {
+ if (aNewParent == this._getFolderIdFromMenuList())
+ TreeStyleTabBookmarksServiceEditable.initParentMenuList();
+ return this.__treestyletab__onItemMoved.apply(this, [aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex, aItemType].concat(aArgs));
+ };
this.editUIInitialized = true;
},
@@ -255,7 +273,7 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
},
_createSiblingsFragmentInternal : function TSTBMEditable_createSiblingsFragmentInternal(aCurrentItem, aItems, aCallback)
{
- var treeStructure = this.getTreeStructureFromItems(aItems);
+ var treeStructure = TreeStyleTabBookmarksService.getTreeStructureFromItems(aItems);
var currentIndex = aItems.indexOf(aCurrentItem);
var selected = treeStructure[currentIndex];
@@ -327,13 +345,20 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
},
_getSiblingItemsIterator : function TSTBMEditable_getSiblingItemsIterator(aId)
{
- return this._getItemsInFolderIterator(PlacesUtils.bookmarks.getFolderIdForItem(aId));
+ var folderId = -1;
+ try {
+ folderId = PlacesUtils.bookmarks.getFolderIdForItem(aId);
+ }
+ catch(e) {
+ }
+ return this._getItemsInFolderIterator(folderId);
},
saveParentFor : function TSTBMEditable_saveParentFor(aId, aJustNow)
{
var newParentId = parseInt(this.menulist.value || -1);
- if (this.canceled || newParentId == this.getParentItem(aId)) return;
+ if (this.canceled || newParentId == TreeStyleTabBookmarksService.getParentItem(aId))
+ return;
var itemsIterator = this._getSiblingItemsIterator(aId);
var items = [];
@@ -350,7 +375,7 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
},
_saveParentForInternal : function TSTBMEditable_saveParentForInternal(aId, aNewParentId, aItems)
{
- var treeStructure = this.getTreeStructureFromItems(aItems);
+ var treeStructure = TreeStyleTabBookmarksService.getTreeStructureFromItems(aItems);
var parentIndex = aItems.indexOf(aNewParentId);
var newIndex;
diff --git a/content/treestyletab/config.xul b/content/treestyletab/config.xul
index 7c06f7c..c85a27d 100644
--- a/content/treestyletab/config.xul
+++ b/content/treestyletab/config.xul
@@ -750,6 +750,7 @@
oncommand="syncEnabledState(this, this.value == 0);"
sync-enabled-state-targets="extensions.treestyletab.closeRootBehavior-check">
<radio value="2" label="&config.closeParentBehavior.close;"/>
+ <radio value="5" label="&config.closeParentBehavior.replaceWithGroupTab;"/>
<radio value="3" label="&config.closeParentBehavior.promoteFirst;"/>
<radio value="0" label="&config.closeParentBehavior.promoteAll;"/>
<hbox align="center">
diff --git a/content/treestyletab/license.txt b/content/treestyletab/license.txt
index 62dcd4b..c35e8f1 100644
--- a/content/treestyletab/license.txt
+++ b/content/treestyletab/license.txt
@@ -14,7 +14,7 @@ License.
The Original Code is the Tree Style Tab.
The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
-Portions created by the Initial Developer are Copyright (C) 2007-2014
+Portions created by the Initial Developer are Copyright (C) 2007-2016
the Initial Developer. All Rights Reserved.
Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
diff --git a/content/treestyletab/treestyletab.css b/content/treestyletab/treestyletab.css
index bae0f28..ecf5c54 100644
--- a/content/treestyletab/treestyletab.css
+++ b/content/treestyletab/treestyletab.css
@@ -447,6 +447,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
margin-right 0.2s ease-out,
margin-top 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
min-width 0.15s ease-out /* for Firefox itself */,
@@ -455,6 +456,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
margin-right 0.2s ease-out,
margin-top 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
min-width 0.15s ease-out /* for Firefox itself */,
@@ -466,6 +468,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
margin-right 0.2s ease-out,
margin-top 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
min-width 0.15s ease-out /* for Firefox itself */,
@@ -475,6 +478,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
margin-right 0.2s ease-out,
margin-top 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
min-width 0.15s ease-out /* for Firefox itself */,
@@ -486,6 +490,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
.tabbrowser-tab:not([treestyletab-collapsed-done="true"]) {
-moz-transition: margin-left 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
margin-top 0.2s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
@@ -493,6 +498,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
max-width 0.15s ease-out /* for Firefox itself */;
transition: margin-left 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
margin-top 0.2s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
@@ -503,6 +509,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
.tabbrowser-tab:not([treestyletab-collapsed-done="true"]) {
-moz-transition: margin-left 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
margin-top 0.2s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
@@ -511,6 +518,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
transform 0.2s ease-out /* for Firefox itself */;
transition: margin-left 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
margin-top 0.2s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
@@ -523,6 +531,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
.tabbrowser-tab:not([treestyletab-collapsed-done="true"]) {
-moz-transition: margin-left 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
margin-bottom 0.2s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
@@ -530,6 +539,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
max-width 0.15s ease-out /* for Firefox itself */;
transition: margin-left 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
margin-bottom 0.2s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
@@ -540,6 +550,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
.tabbrowser-tab:not([treestyletab-collapsed-done="true"]) {
-moz-transition: margin-left 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
margin-bottom 0.2s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
@@ -548,6 +559,7 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
transform 0.2s ease-out /* for Firefox itself */;
transition: margin-left 0.15s ease-out,
opacity 0.15s ease-out,
+ outline-color 0.5s ease-out,
margin-bottom 0.2s ease-out,
min-height 0.15s ease-out,
max-height 0.15s ease-out,
diff --git a/content/treestyletab/treestyletab.js b/content/treestyletab/treestyletab.js
index 4b63e06..4dc1cfc 100644
--- a/content/treestyletab/treestyletab.js
+++ b/content/treestyletab/treestyletab.js
@@ -23,7 +23,9 @@
}, false);
ReferenceCounter.add('window,aEvent.type,onDOMContentLoaded,false');
- var ns = {};
- Components.utils.import('resource://treestyletab-modules/window.js', ns);
- new ns.TreeStyleTabWindow(window);
+ var { TreeStyleTabUtils } = Components.utils.import('resource://treestyletab-modules/utils.js', {});
+ window.TreeStyleTabUtils = TreeStyleTabUtils;
+
+ var { TreeStyleTabWindow } = Components.utils.import('resource://treestyletab-modules/window.js', {});
+ new TreeStyleTabWindow(window);
})();
diff --git a/content/treestyletab/treestyletab.xul b/content/treestyletab/treestyletab.xul
index 5b7d51d..6065ef6 100644
--- a/content/treestyletab/treestyletab.xul
+++ b/content/treestyletab/treestyletab.xul
@@ -84,7 +84,7 @@
event.stopPropagation();
this.parentNode.hidePopup();
}"
- multipletab-insertbefore="TreeStyleTabService.evaluateXPath(
+ multipletab-insertbefore="TreeStyleTabUtils.evaluateXPath(
"(descendant::*[starts-with(@id, 'multipletab-context-removeAll') | starts-with(@id, 'context_closeTab')][1] | child::xul:menuitem[last()])/preceding-sibling::xul:menuseparator[1]"
, tabContextMenu, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue"/>
<menuitem id="context-item-removeDescendantTabs"
@@ -107,7 +107,7 @@
label="&context.bookmarkTabSubtree.label;"
accesskey="&context.bookmarkTabSubtree.accesskey;"
oncommand="TreeStyleTabBookmarksService.bookmarkTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
- multipletab-insertafter="TreeStyleTabService.evaluateXPath(
+ multipletab-insertafter="TreeStyleTabUtils.evaluateXPath(
"descendant::*[starts-with(@id, 'context_bookmarkTab')][1] | descendant::*[@command='Browser:BookmarkAllTabs']/preceding-sibling[1]"
, tabContextMenu, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue"/>
diff --git a/content/treestyletab/windowHelper.js b/content/treestyletab/windowHelper.js
index 1b35e03..1d2e301 100644
--- a/content/treestyletab/windowHelper.js
+++ b/content/treestyletab/windowHelper.js
@@ -31,7 +31,7 @@ var TreeStyleTabWindowHelper = {
else
where = TreeStyleTabUtils.prefs.getPref('browser.link.open_newwindow');
}
- TreeStyleTabService.onBeforeBrowserAccessOpenURI(aOpener, where, aContext);
+ TreeStyleTabService.onBeforeBrowserAccessOpenURI(aOpener, where);
return nsBrowserAccess.prototype.__treestyletab__openURI.call(this, aURI, aOpener, aWhere, aContext);
};
@@ -69,25 +69,34 @@ var TreeStyleTabWindowHelper = {
return tab;
};
- [
- 'window.duplicateTab.handleLinkClick',
- 'window.duplicatethistab.handleLinkClick',
- 'window.__treestyletab__highlander__origHandleLinkClick',
- 'window.__splitbrowser__handleLinkClick',
- 'window.__ctxextensions__handleLinkClick',
- 'window.handleLinkClick'
- ].some(function(aName) {
- let func = this._getFunction(aName);
- if (!func || !/^\(?function handleLinkClick/.test(func.toString()))
- return false;
- TreeStyleTabUtils.doPatching(func, aName, function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- /(charset\s*:\s*doc\.characterSet\s*)/,
- '$1, event : event, linkNode : linkNode'
- ));
- }, 'event : event, linkNode : linkNode');
- return true;
- }, this);
+ window.__treestyletab__openLinkIn = window.openLinkIn;
+ window.openLinkIn = function(aUrl, aWhere, aParams, ...aArgs) {
+ if (window.__treestyletab__openLinkIn_extraParams)
+ Object.keys(window.__treestyletab__openLinkIn_extraParams).forEach(function(aKey) {
+ aParams[aKey] = window.__treestyletab__openLinkIn_extraParams[aKey];
+ });
+ try {
+ TreeStyleTabService.onBeforeOpenLinkWithTab(gBrowser.selectedTab, aParams);
+ return window.__treestyletab__openLinkIn.apply(this, [aUrl, aWhere, aParams].concat(aArgs));
+ }
+ finally {
+ delete window.__treestyletab__openLinkIn_extraParams;
+ }
+ };
+
+ window.__treestyletab__handleLinkClick = window.handleLinkClick;
+ window.handleLinkClick = function(aEvent, aHref, aLinkNode, ...aArgs) {
+ window.__treestyletab__openLinkIn_extraParams = {
+ event : aEvent,
+ linkNode : aLinkNode
+ };
+ try {
+ return window.__treestyletab__handleLinkClick.apply(this, [aEvent, aHref, aLinkNode].concat(aArgs));
+ }
+ finally {
+ delete window.__treestyletab__openLinkIn_extraParams;
+ }
+ };
this.overrideExtensionsPreInit(); // windowHelperHacks.js
},
@@ -223,12 +232,6 @@ var TreeStyleTabWindowHelper = {
return BrowserSearch.__treestyletab__loadSearch.call(this, aSearchText, aUseNewTab, aPurpose);
};
- window.__treestyletab__openLinkIn = window.openLinkIn;
- window.openLinkIn = function(aUrl, aWhere, aParams) {
- TreeStyleTabService.onBeforeOpenLinkWithTab(gBrowser.selectedTab, aParams.fromChrome);
- return window.__treestyletab__openLinkIn.call(this, aUrl, aWhere, aParams);
- };
-
[
{ owner: window.permaTabs && window.permaTabs.utils && window.permaTabs.utils.wrappedFunctions,
name: 'window.contentAreaClick' },
@@ -263,21 +266,11 @@ var TreeStyleTabWindowHelper = {
return window.__treestyletab__duplicateTabIn.call(this, aTab, where, delta);
};
- [
- 'permaTabs.utils.wrappedFunctions["window.BrowserHomeClick"]',
- 'window.BrowserHomeClick',
- 'window.BrowserGoHome'
- ].forEach(function(aName) {
- let func = this._getFunction(aName);
- if (!func || !/^\(?function (BrowserHomeClick|BrowserGoHome)/.test(func.toString()))
- return;
- TreeStyleTabUtils.doPatching(func, aName, function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- 'gBrowser.loadTabs(',
- 'TreeStyleTabService.readyToOpenNewTabGroup(gBrowser); $&'
- ));
- }, 'TreeStyleTab');
- }, this);
+ window.__treestyletab__BrowserGoHome = window.BrowserGoHome;
+ window.BrowserGoHome = function(aEvent) {
+ TreeStyleTabService.onBeforeGoHome(aEvent, gBrowser);
+ return window.__treestyletab__BrowserGoHome.call(this, aEvent);
+ };
FeedHandler.__treestyletab__loadFeed = FeedHandler.loadFeed;
FeedHandler.loadFeed = function(aHref, aEvent) {
@@ -455,23 +448,17 @@ var TreeStyleTabWindowHelper = {
return eval(aName+' = '+aSource.replace(
'if (nextTab)',
'(function() {\n' +
- ' if (this.treeStyleTab.hasChildTabs(this.mCurrentTab)) {\n' +
- ' let descendant = this.treeStyleTab.getDescendantTabs(this.mCurrentTab);\n' +
- ' if (descendant.length)\n' +
- ' nextTab = this.treeStyleTab.getNextTab(descendant[descendant.length-1]);\n' +
+ ' let descendants = this.treeStyleTab.getDescendantTabs(this.mCurrentTab);\n' +
+ ' if (descendants.indexOf(nextTab) > -1) {\n' +
+ ' let lastDescendant = this.treeStyleTab.getLastDescendantTab(this.mCurrentTab);\n' +
+ ' nextTab = this.treeStyleTab.getNextVisibleTab(lastDescendant || this.mCurrentTab);\n' +
+ ' }\n' +
+ ' if (this.treeStyleTab.hasChildTabs(nextTab) && this.treeStyleTab.isSubtreeCollapsed(nextTab)) {\n' +
+ ' nextTab = this.treeStyleTab.getLastDescendantTab(nextTab);\n' +
' }\n' +
'}).call(this);' +
'$&'
).replace(
- /(this.moveTabTo\([^;]+\);)/,
- '(function() {\n' +
- ' let descendant = this.treeStyleTab.getDescendantTabs(nextTab);\n' +
- ' if (descendant.length) {\n' +
- ' nextTab = descendant[descendant.length-1];\n' +
- ' }\n' +
- ' $1\n' +
- '}).call(this);'
- ).replace(
'this.moveTabToStart();',
'(function() {\n' +
' this.treeStyleTab.internallyTabMovingCount++;\n' +
@@ -490,6 +477,12 @@ var TreeStyleTabWindowHelper = {
TreeStyleTabUtils.doPatching(b.moveTabBackward, 'b.moveTabBackward', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
+ 'if (previousTab)',
+ '(function() {\n' +
+ ' previousTab = this.treeStyleTab.getPreviousVisibleTab(this.mCurrentTab);\n' +
+ '}).call(this);' +
+ '$&'
+ ).replace(
'this.moveTabToEnd();',
'(function() {\n' +
' this.treeStyleTab.internallyTabMovingCount++;\n' +
@@ -506,24 +499,34 @@ var TreeStyleTabWindowHelper = {
));
}, 'treeStyleTab');
- TreeStyleTabUtils.doPatching(b.loadTabs, 'b.loadTabs', function(aName, aSource) {
- return eval(aName+' = '+aSource.replace(
- 'var tabNum = ',
- 'if (this.treeStyleTab.readiedToAttachNewTabGroup)\n' +
- ' TreeStyleTabService.readyToOpenChildTab(firstTabAdded || this.selectedTab, true);\n' +
- '$&'
- ).replace(
- 'if (!aLoadInBackground)',
- 'if (TreeStyleTabService.checkToOpenChildTab(this))\n' +
- ' TreeStyleTabService.stopToOpenChildTab(this);\n' +
- '$&'
- ).replace(
- 'this.selectedTab = firstTabAdded;',
- 'this.selectedTab = aURIs[0].indexOf("about:treestyletab-group") < 0 ? \n' +
- ' firstTabAdded :\n' +
- ' TreeStyleTabService.getNextTab(firstTabAdded) ;'
- ));
- }, 'TreeStyleTab');
+ b.__treestyletab__loadTabs = b.loadTabs;
+ b.loadTabs = function(aURIs, aLoadInBackground, aReplace, ...aArgs) {
+ if (aReplace)
+ this.treeStyleTab.readyToOpenChildTab(this.selectedTab, true);
+ else if (typeof this.treeStyleTab.nextOpenedTabToBeParent == 'undefined')
+ this.treeStyleTab.nextOpenedTabToBeParent = true;
+
+ var result;
+ var tabs = [];
+ var firstTabAdded;
+ try {
+ tabs = this.treeStyleTab.doAndGetNewTabs((function() {
+ result = this.__treestyletab__loadTabs.apply(this, [aURIs, aLoadInBackground, aReplace].concat(aArgs));
+ }).bind(this));
+ firstTabAdded = tabs[0];
+ }
+ finally {
+ if (!aReplace && firstTabAdded) {
+ this.selectedTab = aURIs[0].indexOf('about:treestyletab-group') == 0 ?
+ TreeStyleTabService.getNextTab(firstTabAdded) :
+ firstTabAdded;
+ }
+ if (this.treeStyleTab.checkToOpenChildTab(this))
+ this.treeStyleTab.stopToOpenChildTab(this);
+ delete this.treeStyleTab.nextOpenedTabToBeParent;
+ }
+ return result;
+ };
TreeStyleTabUtils.doPatching(b._beginRemoveTab, 'b._beginRemoveTab', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
diff --git a/content/treestyletab/windowHelperHacks.js b/content/treestyletab/windowHelperHacks.js
index af5fbb2..5892849 100644
--- a/content/treestyletab/windowHelperHacks.js
+++ b/content/treestyletab/windowHelperHacks.js
@@ -1122,7 +1122,7 @@ TreeStyleTabWindowHelper.overrideExtensionsAfterBrowserInit = function TSTWH_ove
return;
case 'click':
- if (sv.evaluateXPath(
+ if (TreeStyleTabUtils.evaluateXPath(
'ancestor-or-self::*['
+'contains(concat(" ", normalize-space(@class), " "), " textbox-presentation-segment ")'
+']',
diff --git a/defaults/preferences/treestyletab.js b/defaults/preferences/treestyletab.js
index 3c2a2ba..70390fd 100644
--- a/defaults/preferences/treestyletab.js
+++ b/defaults/preferences/treestyletab.js
@@ -68,7 +68,7 @@ pref("extensions.treestyletab.tabbar.invertScrollbar", true);
* This option works only for vertical tab bar.
*/
pref("extensions.treestyletab.tabbar.narrowScrollbar", true);
-pref("extensions.treestyletab.tabbar.narrowScrollbar.size", "10px");
+pref("extensions.treestyletab.tabbar.narrowScrollbar.width", 10);
/**
* On some environments (ex. GNOME3 on Linux), "narrow scrollbar" cannot get
@@ -136,6 +136,11 @@ pref("extensions.treestyletab.tabbar.autoShow.accelKeyDown", true);
pref("extensions.treestyletab.tabbar.autoShow.accelKeyDown.delay", 800);
pref("extensions.treestyletab.tabbar.autoShow.tabSwitch", true);
pref("extensions.treestyletab.tabbar.autoShow.feedback", false);
+pref("extensions.treestyletab.tabbar.autoShow.feedback.opened", true);
+pref("extensions.treestyletab.tabbar.autoShow.feedback.closed", true);
+pref("extensions.treestyletab.tabbar.autoShow.feedback.moved", true);
+pref("extensions.treestyletab.tabbar.autoShow.feedback.selected", true);
+pref("extensions.treestyletab.tabbar.autoShow.feedback.titleChanged", true);
pref("extensions.treestyletab.tabbar.autoShow.feedback.delay", 3000);
/**
* Size of the placeholder for "hidden tab bar".
@@ -343,6 +348,10 @@ pref("extensions.treestyletab.tooltip.maxCount", 10);
* Negative value means "do not show full tooltip".
*/
pref("extensions.treestyletab.tooltip.fullTooltipDelay", 2000);
+/**
+ * If true, too many items are shown in multiple columns.
+ */
+pref("extensions.treestyletab.tooltip.columnize", true);
/**
* Visibility of extra menu items for the context menu on tabs, inserted by TST.
@@ -629,8 +638,6 @@ pref("extensions.treestyletab.restoreTree.level", 1);
* conflict with TST features. They will be rolled back when TST is uninstalled.
*/
pref("browser.link.open_newwindow.restriction.override", 0);
-pref("browser.tabs.insertRelatedAfterCurrent.override", false);
-pref("browser.tabs.insertRelatedAfterCurrent.override.force", true);
/**
* Extra commands for selected tabs (Multiple Tab Handler)
@@ -658,6 +665,11 @@ pref("extensions.treestyletab.createSubtree.underParent.temporaryGroup", true);
pref("extensions.treestyletab.pinnedTab.faviconized", true);
/**
+ * If true, too many items are shown in multiple columns in a dummy (group) tab.
+ */
+pref("extensions.treestyletab.groupTab.columnize", true);
+
+/**
* Compatibility hack flags for other addons. They can be disabled by each
* addon, when the addon become working with TST without dirty hacks.
* In other words, add-on authros can disable TST's dirty hack if it is
@@ -728,7 +740,10 @@ pref("extensions.treestyletab.prefsVersion", 0);
pref("extensions.treestyletab.debug.all", false);
pref("extensions.treestyletab.debug.autoHide", false);
pref("extensions.treestyletab.debug.base", false);
+pref("extensions.treestyletab.debug.bookmark", false);
pref("extensions.treestyletab.debug.browser", false);
pref("extensions.treestyletab.debug.browserUIShowHideObserver", false);
pref("extensions.treestyletab.debug.contentBridge", false);
+pref("extensions.treestyletab.debug.fullscreenObserver", false);
pref("extensions.treestyletab.debug.tabbarDNDObserver", false);
+pref("extensions.treestyletab.debug.window", false);
diff --git a/install.rdf b/install.rdf
index c377fc1..03ac69f 100644
--- a/install.rdf
+++ b/install.rdf
@@ -5,7 +5,7 @@
<RDF:Description RDF:about="urn:mozilla:install-manifest"
em:id="treestyletab at piro.sakura.ne.jp"
em:name="Tree Style Tab"
- em:version="0.16.2015122501"
+ em:version="0.16.2016021602"
em:creator="YUKI "Piro" Hiroshi"
em:description="Show tabs like a tree."
em:homepageURL="http://piro.sakura.ne.jp/xul/_treestyletab.html.en"
@@ -84,7 +84,7 @@
</em:localized>
<em:localized>
<RDF:Description em:locale="es-ES"
- em:name="Tree Style Tab (Pestañas estilo árbol)"
+ em:name="Pestañas estilo árbol"
em:description="Muestra las pestañas en vista de árbol"
em:homepageURL="http://piro.sakura.ne.jp/xul/_treestyletab.html.en"
em:creator="YUKI "Piro" Hiroshi">
@@ -112,6 +112,7 @@
<em:contributor>mnoorenberghe (Firefox 36 support)</em:contributor>
<em:contributor>Xidorn Quan (Firefox 40+ support)</em:contributor>
<em:translator>Andy Pillip (de-DE locale)</em:translator>
+ <em:translator>Björn Kautler (de-DE locale)</em:translator>
</RDF:Description>
</em:localized>
<em:localized>
@@ -134,7 +135,7 @@
</em:localized>
<em:localized>
<RDF:Description em:locale="ru"
- em:name="Tree Style Tab (Древовидный стиль вкладок)"
+ em:name="Древовидный стиль вкладок"
em:description="Отображение вкладок в виде дерева"
em:homepageURL="http://piro.sakura.ne.jp/xul/_treestyletab.html.en"
em:creator="YUKI "Piro" Hiroshi">
diff --git a/locale/cs/treestyletab/treestyletab.dtd b/locale/cs/treestyletab/treestyletab.dtd
index c57e86d..422f7c2 100644
--- a/locale/cs/treestyletab/treestyletab.dtd
+++ b/locale/cs/treestyletab/treestyletab.dtd
@@ -113,7 +113,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "Zobrazit lištu po">
<!ENTITY config.autoShow.accelKeyDown.delay.after "ms">
<!ENTITY config.autoShow.tabSwitch "Panel je přepnut kombinací kláves Ctrl-Tab">
-<!ENTITY config.autoShow.feedback "Panel je otevřen nebo zavřen">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "Panel je otevřen nebo zavřen"-->
<!ENTITY config.autoShow.feedback.delay.before "Opět zmenšit nebo schovat lištu po">
<!ENTITY config.autoShow.feedback.delay.after "ms">
@@ -131,6 +132,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "Povýšit prvního potomka na rodičovský panel">
<!ENTITY config.closeParentBehavior.promoteAll "Povýšit všechny potomky na úroveň rodičovského panelu">
<!ENTITY config.closeParentBehavior.detach "Osvobodit potomky z celého stromu">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "Povýšit prvního potomka na rodičovský panel, pokud původní rodič sám neměl rodiče">
<!ENTITY config.focusMode "Přepnout na následující/předchozí panel pomocí Ctrl-Tab i přesto, že není vidět">
diff --git a/locale/da-DK/treestyletab/treestyletab.dtd b/locale/da-DK/treestyletab/treestyletab.dtd
index 29da501..c03a1db 100644
--- a/locale/da-DK/treestyletab/treestyletab.dtd
+++ b/locale/da-DK/treestyletab/treestyletab.dtd
@@ -127,7 +127,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "Vis efter">
<!ENTITY config.autoShow.accelKeyDown.delay.after "msec.">
<!ENTITY config.autoShow.tabSwitch "Ctrl-Tab skifter faner">
-<!ENTITY config.autoShow.feedback "Ved åbning eller lukning af faner">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "Ved åbning eller lukning af faner"-->
<!ENTITY config.autoShow.feedback.delay.before "Skjul efter">
<!ENTITY config.autoShow.feedback.delay.after "msec.">
@@ -145,6 +146,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "Gør første underfane til hovedfane">
<!ENTITY config.closeParentBehavior.promoteAll "Gør alle underfaner til hovedfaner">
<!ENTITY config.closeParentBehavior.detach "Frigør underfaner fra træet">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "Gør første underfane til hovedfane, hvis den lukkede fane er den første">
<!ENTITY config.focusMode "Flyt fokus til næste/forrige fane, selv om den ikke er synlig, med Ctrl-Tab">
diff --git a/locale/de-DE/treestyletab/license.txt b/locale/de-DE/treestyletab/license.txt
index 6b66e3f..b4ce9e5 100644
--- a/locale/de-DE/treestyletab/license.txt
+++ b/locale/de-DE/treestyletab/license.txt
@@ -14,10 +14,11 @@ License.
The Original Code is the Tree Style Tab.
The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
-Portions created by the Initial Developer are Copyright (C) 2007-2009
+Portions created by the Initial Developer are Copyright (C) 2007-2016
the Initial Developer. All Rights Reserved.
-Contributor(s): Andy Pillip <andy at pillip.eu>
+Contributor(s): Andy Pillip <andy at pillip.eu>
+ Björn Kautler <https://github.com/Vampire>
YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
Alternatively, the contents of these files may be used under the terms of
diff --git a/locale/de-DE/treestyletab/treestyletab.dtd b/locale/de-DE/treestyletab/treestyletab.dtd
index 226d710..dae26df 100644
--- a/locale/de-DE/treestyletab/treestyletab.dtd
+++ b/locale/de-DE/treestyletab/treestyletab.dtd
@@ -6,164 +6,153 @@
<!ENTITY config.tabs.appearance "Darstellung">
-<!ENTITY config.tabbar.position.caption "Position der Tableiste">
-<!ENTITY config.tabbar.position.left "Links">
-<!ENTITY config.tabbar.position.right "Rechts">
-<!ENTITY config.tabbar.position.top "Oben (Firefox Standard)">
-<!ENTITY config.tabbar.position.bottom "Unten">
-<!ENTITY config.tabbar.invertClosebox.left "Schließen-Button in jedem Tab links anzeigen">
-<!ENTITY config.tabbar.invertClosebox.right "Schließen-Button in jedem Tab rechts anzeigen">
-<!ENTITY config.tabbar.invertTab "Tabs von rechts einrücken">
-<!ENTITY config.tabbar.invertTabContents "Symbol und Text in den Tabs vertauschen">
-<!ENTITY config.tabbar.narrowScrollbar "Narrow scrollbar">
-<!ENTITY config.enableSubtreeIndent "Tabs einrücken">
-<!ENTITY config.maxTreeLevel.before "bis">
-<!ENTITY config.maxTreeLevel.after "Level">
-<!ENTITY config.allowSubtreeCollapseExpand "Auf- und Einklappen von Zweigen erlauben">
+<!ENTITY config.tabbar.position.caption "Position der Tableiste">
+<!ENTITY config.tabbar.position.left "Links">
+<!ENTITY config.tabbar.position.right "Rechts">
+<!ENTITY config.tabbar.position.top "Oben (Firefox Standard)">
+<!ENTITY config.tabbar.position.bottom "Unten">
+<!ENTITY config.tabbar.invertClosebox.left "Schließen-Knopf in jedem Tab links anzeigen">
+<!ENTITY config.tabbar.invertClosebox.right "Schließen-Knopf in jedem Tab rechts anzeigen">
+<!ENTITY config.tabbar.invertTab "Tabs von rechts einrücken">
+<!ENTITY config.tabbar.invertTabContents "Symbol und Text in den Tabs vertauschen">
+<!ENTITY config.tabbar.narrowScrollbar "Schmale Bildlaufleiste">
+<!ENTITY config.enableSubtreeIndent "Tabs einrücken">
+<!ENTITY config.maxTreeLevel.before "bis">
+<!ENTITY config.maxTreeLevel.after "Level">
+<!ENTITY config.allowSubtreeCollapseExpand "Auf- und Einklappen von Zweigen erlauben">
<!ENTITY config.tabbarSize.before-horizontal ":">
-<!ENTITY config.tabbarSize.after-horizontal "px height">
+<!ENTITY config.tabbarSize.after-horizontal "px Höhe">
<!ENTITY config.tabbarSize.before-vertical ":">
-<!ENTITY config.tabbarSize.after-vertical "px width">
+<!ENTITY config.tabbarSize.after-vertical "px Breite">
-<!ENTITY config.tabs.style "Style">
+<!ENTITY config.tabs.style "Aussehen">
<!ENTITY config.tabbar.style.caption "Aussehen der Tableiste">
-<!ENTITY config.tabbar.style.plain "Plain">
-<!ENTITY config.tabbar.style.flat "Flat">
+<!ENTITY config.tabbar.style.plain "Pur">
+<!ENTITY config.tabbar.style.flat "Flach">
<!ENTITY config.tabbar.style.mixed "Gemischt">
<!ENTITY config.tabbar.style.vertigo "Vertigo">
<!ENTITY config.tabbar.style.metal "Metal">
-<!ENTITY config.tabbar.style.sidebar "Sidebar">
+<!ENTITY config.tabbar.style.sidebar "Seitenleiste">
<!ENTITY config.tabbar.style.none "Standard (durch Theme festgelegt)">
-<!ENTITY config.twisty.style.caption "Aufklappsymbole">
-<!ENTITY config.twisty.style.auto "Auto">
-<!ENTITY config.twisty.style.none "Keine">
-<!ENTITY config.twisty.style.retro "Retro">
+<!ENTITY config.twisty.style.caption "Aufklappsymbole">
+<!ENTITY config.twisty.style.auto "Auto">
+<!ENTITY config.twisty.style.none "Keine">
+<!ENTITY config.twisty.style.retro "Retro">
<!ENTITY config.twisty.style.modern.black "Schwarz Modern">
<!ENTITY config.twisty.style.modern.white "Weiß Modern">
-<!ENTITY config.twisty.style.osx "OS X">
+<!ENTITY config.twisty.style.osx "OS X">
<!ENTITY config.tabs.menu "Menü">
<!ENTITY config.show.tabContextMenu.caption "Folgende Zeilen im Kontextmenü der Tabs anzeigen">
-<!ENTITY config.show.openSelectionLinks ""Links im markierten Webseitentext in Tabs öffnen" im Kontextmenü der Markierung anbieten">
-
<!ENTITY config.tabs.tab "Tabs Öffnen">
-<!--
-<!ENTITY config.autoAttach.newTabCommand.caption "Neuen Tab öffnen:">
-<!ENTITY config.autoAttach.newTabCommand.independent "Auf oberster Ebene">
-<!ENTITY config.autoAttach.newTabCommand.child "Dem aktuellen Tab unterordnen">
-<!ENTITY config.autoAttach.newTabCommand.sibling "Auf Ebene des aktuellen Tabs öffnen">
-<!ENTITY config.autoAttach.newTabCommand.nextSibling "Open as the next sibling of the current tab">
-
-<!ENTITY config.autoAttach.duplicateTabCommand.caption "When a tab is duplicated by middle click on the "Reload" button:">
-<!ENTITY config.autoAttach.duplicateTabCommand.independent "Auf oberster Ebene">
-<!ENTITY config.autoAttach.duplicateTabCommand.child "Dem aktuellen Tab unterordnen">
-<!ENTITY config.autoAttach.duplicateTabCommand.sibling "Auf Ebene des aktuellen Tabs öffnen">
-<!ENTITY config.autoAttach.duplicateTabCommand.nextSibling "Open as the next sibling of the source tab">
--->
-<!ENTITY config.autoAttach.newTabCommand.label_before "Open new blank tab as">
-<!ENTITY config.autoAttach.newTabCommand.independent "an independent tab">
-<!ENTITY config.autoAttach.newTabCommand.child "a child of the current tab">
-<!ENTITY config.autoAttach.newTabCommand.sibling "a sibling of the current tab">
-<!ENTITY config.autoAttach.newTabCommand.nextSibling "the next sibling of the current tab">
-<!ENTITY config.autoAttach.newTabCommand.label_after "">
-
-<!ENTITY config.autoAttach.newTabButton.label_before "For middle click on the "New Tab" button, open new blank tab as">
-<!ENTITY config.autoAttach.newTabButton.independent "an independent tab">
-<!ENTITY config.autoAttach.newTabButton.child "a child of the current tab">
-<!ENTITY config.autoAttach.newTabButton.sibling "a sibling of the current tab">
-<!ENTITY config.autoAttach.newTabButton.nextSibling "the next sibling of the current tab">
-<!ENTITY config.autoAttach.newTabButton.label_after "">
-
-<!ENTITY config.autoAttach.duplicateTabCommand.label_before "For middle click on the "Reload" button, duplicate the tab as">
-<!ENTITY config.autoAttach.duplicateTabCommand.independent "an independent tab">
-<!ENTITY config.autoAttach.duplicateTabCommand.child "a child of the source tab">
-<!ENTITY config.autoAttach.duplicateTabCommand.sibling "a sibling of the source tab">
-<!ENTITY config.autoAttach.duplicateTabCommand.nextSibling "the next sibling of the source tab">
-<!ENTITY config.autoAttach.duplicateTabCommand.label_after "">
-
-<!ENTITY config.autoAttach.goButton.label_before "For middle click on the "Go" button, open new tab as">
-<!ENTITY config.autoAttach.goButton.independent "an independent tab">
-<!ENTITY config.autoAttach.goButton.child "a child of the current tab">
-<!ENTITY config.autoAttach.goButton.sibling "a sibling of the current tab">
-<!ENTITY config.autoAttach.goButton.nextSibling "the next sibling of the current tab">
-<!ENTITY config.autoAttach.goButton.label_after "">
-
-<!ENTITY config.openGroupBookmark.caption "Verhalten von "Alle in Tabs öffnen" für Seiten in einem Lesezeichenordner">
-<!ENTITY config.openGroupBookmark.ask "Jedes Mal nachfragen">
-<!ENTITY config.openGroupBookmark.subtree "Als Zweig öffnen (Empfohlen)">
-<!ENTITY config.openGroupBookmark.subtree.type.before "">
-<!ENTITY config.openGroupBookmark.subtree.type.restore "Speichere">
-<!ENTITY config.openGroupBookmark.subtree.type.flat "Ignoriere">
-<!ENTITY config.openGroupBookmark.subtree.type.after "Anordnung der Tabs im Zweig beim Speichern als Lesezeichen">
-<!ENTITY config.openGroupBookmark.flat "Als eigenständige Tabs öffnen (Firefox Standard)">
-<!ENTITY config.openGroupBookmark.underParent "Seiten zur Gruppierung einem Dummytab unterordnen">
-
-<!ENTITY config.dropLinksOnTab.caption "Verhalten für Drag & Drop auf Tabs">
+<!ENTITY config.autoAttach.newTabCommand.label_before "Neuen leeren Tab als">
+<!ENTITY config.autoAttach.newTabCommand.independent "eigenständigen Tab">
+<!ENTITY config.autoAttach.newTabCommand.child "untergeordneten Tab des aktiven Tab">
+<!ENTITY config.autoAttach.newTabCommand.sibling "Tab auf der Ebene des aktiven Tab">
+<!ENTITY config.autoAttach.newTabCommand.nextSibling "direkten Nachbar auf der Ebene des aktiven Tab">
+<!ENTITY config.autoAttach.newTabCommand.label_after "öffnen">
+
+<!ENTITY config.autoAttach.newTabButton.label_before "Bei Mittelklick auf den "Neuer Tab" Knopf, neuen leeren Tab als">
+<!ENTITY config.autoAttach.newTabButton.independent "eigenständigen Tab">
+<!ENTITY config.autoAttach.newTabButton.child "untergeordneten Tab des aktiven Tab">
+<!ENTITY config.autoAttach.newTabButton.sibling "Tab auf der Ebene des aktiven Tab">
+<!ENTITY config.autoAttach.newTabButton.nextSibling "direkten Nachbar auf der Ebene des aktiven Tab">
+<!ENTITY config.autoAttach.newTabButton.label_after "öffnen">
+
+<!ENTITY config.autoAttach.duplicateTabCommand.label_before "Bei Mittelklick auf den "Neu Laden" Knopf, den aktiven Tab als">
+<!ENTITY config.autoAttach.duplicateTabCommand.independent "eigenständigen Tab">
+<!ENTITY config.autoAttach.duplicateTabCommand.child "untergeordneten Tab des aktiven Tab">
+<!ENTITY config.autoAttach.duplicateTabCommand.sibling "Tab auf der Ebene des aktiven Tab">
+<!ENTITY config.autoAttach.duplicateTabCommand.nextSibling "direkten Nachbar auf der Ebene des aktiven Tab">
+<!ENTITY config.autoAttach.duplicateTabCommand.label_after "kopieren">
+
+<!ENTITY config.autoAttach.goButton.label_before "Bei Mittelklick auf den "Laden" Knopf, neuen Tab als">
+<!ENTITY config.autoAttach.goButton.independent "eigenständigen Tab">
+<!ENTITY config.autoAttach.goButton.child "untergeordneten Tab des aktiven Tab">
+<!ENTITY config.autoAttach.goButton.sibling "Tab auf der Ebene des aktiven Tab">
+<!ENTITY config.autoAttach.goButton.nextSibling "direkten Nachbar auf der Ebene des aktiven Tab">
+<!ENTITY config.autoAttach.goButton.label_after "öffnen">
+
+<!ENTITY config.openGroupBookmark.caption "Verhalten von "Alle in Tabs öffnen" in einem Lesezeichenordner">
+<!ENTITY config.openGroupBookmark.ask "Jedes Mal nachfragen">
+<!ENTITY config.openGroupBookmark.subtree "Als Zweig öffnen (Empfohlen)">
+<!ENTITY config.openGroupBookmark.subtree.type.before "Die Zweigstruktur von als Tabs gespeicherten Lesezeichen">
+<!ENTITY config.openGroupBookmark.subtree.type.restore "wiederherstellen">
+<!ENTITY config.openGroupBookmark.subtree.type.flat "ignorieren">
+<!ENTITY config.openGroupBookmark.subtree.type.after "">
+<!ENTITY config.openGroupBookmark.flat "Als eigenständige Tabs öffnen (Firefox Standard)">
+<!ENTITY config.openGroupBookmark.underParent "Seiten zur Gruppierung einem Pseudotab unterordnen">
+
+<!ENTITY config.dropLinksOnTab.caption "Verhalten für Drag & Drop von Link, URL, Bookmark oder Datei auf existierenden Tab">
<!ENTITY config.dropLinksOnTab.ask "Immer nachfragen">
<!ENTITY config.dropLinksOnTab.load "Seite im Tab laden (Firefox default)">
<!ENTITY config.dropLinksOnTab.newTab "Seite in einem neuen untergeordneten Tab laden">
-<!ENTITY config.tabs.autohide "Platz sparen">
-
-<!ENTITY config.autoHide.mode.normal.caption "Bei normaler Fenstergröße">
-<!ENTITY config.autoHide.mode.fullscreen.caption "Im Vollbildmodus">
-<!ENTITY config.autoHide.mode.0 "Tableiste immer voll anzeigen">
-<!ENTITY config.autoHide.mode.1 "Inaktive Tableiste verstecken">
-<!ENTITY config.autoHide.mode.2 "Inaktive Tableiste verkleinert anzeigen">
-<!ENTITY config.autoShow.caption "Tableiste aktivieren">
-<!ENTITY config.autoShow.mousemove "Wenn der Mauszeiger die Fensterecken berührt">
-<!ENTITY config.autoHide.area.before "Empfindlicher Bereich:">
-<!ENTITY config.autoHide.area.after "Pixel rund um die Fensterecken / Kante der Tableiste">
-<!ENTITY config.autoHide.delay.before "Verzögerung:">
-<!ENTITY config.autoHide.delay.after "msec.">
-<!ENTITY config.autoShow.accelKeyDown "Wenn die Strg-Taste eine Zeit lang gedrückt wird">
+
+<!ENTITY config.tabs.autohide "Automatisches Ausblenden">
+
+<!ENTITY config.autoHide.mode.normal.caption "Im Normalmodus">
+<!ENTITY config.autoHide.mode.fullscreen.caption "Im Vollbildmodus">
+<!ENTITY config.autoHide.mode.0 "Tableiste immer anzeigen">
+<!ENTITY config.autoHide.mode.1 "Tableiste automatisch verstecken">
+<!ENTITY config.autoHide.mode.2 "Tableiste automatisch verkleinern">
+<!ENTITY config.autoShow.caption "Tableiste anzeigen">
+<!ENTITY config.autoShow.mousemove "Wenn sich der Mauszeiger der Fenster- oder Tableistenkante annähert">
+<!ENTITY config.autoHide.area.before "Empfindlicher Bereich:">
+<!ENTITY config.autoHide.area.after "Pixel rund um die Fenster- oder Tableistenkante">
+<!ENTITY config.autoHide.delay.before "Verzögerung:">
+<!ENTITY config.autoHide.delay.after "Millisekunden">
+<!ENTITY config.autoShow.accelKeyDown "Wenn die Strg-Taste eine Zeit lang gedrückt wird">
<!ENTITY config.autoShow.accelKeyDown.delay.before "Nach">
-<!ENTITY config.autoShow.accelKeyDown.delay.after "msec. aktivieren">
-<!ENTITY config.autoShow.tabSwitch "Wenn Strg+Tab (wechselt zwischen Tabs) gedrückt wird">
-<!ENTITY config.autoShow.feedback "Wenn neue Tabs geöffnet oder alte geschlossen werden">
-<!ENTITY config.autoShow.feedback.delay.before "Nach">
-<!ENTITY config.autoShow.feedback.delay.after "msec. wieder deaktivieren">
+<!ENTITY config.autoShow.accelKeyDown.delay.after "Millisekunden anzeigen">
+<!ENTITY config.autoShow.tabSwitch "Wenn Strg+Tab gedrückt wird um zwischen Tabs zu wechseln">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "Wenn Tabs geöffnet oder geschlossen werden"-->
+<!ENTITY config.autoShow.feedback.delay.before "Nach">
+<!ENTITY config.autoShow.feedback.delay.after "Millisekunden wieder ausblenden">
-<!ENTITY config.tabs.tree "Verhalten">
+<!ENTITY config.tabs.tree "Zweig">
-<!ENTITY config.autoCollapseExpandSubtreeOnAttach "When a new tree appears, collapse others automatically">
-<!ENTITY config.autoCollapseExpandSubtreeOnSelect "Nicht aktive Zweige zuklappen">
-<!ENTITY config.autoCollapseExpandSubtreeOnSelect.onCurrentTabRemove "Keine Fokusänderung beim Schließen des aktiven Tabs">
-<!ENTITY config.collapseExpandSubtree.dblclick "Bei Doppelklick auf Tab untergeordneten Zweig auf- oder zuklappen">
-<!ENTITY config.autoExpandSubtreeOnAppendChild "Zweig automatisch aufklappen, wenn ein Tab in den Zweig eingefügt wird">
+<!ENTITY config.autoCollapseExpandSubtreeOnAttach "Wenn ein neuer Zweig erscheint, andere Zweige automatisch zuklappen">
+<!ENTITY config.autoCollapseExpandSubtreeOnSelect "Wenn ein Tab ausgewählt wird, untergeordneten Zweig automatisch auf- und andere Zweige zuklappen">
+<!ENTITY config.autoCollapseExpandSubtreeOnSelect.onCurrentTabRemove "Nicht durch Schließen des aktiven Tabs auslösen">
+<!ENTITY config.collapseExpandSubtree.dblclick "Bei Doppelklick auf Tab untergeordneten Zweig auf- oder zuklappen">
+<!ENTITY config.autoExpandSubtreeOnAppendChild "Zweig automatisch aufklappen, wenn ein Tab in den Zweig eingefügt wird">
-<!ENTITY config.closeParentBehavior.caption "Wenn ein Tab geschlossen wird">
-<!ENTITY config.closeParentBehavior.close "Untergeordnete Tabs auch schließen">
-<!ENTITY config.closeParentBehavior.promoteFirst "Das geschlossene Tab durch das erste untergeordnete ersetzen">
-<!ENTITY config.closeParentBehavior.promoteAll "Untergeordnete Tabs auf die Ebene des geschlossenen Tabs verschieben">
-<!ENTITY config.closeParentBehavior.detach "Untergeordnete Tabs ganz aus dem Zweig ausgliedern">
-<!ENTITY config.closeRootBehavior.promoteFirst "Das geschlossene Tab durch das erste untergeordnete ersetzen, wenn das geschlossene Tab kein übergordnetes hatte">
+<!ENTITY config.closeParentBehavior.caption "Wenn ein Tab geschlossen wird">
+<!ENTITY config.closeParentBehavior.close "Untergeordnete Tabs auch schließen">
+<!ENTITY config.closeParentBehavior.promoteFirst "Das geschlossene Tab durch das erste untergeordnete ersetzen">
+<!ENTITY config.closeParentBehavior.promoteAll "Untergeordnete Tabs auf die Ebene des geschlossenen Tabs verschieben">
+<!ENTITY config.closeParentBehavior.detach "Untergeordnete Tabs ganz aus dem Zweig ausgliedern">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Das geschlossene Tab durch ein Pseudotab ersetzen">
+<!ENTITY config.closeRootBehavior.promoteFirst "Das geschlossene Tab durch das erste untergeordnete ersetzen, wenn das geschlossene Tab kein übergeordnetes hatte">
-<!ENTITY config.focusMode "Strg+Tab selektiert auch nicht sichtbare Tabs">
+<!ENTITY config.focusMode "Bei Strg+Tab auch zu nicht sichtbaren Tabs wechseln">
<!ENTITY config.insertNewChildAt.caption "Einfügeposition neuer untergeordneter Tabs">
-<!ENTITY config.insertNewChildAt.first "Oben im Zweig einfügen">
-<!ENTITY config.insertNewChildAt.last "Unten im Zweig einfügen">
+<!ENTITY config.insertNewChildAt.first "Als erstes Tab einfügen">
+<!ENTITY config.insertNewChildAt.last "Als letztes Tab anfügen">
-<!ENTITY config.undoCloseTabSet.caption "Wenn ein Element eines Zweiges durch "Tab wieder öffnen" wiederhergestellt wird.">
+<!ENTITY config.undoCloseTabSet.caption "Wenn ein Element eines Zweiges durch "Tab wiederherstellen" geöffnet wird">
<!ENTITY config.undoCloseTabSet.ask "Immer nachfragen">
-<!ENTITY config.undoCloseTabSet.set "Den ganzen Zweig wieder herstellen">
-<!ENTITY config.undoCloseTabSet.separate "Nur das eine Tab wieder herstellen (Firefox Standard)">
+<!ENTITY config.undoCloseTabSet.set "Den ganzen Zweig wiederherstellen">
+<!ENTITY config.undoCloseTabSet.separate "Nur das eine Tab wiederherstellen (Firefox Standard)">
+
<!ENTITY config.tabs.advanced "Erweitert">
-<!ENTITY config.tooltip.includeChildren "Titel der untergeordneten Tabs im Tooltip geschlossener Tabs anzeigen">
+<!ENTITY config.tooltip.includeChildren "Titel der untergeordneten Tabs im Tooltip des Tabs anzeigen">
-<!ENTITY config.bookmarkDroppedTabs.caption "Verhalten für Drag & Drop von Tab-Zweigen auf das Lesezeichenverzeichnis">
+<!ENTITY config.bookmarkDroppedTabs.caption "Verhalten für Drag & Drop von Tab-Zweigen auf den Lesezeichenbaum">
<!ENTITY config.bookmarkDroppedTabs.ask "Immer nachfragen">
<!ENTITY config.bookmarkDroppedTabs.all "Alle Tabs im Zweig als Lesezeichen speichern">
<!ENTITY config.bookmarkDroppedTabs.parent "Nur das gezogene Tab als Lesezeichen speichern">
@@ -171,34 +160,35 @@
-<!ENTITY selection.removeTabSubtree.label "Ausgewählte Zweige schließen">
-<!ENTITY selection.removeTabSubtree.accesskey "s">
-<!ENTITY selection.createSubtree.label "Zweig auf oberste Ebene verschieben">
+
+<!ENTITY selection.createSubtree.label "Zu neuem Zweig zusammenfügen">
<!ENTITY selection.createSubtree.accesskey "g">
-<!ENTITY context.reloadTabSubtree.label "Diesen Zweig neu laden">
-<!ENTITY context.reloadTabSubtree.accesskey "r">
+<!ENTITY selection.removeTabSubtree.label "Ausgewählte Zweige schließen">
+<!ENTITY selection.removeTabSubtree.accesskey "s">
+<!ENTITY context.reloadTabSubtree.label "Diesen Zweig neu laden">
+<!ENTITY context.reloadTabSubtree.accesskey "r">
<!ENTITY context.reloadDescendantTabs.label "Untergeordnete Tabs neu laden">
<!ENTITY context.reloadDescendantTabs.accesskey "r">
-<!ENTITY context.removeTabSubtree.label "Diesen Zweig schließen">
-<!ENTITY context.removeTabSubtree.accesskey "s">
+<!ENTITY context.removeTabSubtree.label "Diesen Zweig schließen">
+<!ENTITY context.removeTabSubtree.accesskey "s">
<!ENTITY context.removeDescendantTabs.label "Untergeordnete Tabs schließen">
<!ENTITY context.removeDescendantTabs.accesskey "d">
-<!ENTITY context.removeAllTabsBut.label "Andere Zweige schließen">
+<!ENTITY context.removeAllTabsBut.label "Andere Tabs außer diesem Zweig schließen">
<!ENTITY context.removeAllTabsBut.accesskey "a">
-<!ENTITY context.collapseAllSubtree.label "Alle Zweige zuklappen">
-<!ENTITY context.collapseAllSubtree.accesskey "c">
-<!ENTITY context.expandAllSubtree.label "Alle Zweige aufklappen">
-<!ENTITY context.expandAllSubtree.accesskey "e">
-<!ENTITY context.toggleAutoHide.label.hide "Tableiste verstecken">
-<!ENTITY context.toggleAutoHide.label.shrink "Tableiste verkleinert anzeigen">
-<!ENTITY context.toggleAutoHide.accesskey "h">
-<!ENTITY context.toggleFixed.label "Feste Position und Größe der Tableiste">
-<!ENTITY context.toggleFixed.label.horizontal "Feste Position und Höhe der Tableiste">
-<!ENTITY context.toggleFixed.label.vertical "Feste Position und Breite der Tableiste">
-<!ENTITY context.toggleFixed.accesskey "f">
-<!ENTITY context.bookmarkTabSubtree.label "Zweig als Lesezeichen speichern">
-<!ENTITY context.bookmarkTabSubtree.accesskey "t">
-
-<!ENTITY group.default "Neue Gruppe">
-<!ENTITY group.temporary "Temporary Group">
+<!ENTITY context.collapseAllSubtree.label "Alle Zweige zuklappen">
+<!ENTITY context.collapseAllSubtree.accesskey "c">
+<!ENTITY context.expandAllSubtree.label "Alle Zweige aufklappen">
+<!ENTITY context.expandAllSubtree.accesskey "e">
+<!ENTITY context.toggleAutoHide.label.hide "Tableiste automatisch verstecken">
+<!ENTITY context.toggleAutoHide.label.shrink "Tableiste automatisch verkleinern">
+<!ENTITY context.toggleAutoHide.accesskey "h">
+<!ENTITY context.toggleFixed.label "Feste Position und Größe der Tableiste">
+<!ENTITY context.toggleFixed.label.horizontal "Feste Position und Höhe der Tableiste">
+<!ENTITY context.toggleFixed.label.vertical "Feste Position und Breite der Tableiste">
+<!ENTITY context.toggleFixed.accesskey "f">
+<!ENTITY context.bookmarkTabSubtree.label "Zweig als Lesezeichen speichern">
+<!ENTITY context.bookmarkTabSubtree.accesskey "t">
+
+<!ENTITY group.default "Neue Gruppe">
+<!ENTITY group.temporary "Temporäre Gruppe">
diff --git a/locale/en-US/treestyletab/treestyletab.dtd b/locale/en-US/treestyletab/treestyletab.dtd
index a780985..504090d 100644
--- a/locale/en-US/treestyletab/treestyletab.dtd
+++ b/locale/en-US/treestyletab/treestyletab.dtd
@@ -113,7 +113,7 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "Show after">
<!ENTITY config.autoShow.accelKeyDown.delay.after "msec.">
<!ENTITY config.autoShow.tabSwitch "Control-Tab to switch tabs">
-<!ENTITY config.autoShow.feedback "New tabs are opened or some tabs are closed">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
<!ENTITY config.autoShow.feedback.delay.before "Hide after">
<!ENTITY config.autoShow.feedback.delay.after "msec.">
@@ -131,6 +131,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "Promote the first child tab as the new parent">
<!ENTITY config.closeParentBehavior.promoteAll "Promote all child tabs as the level of the closed parent tab">
<!ENTITY config.closeParentBehavior.detach "Liberate child tabs from the tree">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "Promote the first child tab as the new parent, if the closed parent has no parent">
<!ENTITY config.focusMode "Focus to the next/previous tab even if it is invisible, by Control-Tab">
diff --git a/locale/es-ES/treestyletab/treestyletab.dtd b/locale/es-ES/treestyletab/treestyletab.dtd
index 8e3de37..4fb2642 100644
--- a/locale/es-ES/treestyletab/treestyletab.dtd
+++ b/locale/es-ES/treestyletab/treestyletab.dtd
@@ -122,7 +122,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "Mostrar después">
<!ENTITY config.autoShow.accelKeyDown.delay.after "mseg.">
<!ENTITY config.autoShow.tabSwitch "Control-Tab para cambiar pestañas">
-<!ENTITY config.autoShow.feedback "Nuevas pestañas son abiertas o algunas pestañas son cerradas">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "Nuevas pestañas son abiertas o algunas pestañas son cerradas"-->
<!ENTITY config.autoShow.feedback.delay.before "Ocultar después">
<!ENTITY config.autoShow.feedback.delay.after "mseg.">
@@ -141,6 +142,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "Promover la primer pestañas como madre">
<!ENTITY config.closeParentBehavior.promoteAll "Promover todas las pestañas hijas al nivel de la pestaña cerrada">
<!ENTITY config.closeParentBehavior.detach "Liberar las hijas del árbol">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "Promover la primer hija como la nueva madre, si la madre cerrada no tiene madres">
<!--ENTITY config.attachChildrenToGrandParentOnRemoveTab "Liberar las pestañas hijas del árbol cuando el árbol es cerrado"-->
diff --git a/locale/fr-FR/treestyletab/treestyletab.dtd b/locale/fr-FR/treestyletab/treestyletab.dtd
index 6f7fad5..5e67997 100644
--- a/locale/fr-FR/treestyletab/treestyletab.dtd
+++ b/locale/fr-FR/treestyletab/treestyletab.dtd
@@ -114,7 +114,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "Afficher après">
<!ENTITY config.autoShow.accelKeyDown.delay.after "msec.">
<!ENTITY config.autoShow.tabSwitch "Control-Tab pour passer à l'onglet suivant">
-<!ENTITY config.autoShow.feedback "De nouveaux onglets sont ouverts ou d'autres sont fermés">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "De nouveaux onglets sont ouverts ou d'autres sont fermés"-->
<!ENTITY config.autoShow.feedback.delay.before "Masquer après">
<!ENTITY config.autoShow.feedback.delay.after "msec.">
@@ -132,6 +133,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "Promouvoir le premier onglet enfant en nouveau parent">
<!ENTITY config.closeParentBehavior.promoteAll "Promouvoir tous les onglets enfants au même niveau que l'onglet parent fermé">
<!ENTITY config.closeParentBehavior.detach "Sortir les onglets enfants de l'arborescence">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "Promouvoir le premier onglet enfant en nouveau parent, si le parent fermé n'a pas de parent">
<!ENTITY config.focusMode "Activer l'onglet suivant/précédent même s'il n'est pas visible par Control-Tab">
diff --git a/locale/it-IT/treestyletab/treestyletab.dtd b/locale/it-IT/treestyletab/treestyletab.dtd
index a11fdb7..b8949cd 100644
--- a/locale/it-IT/treestyletab/treestyletab.dtd
+++ b/locale/it-IT/treestyletab/treestyletab.dtd
@@ -122,7 +122,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "Visualizza dopo">
<!ENTITY config.autoShow.accelKeyDown.delay.after "msec.">
<!ENTITY config.autoShow.tabSwitch "Viene utilizzata la scorciatoia Control+Tab per passare da una scheda all'altra">
-<!ENTITY config.autoShow.feedback "Viene aperta o chiusa una scheda">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "Viene aperta o chiusa una scheda"-->
<!ENTITY config.autoShow.feedback.delay.before "Nascondi dopo">
<!ENTITY config.autoShow.feedback.delay.after "msec.">
@@ -141,6 +142,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "Promote the first child tab as the new parent">
<!ENTITY config.closeParentBehavior.promoteAll "porta le sottoschede al livello della scheda principale">
<!ENTITY config.closeParentBehavior.detach "elimina le sottoschede dall'albero">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "Promote the first child tab as the new parent, if the closed parent has no parent">
<!--ENTITY config.attachChildrenToGrandParentOnRemoveTab "Elimina le sottoschede dall'albero alla chiusura della scheda principale"-->
diff --git a/locale/ja/treestyletab/treestyletab.dtd b/locale/ja/treestyletab/treestyletab.dtd
index 45f3534..90626b2 100644
--- a/locale/ja/treestyletab/treestyletab.dtd
+++ b/locale/ja/treestyletab/treestyletab.dtd
@@ -114,7 +114,7 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "">
<!ENTITY config.autoShow.accelKeyDown.delay.after "ミリ秒以上で反応">
<!ENTITY config.autoShow.tabSwitch "Control-Tabでタブを切り替える時">
-<!ENTITY config.autoShow.feedback "新しいタブが開かれたりタブが閉じられたりした時">
+<!ENTITY config.autoShow.feedback "タブに何かが起こった時(開く、閉じる、フォーカス移動、タイトルの変化)">
<!ENTITY config.autoShow.feedback.delay.before "">
<!ENTITY config.autoShow.feedback.delay.after "ミリ秒後に自動で隠す">
@@ -135,6 +135,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "最初の子タブを新しい親にする">
<!ENTITY config.closeParentBehavior.promoteAll "閉じた親タブの階層に子孫のタブを移動する">
<!ENTITY config.closeParentBehavior.detach "子孫のタブをツリーから解放する">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "代わりにグループ化用のダミーのタブを開いてツリーを維持する">
<!ENTITY config.closeRootBehavior.promoteFirst "最上位の親タブを閉じた時だけは、最初の子タブを新しい親にする">
<!ENTITY config.insertNewChildAt.caption "新しい子タブを開く位置">
diff --git a/locale/pl/treestyletab/treestyletab.dtd b/locale/pl/treestyletab/treestyletab.dtd
index a08be90..27d47dd 100644
--- a/locale/pl/treestyletab/treestyletab.dtd
+++ b/locale/pl/treestyletab/treestyletab.dtd
@@ -122,7 +122,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "Opóźnienie:">
<!ENTITY config.autoShow.accelKeyDown.delay.after "ms">
<!ENTITY config.autoShow.tabSwitch "Podczas przełączania kart za pomocą skrótu [Ctrl+Tab]">
-<!ENTITY config.autoShow.feedback "Podczas otwierania nowych/zamykania kart">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "Podczas otwierania nowych/zamykania kart"-->
<!ENTITY config.autoShow.feedback.delay.before "Ukrywaj po">
<!ENTITY config.autoShow.feedback.delay.after "ms">
@@ -140,6 +141,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "promuj pierwszą kartę potomną na kartę macierzystą">
<!ENTITY config.closeParentBehavior.promoteAll "promuj wszystkie potomne karty na poziom zamkniętej karty macierzystej">
<!ENTITY config.closeParentBehavior.detach "odłączaj karty potomne od drzewa">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "promuj pierwszą potomną, jeśli zamykana karta nie ma macierzystej">
<!ENTITY config.focusMode "Skrót [Ctrl+Tab] uaktywnia następną/poprzednią kartę nawet jeśli jest niewidoczna">
diff --git a/locale/ru/treestyletab/treestyletab.dtd b/locale/ru/treestyletab/treestyletab.dtd
index 6005e15..ed5bbb5 100755
--- a/locale/ru/treestyletab/treestyletab.dtd
+++ b/locale/ru/treestyletab/treestyletab.dtd
@@ -21,14 +21,14 @@
<!ENTITY config.maxTreeLevel.after "">
<!ENTITY config.allowSubtreeCollapseExpand "Разрешить сворачивать/разворачивать поддеревья вкладок">
<!ENTITY config.tabbarSize.before-horizontal ":">
-<!ENTITY config.tabbarSize.after-horizontal "px height">
+<!ENTITY config.tabbarSize.after-horizontal "пикселей в высоту">
<!ENTITY config.tabbarSize.before-vertical ":">
-<!ENTITY config.tabbarSize.after-vertical "px width">
+<!ENTITY config.tabbarSize.after-vertical "пикселей в ширину">
<!ENTITY config.tabs.style "Стиль">
-<!ENTITY config.tabbar.style.caption "Стиль вкладок на панели">
+<!ENTITY config.tabbar.style.caption "Стиль панели вкладок">
<!ENTITY config.tabbar.style.plain "Plain">
<!ENTITY config.tabbar.style.flat "Flat">
<!ENTITY config.tabbar.style.mixed "Mixed">
@@ -113,14 +113,15 @@
<!ENTITY config.autoShow.caption "Автоматически показывать панель вкладок при">
<!ENTITY config.autoShow.mousemove "Перемещении мышки к краю окна или панели вкладок">
<!ENTITY config.autoHide.area.before "Область срабатывания:">
-<!ENTITY config.autoHide.area.after "пикселов от края окна или панели вкладок">
+<!ENTITY config.autoHide.area.after "пикселей от края окна или панели вкладок">
<!ENTITY config.autoHide.delay.before "Задержка:">
<!ENTITY config.autoHide.delay.after "мсек.">
<!ENTITY config.autoShow.accelKeyDown "При удерживании клавиши Ctrl">
<!ENTITY config.autoShow.accelKeyDown.delay.before "Показывать после">
<!ENTITY config.autoShow.accelKeyDown.delay.after "мсек.">
<!ENTITY config.autoShow.tabSwitch "Переключении вкладок через Ctrl+Tab">
-<!ENTITY config.autoShow.feedback "Закрытии вкладок или открытии новых">
+<!ENTITY config.autoShow.feedback "Изменении вкладок (новая вкладка, закрытие вкладки, изменение фокуса, изменение заголовка)">
+<!--ENTITY config.autoShow.feedback "Закрытии вкладок или открытии новых"-->
<!ENTITY config.autoShow.feedback.delay.before "Скрыть после">
<!ENTITY config.autoShow.feedback.delay.after "мсек.">
@@ -138,6 +139,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "Сделать первую дочернюю вкладку новой родительской">
<!ENTITY config.closeParentBehavior.promoteAll "Переместить все дочерние вкладки на уровень закрытой родительской вкладки">
<!ENTITY config.closeParentBehavior.detach "Переместить дочерние вкладки из дерева">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Заменить закрытую родительскую вкладку пустышкой и сохранить дерево">
<!ENTITY config.closeRootBehavior.promoteFirst "Сделать первую дочернюю вкладку новой родительской, если закрытая родительская вкладка не имела родителя">
<!ENTITY config.focusMode "Переходить по Ctrl+Tab на следующую/предыдущую вкладку даже если она скрыта">
diff --git a/locale/sv-SE/treestyletab/treestyletab.dtd b/locale/sv-SE/treestyletab/treestyletab.dtd
index b153eb2..4f16fd6 100644
--- a/locale/sv-SE/treestyletab/treestyletab.dtd
+++ b/locale/sv-SE/treestyletab/treestyletab.dtd
@@ -126,7 +126,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "Visa efter">
<!ENTITY config.autoShow.accelKeyDown.delay.after "ms">
<!ENTITY config.autoShow.tabSwitch "Ctrl+Tabb för att byta mellan flikar">
-<!ENTITY config.autoShow.feedback "Nya flikar öppnas eller några flikar stängs">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "Nya flikar öppnas eller några flikar stängs"-->
<!ENTITY config.autoShow.feedback.delay.before "Dölj efter">
<!ENTITY config.autoShow.feedback.delay.after "ms">
@@ -144,6 +145,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "Befordra den första underordnade fliken till ny överordnad flik">
<!ENTITY config.closeParentBehavior.promoteAll "Befordra alla underordnade flikar till nivån för den stängda överordnade fliken">
<!ENTITY config.closeParentBehavior.detach "Frigör underordnade flikar från trädet">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "Befordra den första underordnade fliken till ny överordnad, om den stängda fliken var högsta överordnade flik">
<!ENTITY config.focusMode "Fokusera på nästa/föregående flik även om den är osynlig, m.h.a. Ctrl+Tabb">
diff --git a/locale/zh-CN/treestyletab/treestyletab.dtd b/locale/zh-CN/treestyletab/treestyletab.dtd
index 527fcdf..9cdd922 100644
--- a/locale/zh-CN/treestyletab/treestyletab.dtd
+++ b/locale/zh-CN/treestyletab/treestyletab.dtd
@@ -126,7 +126,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "等待">
<!ENTITY config.autoShow.accelKeyDown.delay.after "毫秒再显示">
<!ENTITY config.autoShow.tabSwitch "用Ctrl-Tab切换标签时">
-<!ENTITY config.autoShow.feedback "新建或关闭标签之后">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "新建或关闭标签之后"-->
<!ENTITY config.autoShow.feedback.delay.before "等待">
<!ENTITY config.autoShow.feedback.delay.after "毫秒再自动隐藏">
@@ -144,6 +145,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "提升首个子标签为父标签">
<!ENTITY config.closeParentBehavior.promoteAll "提升所有子标签到父标签的级别">
<!ENTITY config.closeParentBehavior.detach "让子标签脱离树状关系">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "若父标签之上无父标签,则提升首个子标签为父标签">
<!ENTITY config.focusMode "通过“Ctrl-Tab”切换标签时可切换到折叠起来的标签上。">
diff --git a/locale/zh-TW/treestyletab/treestyletab.dtd b/locale/zh-TW/treestyletab/treestyletab.dtd
index 5102cd5..bd15c9e 100644
--- a/locale/zh-TW/treestyletab/treestyletab.dtd
+++ b/locale/zh-TW/treestyletab/treestyletab.dtd
@@ -114,7 +114,8 @@
<!ENTITY config.autoShow.accelKeyDown.delay.before "">
<!ENTITY config.autoShow.accelKeyDown.delay.after "毫秒以上才顯示">
<!ENTITY config.autoShow.tabSwitch "用 Ctrl-Tab 切換分頁時">
-<!ENTITY config.autoShow.feedback "開新分頁或關閉分頁時">
+<!ENTITY config.autoShow.feedback "Something happen on tabs (new tab, closed tab, focus changing, title changing)">
+<!--ENTITY config.autoShow.feedback "開新分頁或關閉分頁時"-->
<!ENTITY config.autoShow.feedback.delay.before "">
<!ENTITY config.autoShow.feedback.delay.after "毫秒後自動隱藏">
@@ -135,6 +136,7 @@
<!ENTITY config.closeParentBehavior.promoteFirst "提升第一個子分頁到父分頁所在階層">
<!ENTITY config.closeParentBehavior.promoteAll "所有子分頁都提升到父分頁所在階層">
<!ENTITY config.closeParentBehavior.detach "從該樹釋放所屬子分頁">
+<!ENTITY config.closeParentBehavior.replaceWithGroupTab "Replace closed parent with a dummy tab and keep the tree">
<!ENTITY config.closeRootBehavior.promoteFirst "只有關閉最頂層的父分頁時,才提升第一子分頁為父分頁">
diff --git a/modules/autoHide.js b/modules/autoHide.js
index 782d504..65712e1 100644
--- a/modules/autoHide.js
+++ b/modules/autoHide.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2015
+ * Portions created by the Initial Developer are Copyright (C) 2010-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -47,6 +47,7 @@ Cu.import('resource://treestyletab-modules/constants.js');
Cu.import('resource://treestyletab-modules/ReferenceCounter.js');
XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
+XPCOMUtils.defineLazyModuleGetter(this, 'TabAttributesObserver', 'resource://treestyletab-modules/tabAttributesObserver.js');
XPCOMUtils.defineLazyGetter(this, 'window', function() {
Cu.import('resource://treestyletab-modules/lib/namespace.jsm');
@@ -57,6 +58,12 @@ XPCOMUtils.defineLazyGetter(this, 'prefs', function() {
return window['piro.sakura.ne.jp'].prefs;
});
+function log(...aArgs) {
+ utils.log.apply(utils, ['autoHide'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['autoHide'].concat(aArgs));
+}
var AutoHideConstants = Object.freeze(inherit(TreeStyleTabConstants, {
kMODE : 'treestyletab-tabbar-autohide-mode',
@@ -75,6 +82,7 @@ var AutoHideConstants = Object.freeze(inherit(TreeStyleTabConstants, {
kSHOWN_BY_SHORTCUT : 1 << 0,
kSHOWN_BY_MOUSEMOVE : 1 << 1,
kSHOWN_BY_FEEDBACK : 1 << 2,
+ kSHOWN_AUTOMATICALLY : (1 << 0) | (1 << 1),
kSHOWN_BY_ANY_REASON : (1 << 0) | (1 << 1) | (1 << 2),
kSHOWHIDE_BY_START : 1 << 3,
kSHOWHIDE_BY_END : 1 << 4,
@@ -361,6 +369,8 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_EXPANDED);
if (!(aReason & this.kSHOWHIDE_BY_API)) {
+ w.addEventListener('blur', this, true);
+ ReferenceCounter.add('w,blur,AHW,true');
b.addEventListener('dragover', this, true);
ReferenceCounter.add('b,dragover,AHW,true');
b.addEventListener('dragleave', this, true);
@@ -412,6 +422,8 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
this.screen.hidePopup();
if (this.userActionListening) {
+ w.removeEventListener('blur', this, true);
+ ReferenceCounter.remove('w,blur,AHW,true');
b.removeEventListener('dragover', this, true);
ReferenceCounter.remove('b,dragover,AHW,true');
b.removeEventListener('dragleave', this, true);
@@ -570,11 +582,10 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
extraInfo.push('expanded-by-unknown');
if (this.lastMouseDownTarget)
extraInfo.push('mousedown');
- dump('showHideOnMouseMove: ' +
+ log('showHideOnMouseMove: ' +
'('+aCoordinates.screenX + ', ' + aCoordinates.screenY + ') => ' +
humanReadablePosition.join(', ') +
- (extraInfo.length ? ('[' + extraInfo.join(', ') + ']') : '') +
- '\n');
+ (extraInfo.length ? ('[' + extraInfo.join(', ') + ']') : ''));
}
if (sv.isPopupShown() ||
@@ -754,7 +765,7 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
// feedback
- showForFeedback : function AHB_showForFeedback()
+ showForFeedback : function AHB_showForFeedback(aTab)
{
if (!this.enabled ||
!utils.getTreePref('tabbar.autoShow.feedback'))
@@ -769,19 +780,21 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
this.delayedShowForFeedbackTimer = w.setTimeout(
function(aSelf) {
aSelf.delayedShowForFeedbackTimer = null;
- aSelf.delayedShowForFeedback();
+ aSelf.delayedShowForFeedback(aTab);
},
100,
this
);
},
- delayedShowForFeedback : function AHB_delayedShowForFeedback()
+ delayedShowForFeedback : function AHB_delayedShowForFeedback(aTab)
{
+ this.treeStyleTab.highlightTab(aTab);
this.show(this.kSHOWN_BY_FEEDBACK);
this.cancelHideForFeedback();
this.delayedHideTabbarForFeedbackTimer = this.window.setTimeout(
function(aSelf) {
+ // TODO: we do something to highlight the given tab.
aSelf.delayedHideTabbarForFeedbackTimer = null;
aSelf.hide(aSelf.kSHOWN_BY_FEEDBACK);
},
@@ -905,10 +918,9 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
let givenReason = this._getHumanReadableReason(aReason);
let unifiedReason = this._getHumanReadableReason(this.showHideReason);
if (this.expanded)
- dump('autoHide: show by ' + aReason + '(' + givenReason + ' / ' + unifiedReason + ')\n');
+ logWithStackTrace('autoHide: show by ' + aReason + '(' + givenReason + ' / ' + unifiedReason + ')');
else
- dump('autoHide: hide by ' + aReason + '(' + givenReason + ' / ' + unifiedReason + ')\n');
- dump((new Error()).stack.replace(/^/gm, ' ').replace(/\s+$/, '') + '\n');
+ logWithStackTrace('autoHide: hide by ' + aReason + '(' + givenReason + ' / ' + unifiedReason + ')');
}
this.fireStateChangingEvent();
@@ -1216,6 +1228,16 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
{
switch (aEvent.type)
{
+ case 'blur':
+ let activeWindow = Cc['@mozilla.org/focus-manager;1']
+ .getService(Ci.nsIFocusManager)
+ .activeWindow;
+ var inactive = !activeWindow || activeWindow != this.window;
+ if (inactive &&
+ this.showHideReason & this.kSHOWN_AUTOMATICALLY)
+ this.hide(this.kSHOWN_BY_ANY_REASON);
+ return;
+
case 'mousedown':
return this.onMouseDown(aEvent);
@@ -1234,17 +1256,26 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
return this.notifyStatusToAllTabs(aEvent.target);
case 'TabOpen':
+ if (utils.getTreePref('tabbar.autoShow.feedback.opened'))
+ this.showForFeedback(aEvent.originalTarget);
+ return;
+
case 'TabClose':
- return this.showForFeedback();
+ if (utils.getTreePref('tabbar.autoShow.feedback.closed'))
+ this.showForFeedback(aEvent.originalTarget);
+ return;
case 'TabMove':
- if (!this.treeStyleTab.subTreeMovingCount && !this.treeStyleTab.internallyTabMovingCount)
- this.showForFeedback();
+ if (utils.getTreePref('tabbar.autoShow.feedback.moved') &&
+ !this.treeStyleTab.subTreeMovingCount &&
+ !this.treeStyleTab.isTabInternallyMoving(aEvent.originalTarget))
+ this.showForFeedback(aEvent.originalTarget);
return;
case 'select':
- if (!this.window.TreeStyleTabService.accelKeyPressed)
- this.showForFeedback();
+ if (utils.getTreePref('tabbar.autoShow.feedback.selected') &&
+ !this.window.TreeStyleTabService.accelKeyPressed)
+ this.showForFeedback(aEvent.originalTarget);
return;
case 'dragover':
@@ -1310,7 +1341,7 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
if (
aEvent.target &&
!this.isResizing &&
- sv.evaluateXPath(
+ utils.evaluateXPath(
'ancestor-or-self::*[@class="'+sv.kSPLITTER+'"]',
aEvent.originalTarget || aEvent.target,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
@@ -1342,7 +1373,7 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
var sv = this.treeStyleTab;
if (this.isResizing &&
aEvent.originalTarget &&
- sv.evaluateXPath(
+ utils.evaluateXPath(
'ancestor-or-self::*[@class="'+sv.kSPLITTER+'"]',
aEvent.originalTarget,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
@@ -1454,6 +1485,12 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
delayedShowForShortcutTimer : null,
delayedShowForShortcutDone : true,
+
+ onTabTitleChanged : function AHB_onTabTitleChanged(aTab)
+ {
+ if (utils.getTreePref('tabbar.autoShow.feedback.titleChanged'))
+ this.showForFeedback(aTab);
+ },
init : function AHB_init(aTabBrowser)
{
@@ -1500,6 +1537,15 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
ReferenceCounter.add('b,kEVENT_TYPE_TAB_FOCUS_SWITCHING_START,AHW,false');
b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false);
ReferenceCounter.add('b,kEVENT_TYPE_TAB_FOCUS_SWITCHING_END,AHW,false');
+
+ this.tabsAttributeObserver = new TabAttributesObserver({
+ container : b.mTabContainer,
+ attributes : 'titlechanged',
+ callback : (function(aTab) {
+ if (aTab.getAttribute('titlechanged') == 'true')
+ this.onTabTitleChanged(aTab);
+ }).bind(this)
+ });
},
destroy : function AHB_destroy()
@@ -1507,6 +1553,9 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, {
this.end();
prefs.removePrefListener(this);
+ this.tabsAttributeObserver.destroy();
+ delete this.tabsAttributeObserver;
+
var sv = this.treeStyleTab;
var b = this.browser;
b.mTabContainer.removeEventListener('TabOpen', this, false);
@@ -1636,8 +1685,7 @@ AutoHideWindow.prototype = inherit(AutoHideBase.prototype, {
get shouldListenKeyEvents()
{
- return !this.treeStyleTab.ctrlTabPreviewsEnabled &&
- (
+ return (
utils.getTreePref('tabbar.autoShow.accelKeyDown') ||
utils.getTreePref('tabbar.autoShow.tabSwitch') ||
utils.getTreePref('tabbar.autoShow.feedback')
@@ -1706,8 +1754,7 @@ AutoHideWindow.prototype = inherit(AutoHideBase.prototype, {
},
domains : [
- 'extensions.treestyletab.',
- 'browser.ctrlTab.previews'
+ 'extensions.treestyletab.'
],
onPrefChange : function AHW_onPrefChange(aPrefName)
@@ -1719,7 +1766,6 @@ AutoHideWindow.prototype = inherit(AutoHideBase.prototype, {
case 'extensions.treestyletab.tabbar.autoShow.accelKeyDown':
case 'extensions.treestyletab.tabbar.autoShow.tabSwitch':
case 'extensions.treestyletab.tabbar.autoShow.feedback':
- case 'browser.ctrlTab.previews':
this.updateKeyListeners(this.window);
default:
diff --git a/modules/base.js b/modules/base.js
index 3a4452f..75093cc 100644
--- a/modules/base.js
+++ b/modules/base.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2014
+ * Portions created by the Initial Developer are Copyright (C) 2010-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -81,6 +81,13 @@ if (Services.appinfo.OS === 'WINNT') {
else {
this.AeroPeek = null;
}
+
+function log(...aArgs) {
+ utils.log.apply(utils, ['base'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['base'].concat(aArgs));
+}
var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
@@ -132,12 +139,10 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
this.onPrefChange('extensions.treestyletab.indent.vertical');
this.onPrefChange('extensions.treestyletab.indent.horizontal');
this.onPrefChange('extensions.treestyletab.clickOnIndentSpaces.enabled');
- this.onPrefChange('browser.tabs.insertRelatedAfterCurrent.override');
this.onPrefChange('extensions.stm.tabBarMultiRows.override'); // Super Tab Mode
this.onPrefChange('extensions.treestyletab.tabbar.scroll.smooth');
this.onPrefChange('extensions.treestyletab.tabbar.scroll.duration');
this.onPrefChange('extensions.treestyletab.tabbar.scrollToNewTab.mode');
- this.onPrefChange('extensions.treestyletab.tabbar.narrowScrollbar.size');
this.onPrefChange('browser.tabs.animate');
this.onPrefChange('extensions.treestyletab.animation.indent.duration');
this.onPrefChange('extensions.treestyletab.animation.collapse.duration');
@@ -149,8 +154,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
this.overrideExtensions();
}
catch(e) {
- if (utils.isDebugging('base'))
- dump(e+'\n');
+ log(e);
}
},
_initialized : false,
@@ -184,7 +188,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
prefs.removePrefListener(this);
let restorePrefs = [
- 'browser.tabs.insertRelatedAfterCurrent',
'extensions.stm.tabBarMultiRows' // Super Tab Mode
];
for (let i = 0, maxi = restorePrefs.length; i < maxi; i++)
@@ -230,69 +233,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
}
},
- updateNarrowScrollbarStyle : function TSTBase_updateNarrowScrollbarStyle()
- {
- const SSS = Cc['@mozilla.org/content/style-sheet-service;1']
- .getService(Ci.nsIStyleSheetService);
-
- if (this.lastAgentSheet &&
- SSS.sheetRegistered(this.lastAgentSheet, SSS.AGENT_SHEET))
- SSS.unregisterSheet(this.lastAgentSheet, SSS.AGENT_SHEET);
-
- const style = 'data:text/css,'+encodeURIComponent(
- ('@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");' +
-
- 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
- ' .tabbrowser-arrowscrollbox' +
- ' > scrollbox' +
- ' > scrollbar[orient="vertical"],' +
- 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
- ' .tabbrowser-arrowscrollbox' +
- ' > scrollbox' +
- ' > scrollbar[orient="vertical"] * {' +
- ' max-width: %SIZE%;' +
- ' min-width: %SIZE%;' +
- '}' +
-
- 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
- ' .tabbrowser-arrowscrollbox' +
- ' > scrollbox' +
- ' > scrollbar[orient="vertical"] {' +
- ' font-size: %SIZE%;' +
- '}' +
-
- 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
- ' .tabbrowser-arrowscrollbox' +
- ' > scrollbox' +
- ' > scrollbar[orient="vertical"] * {' +
- ' padding-left: 0;' +
- ' padding-right: 0;' +
- ' margin-left: 0;' +
- ' margin-right: 0;' +
- '}' +
-
- '%FORCE_NARROW_SCROLLBAR%')
- .replace(/%FORCE_NARROW_SCROLLBAR%/g,
- utils.getTreePref('tabbar.narrowScrollbar.overrideSystemAppearance') ?
- this.kOVERRIDE_SYSTEM_SCROLLBAR_APPEARANCE : '' )
- .replace(/%MODE%/g, this.kMODE)
- .replace(/%NARROW%/g, this.kNARROW_SCROLLBAR)
- .replace(/%SIZE%/g, utils.getTreePref('tabbar.narrowScrollbar.size'))
- );
- this.lastAgentSheet = this.makeURIFromSpec(style);
- SSS.loadAndRegisterSheet(this.lastAgentSheet, SSS.AGENT_SHEET);
- },
- kOVERRIDE_SYSTEM_SCROLLBAR_APPEARANCE :
- 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
- ' .tabbrowser-arrowscrollbox' +
- ' > scrollbox' +
- ' > scrollbar[orient="vertical"] {' +
- ' appearance: none;' +
- ' -moz-appearance: none;' +
- ' background: ThreeDFace;' +
- ' border: 1px solid ThreeDShadow;' +
- '}',
- lastAgentSheet : null,
/* references to the owner */
@@ -372,10 +312,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
return behavior
},
- kDROPLINK_ASK : 0,
- kDROPLINK_FIXED : 1 + 2,
- kDROPLINK_LOAD : 1,
- kDROPLINK_NEWTAB : 2,
openGroupBookmarkBehavior : function TSTBase_openGroupBookmarkBehavior()
{
@@ -411,14 +347,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
}
return behavior;
},
- kGROUP_BOOKMARK_ASK : 0,
- kGROUP_BOOKMARK_FIXED : 1 + 2 + 4,
- kGROUP_BOOKMARK_SUBTREE : 1,
- kGROUP_BOOKMARK_SEPARATE : 2,
- kGROUP_BOOKMARK_USE_DUMMY : 256,
- kGROUP_BOOKMARK_USE_DUMMY_FORCE : 1024,
- kGROUP_BOOKMARK_DONT_RESTORE_TREE_STRUCTURE : 512,
- kGROUP_BOOKMARK_EXPAND_ALL_TREE : 2048,
bookmarkDroppedTabsBehavior : function TSTBase_bookmarkDroppedTabsBehavior()
{
@@ -519,8 +447,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
var message = 'ERROR: accessed after destruction!';
var error = new Error(message);
- if (utils.isDebugging('base'))
- dump(message+'\n'+error.stack.replace(/^/gm, ' ')+'\n');
+ logWithStackTrace(message);
throw error;
},
@@ -560,7 +487,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
isEventFiredOnClosebox : function TSTBase_isEventFiredOnClosebox(aEvent)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::*[contains(concat(" ", normalize-space(@class), " "), " tab-close-button ")]',
aEvent.originalTarget || aEvent.target,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
@@ -569,7 +496,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
isEventFiredOnClickable : function TSTBase_isEventFiredOnClickable(aEvent)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::*[contains(" button toolbarbutton scrollbar nativescrollbar popup menupopup panel tooltip splitter textbox ", concat(" ", local-name(), " "))]',
aEvent.originalTarget,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
@@ -578,7 +505,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
isEventFiredOnScrollbar : function TSTBase_isEventFiredOnScrollbar(aEvent)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::*[local-name()="scrollbar" or local-name()="nativescrollbar"]',
aEvent.originalTarget,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
@@ -715,92 +642,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
{
return 'tabs-closed-set-<'+Date.now()+'-'+parseInt(Math.random() * 65000)+'>';
},
-
- makeURIFromSpec : function TSTBase_makeURIFromSpec(aURI)
- {
- var newURI;
- aURI = aURI || '';
- if (aURI && String(aURI).indexOf('file:') == 0) {
- var fileHandler = Services.io.getProtocolHandler('file').QueryInterface(Ci.nsIFileProtocolHandler);
- var tempLocalFile = fileHandler.getFileFromURLSpec(aURI);
- newURI = Services.io.newFileURI(tempLocalFile);
- }
- else {
- if (!/^\w+\:/.test(aURI))
- aURI = 'http://'+aURI;
- newURI = Services.io.newURI(aURI, null, null);
- }
- return newURI;
- },
-
- getGroupTabURI : function TSTBase_getGroupTabURI(aOptions)
- {
- aOptions = aOptions || {};
- var parameters = [];
- parameters.push('title=' + encodeURIComponent(aOptions.title || ''));
- parameters.push('temporary=' + !!aOptions.temporary);
- return 'about:treestyletab-group?' + parameters.join('&');
- },
-
-// xpath
-
- NSResolver : {
- lookupNamespaceURI : function(aPrefix)
- {
- switch (aPrefix)
- {
- case 'xul':
- return 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
- case 'html':
- case 'xhtml':
- return 'http://www.w3.org/1999/xhtml';
- case 'xlink':
- return 'http://www.w3.org/1999/xlink';
- default:
- return '';
- }
- }
- },
-
- evaluateXPath : function TSTBase_evaluateXPath(aExpression, aContext, aType)
- {
- if (!aType)
- aType = Ci.nsIDOMXPathResult.ORDERED_NODE_SNAPSHOT_TYPE;
- try {
- var XPathResult = (aContext.ownerDocument || aContext).evaluate(
- aExpression,
- (aContext || document),
- this.NSResolver,
- aType,
- null
- );
- }
- catch(e) {
- return {
- singleNodeValue : null,
- snapshotLength : 0,
- snapshotItem : function() {
- return null
- }
- };
- }
- return XPathResult;
- },
-
- getArrayFromXPathResult : function TSTBase_getArrayFromXPathResult(aXPathResult)
- {
- var max = aXPathResult.snapshotLength;
- var array = new Array(max);
- if (!max)
- return array;
-
- for (var i = 0; i < max; i++)
- {
- array[i] = aXPathResult.snapshotItem(i);
- }
-
- return array;
- },
/* Session Store API */
@@ -903,7 +744,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
var strip = aTabBrowser.mStrip;
return (strip && strip instanceof this.window.Element) ?
strip :
- this.evaluateXPath(
+ utils.evaluateXPath(
'ancestor::xul:toolbar[1]',
aTabBrowser.tabContainer,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -951,10 +792,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
{
var strip = this.tabStrip;
if (!strip) {
- if (utils.isDebugging('base')) {
- dump('FAILED TO SET TABSTRIP ATTRIBUTE ' + aAttr + '=' + aValue + '\n');
- dump((new Error()).stack.replace(/^/gm, ' ') + '\n');
- }
+ logWithStackTrace('FAILED TO SET TABSTRIP ATTRIBUTE ' + aAttr + '=' + aValue);
return;
}
var isFeatureAttribute = aAttr.indexOf('treestyletab-') == 0;
@@ -995,7 +833,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
getTabFromChild : function TSTBase_getTabFromChild(aTab)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::xul:tab',
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -1009,7 +847,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
getNewTabButtonFromEvent : function TSTBase_getNewTabButtonFromEvent(aEvent)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::*['
+'@id="new-tab-button" or '
+'contains(concat(" ", normalize-space(@class), " "), " tabs-newtab-button ")'
@@ -1021,7 +859,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
getSplitterFromEvent : function TSTBase_getSplitterFromEvent(aEvent)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::xul:splitter[contains(concat(" ", normalize-space(@class), " "), " '+this.kSPLITTER+' ")]',
aEvent.originalTarget,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -1030,7 +868,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
isEventFiredOnGrippy : function TSTBase_isEventFiredOnGrippy(aEvent)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::xul:grippy',
aEvent.originalTarget,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
@@ -1070,7 +908,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
getTabbarFromChild : function TSTBase_getTabbarFromChild(aNode)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::*[contains(concat(" ", normalize-space(@class), " "), " tabbrowser-strip ")] | ' +
'ancestor-or-self::xul:tabs[@tabbrowser] | ' +
'ancestor-or-self::xul:toolbar/child::xul:tabs[@tabbrowser]',
@@ -1080,7 +918,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
},
getAncestorTabbarFromChild : function TSTBase_getAncestorTabbarFromChild(aNode)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::*[contains(concat(" ", normalize-space(@class), " "), " tabbrowser-strip ")] | ' +
'ancestor-or-self::xul:tabs[@tabbrowser]',
aNode,
@@ -1162,38 +1000,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
getTabBrowserFromChild : function TSTBase_getTabBrowserFromChild(aTabBrowserChild)
{
- if (!aTabBrowserChild)
- return null;
-
- if (aTabBrowserChild.__treestyletab__linkedTabBrowser) // tab
- return aTabBrowserChild.__treestyletab__linkedTabBrowser;
-
- if (aTabBrowserChild.localName == 'tabbrowser') // itself
- return aTabBrowserChild;
-
- if (aTabBrowserChild.tabbrowser) // tabs
- return aTabBrowserChild.tabbrowser;
-
- if (aTabBrowserChild.localName == 'toolbar') // tabs toolbar
- return aTabBrowserChild.getElementsByTagName('tabs')[0].tabbrowser;
-
- // tab context menu
- var popup = this.evaluateXPath(
- 'ancestor-or-self::xul:menupopup[@id="tabContextMenu"]',
- aTabBrowserChild,
- Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
- ).singleNodeValue;
- if (popup && 'TabContextMenu' in aTabBrowserChild.ownerDocument.defaultView)
- return this.getTabBrowserFromChild(aTabBrowserChild.ownerDocument.defaultView.TabContextMenu.contextTab);
-
- var b = this.evaluateXPath(
- 'ancestor::xul:tabbrowser | '+
- 'ancestor::xul:tabs[@tabbrowser] |'+
- 'ancestor::xul:toolbar/descendant::xul:tabs',
- aTabBrowserChild,
- Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
- ).singleNodeValue;
- return (b && b.tabbrowser) || b;
+ return utils.getTabBrowserFromChild(aTabBrowserChild);
},
getTabBrowserFromFrame : function TSTBase_getTabBrowserFromFrame(aFrame)
@@ -1464,6 +1271,20 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
},
/**
+ * Returns tabs which are newly opened from the given task.
+ */
+ doAndGetNewTabs : function TSTBase_doAndGetNewTabs(aTask, aTabBrowser)
+ {
+ var previousTabs = this.getTabsInfo(aTabBrowser);
+ try {
+ aTask();
+ }
+ catch(e) {
+ Components.utils.reportError(e);
+ }
+ return this.getNewTabsFromPreviousTabsInfo(aTabBrowser, previousTabs);
+ },
+ /**
* Returns tabs which are newly opened. This requires the "previous state".
*/
getNewTabsFromPreviousTabsInfo : function TSTBase_getNewTabsFromPreviousTabsInfo(aTabBrowser, aTabsInfo)
@@ -1510,9 +1331,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
refId = aInsertBefore.getAttribute(this.kID);
}
- if (utils.isDebugging('base'))
- dump('Tree Style Tab: new child tab is requested.\n'+
- new Error().stack.replace(/^/gm, ' ')+'\n');
+ logWithStackTrace('new child tab is requested.');
ownerBrowser.treeStyleTab.readiedToAttachNewTab = true;
ownerBrowser.treeStyleTab.readiedToAttachMultiple = aMultiple || false ;
@@ -1543,6 +1362,41 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
return false;
},
+ readyToOpenOrphanTab : function TSTBase_readyToOpenOrphanTab(aTabOrSomething) /* PUBLIC API */
+ {
+ var browser = this.getBrowserFromTabBrowserElements(aTabOrSomething);
+ if (!browser)
+ return false;
+
+ var ownerBrowser = this.getTabBrowserFromChild(browser);
+
+ logWithStackTrace('new orphan tab is requested.');
+
+ ownerBrowser.treeStyleTab.readiedToAttachNewTab = false;
+
+ return true;
+ },
+ /**
+ * Extended version. If you don't know whether a new tab will be actually
+ * opened or not (by the command called after TST's API), then use this.
+ * This version automatically cancels the "ready" state with delay.
+ */
+ readyToOpenOrphanTabNow : function TSTBase_readyToOpenOrphanTabNow(...aArgs) /* PUBLIC API */
+ {
+ if (this.readyToOpenOrphanTab.apply(this, aArgs)) {
+ setTimeout((function() {
+ try {
+ this.stopToOpenChildTab(aArgs[0]);
+ }
+ catch(e) {
+ this.defaultErrorHandler(e);
+ }
+ }).bind(this), 0);
+ return true;
+ }
+ return false;
+ },
+
readyToOpenNextSiblingTab : function TSTBase_readyToOpenNextSiblingTab(aTabOrSomething) /* PUBLIC API */
{
var browser = this.getBrowserFromTabBrowserElements(aTabOrSomething);
@@ -1611,6 +1465,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
this.stopToOpenChildTab(browser);
var ownerBrowser = this.getTabBrowserFromChild(browser);
+ ownerBrowser.treeStyleTab.readiedToAttachNewTab = false;
ownerBrowser.treeStyleTab.readiedToAttachNewTabGroup = true;
ownerBrowser.treeStyleTab.readiedToAttachMultiple = true;
ownerBrowser.treeStyleTab.multipleCount = 0;
@@ -1649,18 +1504,17 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
var ownerBrowser = this.getTabBrowserFromChild(browser);
- if (ownerBrowser.treeStyleTab.readiedToAttachNewTab && utils.isDebugging('base'))
- dump('Tree Style Tab: new child tab is canceled.\n'+
- new Error().stack.replace(/^/gm, ' ')+'\n');
+ if (ownerBrowser.treeStyleTab.readiedToAttachNewTab)
+ logWithStackTrace('new child tab is canceled.');
- ownerBrowser.treeStyleTab.readiedToAttachNewTab = false;
- ownerBrowser.treeStyleTab.readiedToAttachNewTabGroup = false;
- ownerBrowser.treeStyleTab.readiedToAttachMultiple = false;
- ownerBrowser.treeStyleTab.multipleCount = -1;
- ownerBrowser.treeStyleTab.parentTab = null;
- ownerBrowser.treeStyleTab.insertBefore = null;
- ownerBrowser.treeStyleTab.treeStructure = null;
- ownerBrowser.treeStyleTab.shouldExpandAllTree = false;
+ delete ownerBrowser.treeStyleTab.readiedToAttachNewTab;
+ delete ownerBrowser.treeStyleTab.readiedToAttachNewTabGroup;
+ delete ownerBrowser.treeStyleTab.readiedToAttachMultiple;
+ delete ownerBrowser.treeStyleTab.multipleCount;
+ delete ownerBrowser.treeStyleTab.parentTab;
+ delete ownerBrowser.treeStyleTab.insertBefore;
+ delete ownerBrowser.treeStyleTab.treeStructure;
+ delete ownerBrowser.treeStyleTab.shouldExpandAllTree;
return true;
},
@@ -1693,6 +1547,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
case this.kNEWTAB_OPEN_AS_ORPHAN:
case this.kNEWTAB_DO_NOTHING:
default:
+ this.readyToOpenOrphanTabNow(aBaseTab);
break;
case this.kNEWTAB_OPEN_AS_CHILD:
this.readyToOpenChildTabNow(aBaseTab);
@@ -1820,7 +1675,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
}
}
else {
- parent = this.evaluateXPath(
+ parent = utils.evaluateXPath(
'preceding-sibling::xul:tab[@'+this.kID+'="'+id+'"][1]',
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -1843,8 +1698,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
aTab.label+'\n '+
aTab.getAttribute(this.kID);
}, this).join('\n');
- if (utils.isDebugging('base'))
- dump(message+'\n');
+ log(message);
break;
}
@@ -1856,8 +1710,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
aTab.label+'\n '+
aTab.getAttribute(this.kID);
}, this).join('\n');
- if (utils.isDebugging('base'))
- dump(message+'\n');
+ log(message);
}
tabs.push(parentTab);
@@ -1876,7 +1729,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
return ancestors.length ? ancestors[ancestors.length-1] : aTab ;
}
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'(self::*[not(@'+this.kPARENT+')] | preceding-sibling::xul:tab[not(@'+this.kPARENT+')])[last()]',
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -1917,7 +1770,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
}
var parent = aTab.getAttribute(this.kPARENT);
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'following-sibling::xul:tab['+
(parent ? '@'+this.kPARENT+'="'+parent+'"' : 'not(@'+this.kPARENT+')' )+
'][1]',
@@ -1959,7 +1812,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
}
var parent = aTab.getAttribute(this.kPARENT);
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'preceding-sibling::xul:tab['+
(parent ? '@'+this.kPARENT+'="'+parent+'"' : 'not(@'+this.kPARENT+')' )+
'][1]',
@@ -2004,8 +1857,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
aTab.label+'\n '+
aTab.getAttribute(this.kID);
}, this).join('\n');
- if (utils.isDebugging('base'))
- dump(message+'\n');
+ log(message);
continue;
}
tabs.push(tab);
@@ -2050,7 +1902,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
return firstChild;
}
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'following-sibling::xul:tab[@'+this.kPARENT+'="'+aTab.getAttribute(this.kID)+'"][1]',
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -2077,7 +1929,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
return lastChild;
}
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'following-sibling::xul:tab[@'+this.kPARENT+'="'+aTab.getAttribute(this.kID)+'"][last()]',
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -2146,7 +1998,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
'[not(@'+this.kCOLLAPSED+'="true")]' :
'' ;
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'sum((self::* | preceding-sibling::xul:tab[not(@hidden="true")]'+extraCondition+')'+
'/attribute::'+this.kX_OFFSET+')',
aTab,
@@ -2159,7 +2011,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
'[not(@'+this.kCOLLAPSED+'="true")]' :
'';
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'sum((self::* | preceding-sibling::xul:tab[not(@hidden="true")]'+extraCondition+')'+
'/attribute::'+this.kY_OFFSET+')',
aTab,
@@ -2213,16 +2065,13 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
isGroupTab : function TSTBase_isGroupTab(aTab, aLazyCheck)
{
- return (
- (aLazyCheck || aTab.linkedBrowser.sessionHistory.count == 1) &&
- aTab.linkedBrowser.currentURI.spec.indexOf('about:treestyletab-group') == 0
- );
+ return aTab.linkedBrowser.currentURI.spec.indexOf('about:treestyletab-group') == 0;
},
isTemporaryGroupTab : function TSTBase_isTemporaryGroupTab(aTab)
{
return (
- this.isGroupTab(aTab, true) &&
+ this.isGroupTab(aTab) &&
/.*[\?&;]temporary=(?:1|yes|true)/i.test(aTab.linkedBrowser.currentURI.spec)
);
},
@@ -2246,48 +2095,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
return collapsedStates;
},
- getTreeStructureFromTabs : function TSTBase_getTreeStructureFromTabs(aTabs)
- {
- /* this returns...
- [A] => -1 (parent is not in this tree)
- [B] => 0 (parent is 1st item in this tree)
- [C] => 0 (parent is 1st item in this tree)
- [D] => 2 (parent is 2nd in this tree)
- [E] => -1 (parent is not in this tree, and this creates another tree)
- [F] => 0 (parent is 1st item in this another tree)
- */
- return this.cleanUpTreeStructureArray(
- aTabs.map(function(aTab, aIndex) {
- let tab = this.getParentTab(aTab);
- let index = tab ? aTabs.indexOf(tab) : -1 ;
- return index >= aIndex ? -1 : index ;
- }, this),
- -1
- );
- },
- cleanUpTreeStructureArray : function TSTBase_cleanUpTreeStructureArray(aTreeStructure, aDefaultParent)
- {
- var offset = 0;
- aTreeStructure = aTreeStructure
- .map(function(aPosition, aIndex) {
- return (aPosition == aIndex) ? -1 : aPosition ;
- })
- .map(function(aPosition, aIndex) {
- if (aPosition == -1) {
- offset = aIndex;
- return aPosition;
- }
- return aPosition - offset;
- });
-
- /* The final step, this validates all of values.
- Smaller than -1 is invalid, so it becomes to -1. */
- aTreeStructure = aTreeStructure.map(function(aIndex) {
- return aIndex < -1 ? aDefaultParent : aIndex ;
- }, this);
- return aTreeStructure;
- },
-
applyTreeStructureToTabs : function TSTBase_applyTreeStructureToTabs(aTabs, aTreeStructure, aExpandStates)
{
var b = this.getTabBrowserFromChild(aTabs[0]);
@@ -2339,7 +2146,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
getTreeStructureFromTabBrowser : function TSTBase_getTreeStructureFromTabBrowser(aTabBrowser)
{
- return this.getTreeStructureFromTabs(this.getAllTabs(aTabBrowser));
+ return utils.getTreeStructureFromTabs(this.getAllTabs(aTabBrowser));
},
applyTreeStructureToTabBrowser : function TSTBase_applyTreeStructureToTabBrowser(aTabBrowser, aTreeStructure, aExpandAllTree)
@@ -2403,7 +2210,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
domains : [
'extensions.treestyletab.',
'browser.tabs.animate',
- 'browser.tabs.insertRelatedAfterCurrent',
'extensions.stm.tabBarMultiRows' // Super Tab Mode
],
@@ -2435,13 +2241,11 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
case 'extensions.treestyletab.tabbar.shrunkenWidth':
return this.correctMismatchedTabWidthPrefs(aPrefName);
- case 'browser.tabs.insertRelatedAfterCurrent':
case 'extensions.stm.tabBarMultiRows': // Super Tab Mode
if (this.prefOverriding)
return;
aPrefName += '.override';
prefs.setPref(aPrefName, value);
- case 'browser.tabs.insertRelatedAfterCurrent.override':
case 'extensions.stm.tabBarMultiRows.override': // Super Tab Mode
if (prefs.getPref(aPrefName+'.force')) {
let defaultValue = prefs.getDefaultPref(aPrefName);
@@ -2472,9 +2276,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
case 'extensions.treestyletab.tabbar.scrollToNewTab.mode':
return this.scrollToNewTabMode = value;
- case 'extensions.treestyletab.tabbar.narrowScrollbar.size':
- return this.updateNarrowScrollbarStyle();
-
case 'browser.tabs.animate':
return this.animationEnabled = value;
case 'extensions.treestyletab.animation.indent.duration':
diff --git a/modules/bookmark.js b/modules/bookmark.js
new file mode 100644
index 0000000..943d25c
--- /dev/null
+++ b/modules/bookmark.js
@@ -0,0 +1,504 @@
+/* ***** 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 Tree Style Tab.
+ *
+ * The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
+ * Portions created by the Initial Developer are Copyright (C) 2016
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.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 ******/
+
+var EXPORTED_SYMBOLS = ['TreeStyleTabBookmarksService'];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+Cu.import('resource:///modules/PlacesUIUtils.jsm');
+Cu.import('resource://gre/modules/PlacesUtils.jsm');
+
+Cu.import('resource://treestyletab-modules/lib/inherit.jsm');
+Cu.import('resource://treestyletab-modules/constants.js');
+
+XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
+
+function log(...aArgs) {
+ utils.log.apply(utils, ['bookmark'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['bookmark'].concat(aArgs));
+}
+
+var TreeStyleTabBookmarksService = inherit(TreeStyleTabConstants, {
+ get BookmarksService() {
+ if (!this._BookmarksService) {
+ this._BookmarksService = Cc['@mozilla.org/browser/nav-bookmarks-service;1']
+ .getService(Ci.nsINavBookmarksService);
+ }
+ return this._BookmarksService;
+ },
+ _BookmarksService : null,
+
+
+ beginAddBookmarksFromTabs : function TSTBMService_beginAddBookmarksFromTabs(aTabs) /* PUBLIC API */
+ {
+ if (this._observing ||
+ !aTabs ||
+ aTabs.length <= 0)
+ return;
+
+ this._observing = true;
+
+ var TST = aTabs[0].ownerDocument.defaultView.TreeStyleTabService;
+ aTabs = TST.cleanUpTabsArray(aTabs);
+
+ this._addingBookmarks = [];
+ this._addingBookmarkTreeStructure = aTabs.map(function(aTab) {
+ var parent = TST.getParentTab(aTab);
+ return aTabs.indexOf(parent);
+ }, this);
+
+ this.BookmarksService.addObserver(this, false);
+ },
+
+ endAddBookmarksFromTabs : function TSTBMService_endAddBookmarksFromTabs() /* PUBLIC API */
+ {
+ if (!this._observing)
+ return;
+
+ this._observing = false;
+
+ this.BookmarksService.removeObserver(this);
+ this.handleNewBookmarksFromTabs(this._addingBookmarks, this._addingBookmarkTreeStructure);
+ this._addingBookmarks = [];
+ this._addingBookmarkTreeStructure = [];
+ },
+
+ handleNewBookmarksFromTabs : function TSTBMService_handleNewBookmarksFromTabs(aBookarmks, aTreeStructure)
+ {
+ // this is adding bookmark folder from tabs, so ignroe the first item!
+ if (
+ aBookarmks.length == aTreeStructure.length+1 &&
+ this.BookmarksService.getItemType(aBookarmks[0].id) == this.BookmarksService.TYPE_FOLDER
+ ) {
+ aBookarmks.shift();
+ }
+ else if (aBookarmks.length != aTreeStructure.length) {
+ return;
+ }
+
+ for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
+ {
+ let item = aBookarmks[i];
+ item.position = this.BookmarksService.getItemIndex(item.id);
+ }
+ aBookarmks.sort(function(aA, aB) {
+ return aA.position - aB.position;
+ });
+
+ for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
+ {
+ let item = aBookarmks[i];
+ if (this.BookmarksService.getItemType(item.id) != this.BookmarksService.TYPE_BOOKMARK)
+ continue;
+
+ let uri = this.BookmarksService.getBookmarkURI(item.id);
+ if (/^about:treestyletab-group\b/.test(uri.spec)) {
+ let title = this.BookmarksService.getItemTitle(item.id);
+ let folderId = this.BookmarksService.createFolder(item.parent, title, item.position);
+ this.BookmarksService.removeItem(item.id);
+ item.id = folderId;
+ item.isFolder = true;
+ }
+
+ let index = aTreeStructure[i];
+ let parent = index > -1 ? aBookarmks[index] : null ;
+ if (parent && (parent.folder || parent).isFolder) {
+ let folder = parent.isFolder ? parent : parent.folder ;
+ this.BookmarksService.moveItem(item.id, folder.id, -1);
+ item.folder = folder;
+ }
+ if (parent && !parent.isFolder) {
+ PlacesUtils.setAnnotationsForItem(item.id, [{
+ name : this.kPARENT,
+ value : parent ? parent.id : -1,
+ expires : PlacesUtils.annotations.EXPIRE_NEVER
+ }]);
+ }
+ }
+ },
+
+ bookmarkTabSubtree : function TSTBMService_bookmarkTabSubtree(aTabOrTabs)
+ {
+ var tabs = aTabOrTabs;
+ if (!Array.isArray(tabs)) {
+ tabs = [aTabOrTabs];
+ }
+ if (tabs.length <= 0)
+ return;
+
+ var window = tabs[0].ownerDocument.defaultView;
+ var TST = window.TreeStyleTabService;
+
+ var folderName = (TST.isGroupTab(tabs[0]) || tabs.length == 1) ?
+ tabs[0].label :
+ null ;
+
+ var b = TST.getTabBrowserFromChild(tabs[0]);
+ var bookmarkedTabs = [];
+ for (let i = 0, maxi = tabs.length; i < maxi; i++)
+ {
+ let tab = tabs[i];
+ if (!TST.isGroupTab(tab))
+ bookmarkedTabs.push(tab);
+ bookmarkedTabs = bookmarkedTabs.concat(b.treeStyleTab.getDescendantTabs(tab));
+ }
+
+ this.beginAddBookmarksFromTabs(bookmarkedTabs);
+ try {
+ window['piro.sakura.ne.jp'].bookmarkMultipleTabs.addBookmarkFor(bookmarkedTabs, folderName);
+ }
+ catch(e) {
+ }
+ this.endAddBookmarksFromTabs();
+ },
+ bookmarkTabSubTree : function() { return this.bookmarkTabSubtree.apply(this, arguments); }, // obsolete, for backward compatibility
+
+ getParentItem : function TSTBMService_getParentItem(aId)
+ {
+ if (aId < 0) return -1;
+ var annotations = PlacesUtils.getAnnotationsForItem(aId);
+ for (let i in annotations)
+ {
+ if (annotations[i].name != this.kPARENT) continue;
+ return parseInt(annotations[i].value);
+ }
+ return -1;
+ },
+
+ getTreeStructureFromItems : function TSTBMService_getTreeStructureFromItems(aIDs, aDefaultParentID)
+ {
+ /* this returns a result same to utils.getTreeStructureFromTabs().
+ [A] => -1 (parent is not in this tree)
+ [B] => 0 (parent is 1st item in this tree)
+ [C] => 0 (parent is 1st item in this tree)
+ [D] => 2 (parent is 2nd in this tree)
+ [E] => -1 (parent is not in this tree, and this creates another tree)
+ [F] => 0 (parent is 1st item in this another tree)
+ */
+ if (aDefaultParentID === void(0))
+ aDefaultParentID = -1;
+
+ /* Get array of parents. The index becomes to -1,
+ if there is NO PARENT or the parent is THE TAB ITSELF. */
+ var treeStructure = aIDs.map(function(aId, aIndex) {
+ let id = this.getParentItem(aId);
+ let index = aIDs.indexOf(id);
+ return index >= aIndex ? aDefaultParentID : index ;
+ }, this);
+
+ /* Correct patterns like:
+ [TabA]
+ [TabB] - this has no parent
+ [TabC] - TabA's child
+ to:
+ [TabA]
+ [TabB]
+ [TabC]
+ */
+ treeStructure = treeStructure.reverse();
+ treeStructure = treeStructure.map(function(aPosition, aIndex) {
+ if (aIndex > 0 &&
+ aIndex < treeStructure.length-1 &&
+ aPosition < 0) {
+ aPosition = treeStructure[aIndex-1];
+ }
+ return aPosition;
+ });
+ treeStructure = treeStructure.reverse();
+
+ return utils.cleanUpTreeStructureArray(treeStructure, aDefaultParentID);
+ },
+
+ // based on PlacesUtils.getURLsForContainerNode()
+ getItemIdsForContainerNode : function TSTBMService_getItemIdsForContainerNode(aNode)
+ {
+ var ids = [];
+ if (!aNode || !PlacesUtils.nodeIsContainer(aNode)) return ids;
+
+ var root = aNode;
+ if ('getContainerNodeWithOptions' in PlacesUtils) {
+ root = PlacesUtils.getContainerNodeWithOptions(root, false, true);
+ }
+ var oldViewer = root.parentResult.viewer;
+ var wasOpen = root.containerOpen;
+ if (!wasOpen) {
+ if (oldViewer)
+ root.parentResult.viewer = null;
+ root.containerOpen = true;
+ }
+ for (let i = 0, maxi = root.childCount; i < maxi; ++i)
+ {
+ let child = root.getChild(i);
+ if (PlacesUtils.nodeIsURI(child)) ids.push(child.itemId || -1);
+ }
+ if (!wasOpen) {
+ root.containerOpen = false;
+ if (oldViewer)
+ root.parentResult.viewer = oldViewer;
+ }
+ return ids;
+ },
+
+ handleTabsOpenProcess : function TSTBMService_handleTabsOpenProcess(aWhere, aEvent, aBrowserWindow, aIDs, aURLs, aItemsToOpen, aFolderTitle)
+ {
+ var result = {
+ behavior : undefined,
+ treeStructure : undefined,
+ treeStructureApplied : false
+ };
+ if (
+ aEvent.type != 'drop' &&
+ aWhere.indexOf('tab') != 0 &&
+ aEvent.target.id != 'placesContext_openContainer:tabs' &&
+ aEvent.target.id != 'placesContext_openLinks:tabs' &&
+ aEvent.target != aEvent.target.parentNode._endOptOpenAllInTabs &&
+ aEvent.target.getAttribute('openInTabs') != 'true'
+ )
+ return result;
+
+ var TST = aBrowserWindow.TreeStyleTabService;
+
+ result.behavior = TST.openGroupBookmarkBehavior();
+ if (result.behavior & this.kGROUP_BOOKMARK_SUBTREE) {
+ log('handleTabsOpenProcess: open as a group');
+ let treeStructure = result.behavior & this.kGROUP_BOOKMARK_DONT_RESTORE_TREE_STRUCTURE ?
+ null :
+ this.getTreeStructureFromItems(aIDs) ;
+ log(' treeStructure => ', treeStructure);
+ if (treeStructure) {
+ let parentTabs = treeStructure.filter(function(aParent) {
+ return aParent < 0;
+ });
+ let haveMultipleTrees = parentTabs.length != treeStructure.length;
+ if (result.behavior & this.kGROUP_BOOKMARK_USE_DUMMY) {
+ log(' trying to use dummy group tab');
+ let parentCount = 0;
+ let childCount = 0;
+ for (let i in treeStructure) {
+ if (treeStructure[i] == -1)
+ parentCount++;
+ else
+ childCount++;
+ }
+ log(' parentCount: '+parentCount);
+ log(' childCount: '+childCount);
+ if (
+ parentCount > 1 &&
+ (
+ result.behavior & this.kGROUP_BOOKMARK_USE_DUMMY_FORCE ||
+ // when there is any orphan, then all of parents and orphans should be grouped under a dummy tab.
+ childCount < parentCount
+ )
+ ) {
+ aIDs.unshift(-1);
+ treeStructure = this.getTreeStructureFromItems(aIDs, 0);
+ let uri = utils.getGroupTabURI({
+ title: aFolderTitle,
+ temporary: utils.getTreePref('openGroupBookmark.temporaryGroup')
+ });
+ aURLs.unshift(uri);
+ aItemsToOpen.unshift({
+ itemId: -1,
+ title: aFolderTitle,
+ uri: uri
+ })
+ log(' updated treeStructure => ', treeStructure);
+ }
+ }
+ else if (!haveMultipleTrees) {
+ // make the first item parent.
+ treeStructure = treeStructure.map(function(aParent, aIndex) {
+ if (aIndex == 0)
+ return aParent;
+ if (aParent < 0)
+ return 0;
+ return aParent;
+ });
+ }
+ }
+
+ result.treeStructure = treeStructure;
+
+ if (utils.getTreePref('compatibility.TMP') &&
+ 'TMP_Places' in aBrowserWindow &&
+ 'openGroup' in aBrowserWindow.TMP_Places) {
+ result.treeStructureApplied = false;
+ }
+ else {
+ TST.readyToOpenNewTabGroup(null, treeStructure, result.behavior & this.kGROUP_BOOKMARK_EXPAND_ALL_TREE);
+ result.treeStructureApplied = true;
+ }
+ }
+ else {
+ TST.browser.treeStyleTab.nextOpenedTabToBeParent = false;
+ }
+ return result;
+ },
+
+
+ // observer for nsINavBookmarksService
+ onItemAdded : function TSTBMService_onItemAdded(aID, aFolderID, aPosition)
+ {
+ this._addingBookmarks.push({
+ id : aID,
+ parent : aFolderID
+ });
+ },
+ onItemRemoved : function TSTBMService_onItemRemoved(aID, aFolderID, aPosition) {},
+ onItemMoved : function TSTBMService_onItemMoved(aID, aFolderID, aPosition) {},
+ onItemChanged : function TSTBMService_onItemChanged(aID, aChange, aIsAnnotation, aNewValue) {},
+ onItemVisited : function TSTBMService_onItemVisited(aID, aHistoryID, aDate) {},
+ onBeginUpdateBatch : function TSTBMService_onBeginUpdateBatch() {},
+ onEndUpdateBatch : function TSTBMService_onEndUpdateBatch() {}
+});
+
+
+PlacesUIUtils.__treestyletab__openTabset = PlacesUIUtils._openTabset;
+PlacesUIUtils._openTabset = function(aItemsToOpen, aEvent, aWindow, ...aArgs) {
+ log('TSTBookmarks_openTabset');
+
+ var uris = [];
+ var ids = [];
+ var nodes = this.__treestyletab__openTabset_rawNodes || [];
+ aItemsToOpen = aItemsToOpen.filter(function(aItem, aIndex) {
+ if (aItem.uri) {
+ uris.push(aItem.uri);
+ let id = aItem.id;
+ if (!id && aIndex in nodes)
+ id = nodes[aIndex].itemId;
+ ids.push(id);
+ log(' '+aIndex+': '+id+' / '+aItem.uri);
+ return true;
+ }
+ return false;
+ });
+ log(' items => '+aItemsToOpen.length);
+
+ var allArgs = [aItemsToOpen, aEvent, aWindow].concat(aArgs);
+ if (aItemsToOpen.length <= 0)
+ return this.__treestyletab__openTabset.apply(this, allArgs);
+
+ var w = aWindow && aWindow.document.documentElement.getAttribute('windowtype') == 'navigator:browser' ?
+ aWindow :
+ this._getTopBrowserWin() ;
+ var TST = w.TreeStyleTabService;
+ var BS = TreeStyleTabBookmarksService;
+
+ var where = w && w.whereToOpenLink(aEvent, false, true) || 'window';
+ log(' where: '+where);
+ if (where === 'window')
+ return this.__treestyletab__openTabset.apply(this, allArgs);
+
+ var result = BS.handleTabsOpenProcess(where, aEvent, w, ids, uris, aItemsToOpen, this.__treestyletab__folderName);
+ log(' result: ', result);
+
+ var tabs = TST.doAndGetNewTabs((function() {
+ this.__treestyletab__openTabset.apply(this, allArgs);
+ }).bind(this), w.gBrowser);
+ log(' tabs: '+tabs.length);
+
+ if (!result.treeStructure)
+ tabs = [];
+
+ if (!result.treeStructureApplied)
+ TST.applyTreeStructureToTabs(
+ tabs,
+ result.treeStructure,
+ result.behavior & BS.kGROUP_BOOKMARK_EXPAND_ALL_TREE
+ );
+
+ var loadInBackground = where == 'tabshifted';
+ if (!loadInBackground) {
+ // start scroll after expanding animation is finished
+ w.setTimeout(function() {
+ w.gBrowser.treeStyleTab.scrollToTabs(tabs);
+ }, w.gBrowser.treeStyleTab.collapseDuration);
+ }
+};
+
+PlacesUtils.__treestyletab__getURLsForContainerNode = PlacesUtils.getURLsForContainerNode;
+PlacesUtils.getURLsForContainerNode = function(aNode, ...aArgs) {
+ var uris = this.__treestyletab__getURLsForContainerNode.apply(this, [aNode].concat(aArgs));
+ var nodes = TreeStyleTabBookmarksService.getItemIdsForContainerNode(aNode);
+ for (let i in nodes) {
+ uris[i].id = nodes[i];
+ }
+ return uris;
+};
+
+PlacesUIUtils.__treestyletab__openContainerNodeInTabs = PlacesUIUtils.openContainerNodeInTabs;
+PlacesUIUtils.openContainerNodeInTabs = function(aNode, ...aArgs) {
+ this.__treestyletab__folderName = aNode.title;
+ try {
+ return this.__treestyletab__openContainerNodeInTabs.apply(this, [aNode].concat(aArgs));
+ }
+ finally {
+ delete this.__treestyletab__folderName;
+ }
+};
+
+PlacesUIUtils.__treestyletab__openURINodesInTabs = PlacesUIUtils.openURINodesInTabs;
+PlacesUIUtils.openURINodesInTabs = function(aNode, ...aArgs) {
+ try {
+ this.__treestyletab__openTabset_rawNodes = aNodes;
+ this.__treestyletab__folderName = utils.treeBundle.getFormattedString(
+ PlacesUtils.nodeIsBookmark(aNodes[0]) ?
+ 'openSelectedPlaces.bookmarks' :
+ 'openSelectedPlaces.history',
+ [aNodes[0].title, aNodes.length]
+ );
+ return this.__treestyletab__openURINodesInTabs.apply(this, [aNode].concat(aArgs));
+ }
+ finally {
+ delete this.__treestyletab__openTabset_rawNodes;
+ delete this.__treestyletab__folderName;
+ }
+};
+
+PlacesUIUtils.__treestyletab__openNodeWithEvent = PlacesUIUtils.openNodeWithEvent;
+PlacesUIUtils.openNodeWithEvent = function(aNode, aEvent, aView, ...aArgs) {
+ var window = aView.ownerWindow;
+ if (!window.gBrowser)
+ window = PlacesUIUtils._getTopBrowserWin();
+ if (window && window.gBrowser)
+ window.gBrowser.treeStyleTab.readyToOpenOrphanTabNow();
+ return PlacesUIUtils.__treestyletab__openNodeWithEvent.apply(this, [aNode, aEvent, aView].concat(aArgs));
+};
diff --git a/modules/browser.js b/modules/browser.js
index e6e59e0..01b8a7d 100644
--- a/modules/browser.js
+++ b/modules/browser.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2011-2015
+ * Portions created by the Initial Developer are Copyright (C) 2011-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -56,6 +56,7 @@ XPCOMUtils.defineLazyModuleGetter(this, 'TabpanelDNDObserver', 'resource://trees
XPCOMUtils.defineLazyModuleGetter(this, 'AutoHideBrowser', 'resource://treestyletab-modules/autoHide.js');
XPCOMUtils.defineLazyModuleGetter(this, 'ContentBridge', 'resource://treestyletab-modules/contentBridge.js');
XPCOMUtils.defineLazyModuleGetter(this, 'BrowserUIShowHideObserver', 'resource://treestyletab-modules/browserUIShowHideObserver.js');
+XPCOMUtils.defineLazyModuleGetter(this, 'TabContentsObserver', 'resource://treestyletab-modules/tabContentsObserver.js');
XPCOMUtils.defineLazyModuleGetter(this, 'visuallyselectedTabs', 'resource://treestyletab-modules/lib/visuallyselectedTabs.jsm');
XPCOMUtils.defineLazyGetter(this, 'window', function() {
@@ -75,9 +76,11 @@ function wait(aMilliSeconds) {
});
}
-function mydump(aString) {
- if (utils.isDebugging('browser'))
- dump(aString);
+function log(...aArgs) {
+ utils.log.apply(utils, ['browser'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['browser'].concat(aArgs));
}
Cu.import('resource://treestyletab-modules/window.js');
@@ -433,7 +436,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
get ownerToolbar()
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::xul:toolbar[1]',
this.mTabBrowser.tabContainer,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -588,6 +591,14 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
);
},
+ isTabInternallyMoving : function TSTBrowser_isTabInternallyMoving(aTab)
+ {
+ if (aTab &&
+ aTab.__treestyletab__internallyTabMovingCount)
+ return true;
+ return Boolean(this.internallyTabMovingCount);
+ },
+
isMultiRow : function TSTBrowser_isMultiRow()
{
var w = this.window;
@@ -920,6 +931,8 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
if (this.tabStripPlaceHolder)
this.tabStripPlaceHolderBoxObserver = new BrowserUIShowHideObserver(this, this.tabStripPlaceHolder.parentNode);
+
+ this.tabContentsObserver = new TabContentsObserver(this, this.tabStrip);
},
_initTabbrowserContextMenu : function TSTBrowser_initTabbrowserContextMenu()
@@ -1072,6 +1085,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
aTab.__treestyletab__linkedTabBrowser = this.mTabBrowser;
aTab.__treestyletab__restoreState = this.RESTORE_STATE_INITIAL;
+ aTab.__treestyletab__internallyTabMovingCount = 0;
if (utils.isTabNotRestoredYet(aTab))
aTab.linkedBrowser.__treestyletab__toBeRestored = true;
@@ -1174,52 +1188,61 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
initTabContentsOrder : function TSTBrowser_initTabContentsOrder(aTab, aForce)
{
- if (!aTab.parentNode) // do nothing for closed tab!
+ if (
+ !aTab.parentNode || // do nothing for closed tab!
+ aTab.__treestyletab__initializingContentsOrder
+ )
return;
- var d = this.document;
+ aTab.__treestyletab__initializingContentsOrder = true;
- var namedNodes = {
- label : this.getTabLabel(aTab),
- sound : this.getTabSoundButton(aTab),
- close : this.getTabClosebox(aTab),
- twistyAnchor : this.getTabTwistyAnchorNode(aTab),
- twisty : this.getTabTwisty(aTab),
- counter : d.getAnonymousElementByAttribute(aTab, 'class', this.kCOUNTER_CONTAINER)
- };
+ try {
+ var d = this.document;
+ var namedNodes = {
+ label : this.getTabLabel(aTab),
+ sound : this.getTabSoundButton(aTab),
+ close : this.getTabClosebox(aTab),
+ twistyAnchor : this.getTabTwistyAnchorNode(aTab),
+ twisty : this.getTabTwisty(aTab),
+ counter : d.getAnonymousElementByAttribute(aTab, 'class', this.kCOUNTER_CONTAINER)
+ };
- namedNodes.closeAnchor = namedNodes.label;
- if (namedNodes.closeAnchor.parentNode != namedNodes.close.parentNode) {
- let containerFinder = d.createRange();
- containerFinder.selectNode(namedNodes.closeAnchor);
- containerFinder.setEndAfter(namedNodes.close);
- let container = containerFinder.commonAncestorContainer;
- while (namedNodes.closeAnchor.parentNode != container)
- {
- namedNodes.closeAnchor = namedNodes.closeAnchor.parentNode;
+ namedNodes.closeAnchor = namedNodes.label;
+ if (namedNodes.closeAnchor.parentNode != namedNodes.close.parentNode) {
+ let containerFinder = d.createRange();
+ containerFinder.selectNode(namedNodes.closeAnchor);
+ containerFinder.setEndAfter(namedNodes.close);
+ let container = containerFinder.commonAncestorContainer;
+ while (namedNodes.closeAnchor.parentNode != container)
+ {
+ namedNodes.closeAnchor = namedNodes.closeAnchor.parentNode;
+ }
+ while (namedNodes.close.parentNode != container)
+ {
+ namedNodes.close = namedNodes.close.parentNode;
+ }
}
- while (namedNodes.close.parentNode != container)
+
+ namedNodes.counterAnchor = namedNodes.label;
+
+ var foundContainers = [];
+ var containers = [
+ namedNodes.twistyAnchor.parentNode,
+ namedNodes.label.parentNode,
+ namedNodes.counter.parentNode,
+ namedNodes.closeAnchor.parentNode
+ ];
+ for (let i = 0, maxi = containers.length; i < maxi; i++)
{
- namedNodes.close = namedNodes.close.parentNode;
+ let container = containers[i];
+ if (foundContainers.indexOf(container) > -1)
+ continue;
+ this.initTabContentsOrderInternal(container, namedNodes, aForce);
+ foundContainers.push(container);
}
}
-
- namedNodes.counterAnchor = namedNodes.label;
-
- var foundContainers = [];
- var containers = [
- namedNodes.twistyAnchor.parentNode,
- namedNodes.label.parentNode,
- namedNodes.counter.parentNode,
- namedNodes.closeAnchor.parentNode
- ];
- for (let i = 0, maxi = containers.length; i < maxi; i++)
- {
- let container = containers[i];
- if (foundContainers.indexOf(container) > -1)
- continue;
- this.initTabContentsOrderInternal(container, namedNodes, aForce);
- foundContainers.push(container);
+ finally {
+ delete aTab.__treestyletab__initializingContentsOrder;
}
},
initTabContentsOrderInternal : function TSTBrowser_initTabContentsOrderInternal(aContainer, aNamedNodes, aForce)
@@ -1246,7 +1269,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
if (this.mTabBrowser.getAttribute(this.kCLOSEBOX_INVERTED) == 'true')
nodes.splice(nodes.indexOf(aNamedNodes.closeAnchor), 0, aNamedNodes.close);
else
- nodes.splice(nodes.indexOf(aNamedNodes.closeAnchor)+1, 0, aNamedNodes.close);
+ nodes.push(aNamedNodes.close);
}
index = nodes.indexOf(aNamedNodes.sound);
@@ -1738,7 +1761,9 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
// So, we have to turn the actual tab bar visible manually
// when the grippy is clicked.
let tabContainer = this.mTabBrowser.tabContainer;
- grippy.grippyOnClick = function() {
+ grippy.grippyOnClick = function(aEvent) {
+ if (aEvent.button != 0)
+ return;
tabContainer.ownerDocument.defaultView.setTimeout(function() {
var visible = grippy.getAttribute('state') != 'collapsed';
if (visible != tabContainer.visible)
@@ -1760,6 +1785,8 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
ReferenceCounter.add('splitter,mouseup,windowService,false');
splitter.addEventListener('dblclick', this.windowService, false);
ReferenceCounter.add('splitter,dblclick,windowService,false');
+ splitter.addEventListener('click', this.windowService, false);
+ ReferenceCounter.add('splitter,click,windowService,false');
var ref = this.mTabBrowser.mPanelContainer;
ref.parentNode.insertBefore(splitter, ref);
@@ -1779,6 +1806,8 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
ReferenceCounter.remove('splitter,mouseup,windowService,false');
splitter.removeEventListener('dblclick', this.windowService, false);
ReferenceCounter.remove('splitter,dblclick,windowService,false');
+ splitter.removeEventListener('click', this.windowService, false);
+ ReferenceCounter.remove('splitter,click,windowService,false');
var grippy = splitter.firstChild;
grippy.removeEventListener('click', grippy.grippyOnClick, true);
ReferenceCounter.remove('grippy,click,grippy.grippyOnClick,true');
@@ -1965,7 +1994,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
(aReason & this.kTABBAR_UPDATE_BY_AUTOHIDE ? 'autohide ' : '' ) +
(aReason & this.kTABBAR_UPDATE_BY_INITIALIZE ? 'initialize ' : '' ) +
(aReason & this.kTABBAR_UPDATE_BY_TOGGLE_SIDEBAR ? 'toggle-sidebar ' : '' );
- mydump('TSTBrowser_updateFloatingTabbarInternal: ' + humanReadableReason + '\n');
+ log('updateFloatingTabbarInternal: ' + humanReadableReason);
}
var d = this.document;
@@ -2140,6 +2169,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
splitter.setAttribute('onmousedown', 'TreeStyleTabService.handleEvent(event);');
splitter.setAttribute('onmouseup', 'TreeStyleTabService.handleEvent(event);');
splitter.setAttribute('ondblclick', 'TreeStyleTabService.handleEvent(event);');
+ splitter.setAttribute('onclick', 'TreeStyleTabService.handleEvent(event);');
box.appendChild(splitter);
this.tabStrip.appendChild(box);
}
@@ -2303,6 +2333,11 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
delete this.tabStripPlaceHolderBoxObserver;
}
+ if (this.tabContentsObserver) {
+ this.tabContentsObserver.destroy();
+ delete this.tabContentsObserver;
+ }
+
this._destroyOldSplitter();
var w = this.window;
@@ -2760,6 +2795,12 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
case 'extensions.treestyletab.tabbar.narrowScrollbar':
return this.setTabbrowserAttribute(this.kNARROW_SCROLLBAR, value);
+ case 'extensions.treestyletab.tabbar.narrowScrollbar.width':
+ if (this.isVertical &&
+ this.mTabBrowser.mTabContainer.getAttribute('overflow') == 'true')
+ utils.updateNarrowScrollbarStyle(this.browser);
+ return;
+
case 'extensions.treestyletab.maxTreeLevel.physical':
if (this.maxTreeLevelPhysical = value)
this.promoteTooDeepLevelTabs();
@@ -3159,12 +3200,26 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
var pareintIndexInTree = hasStructure ? this.treeStructure.shift() : 0 ;
var lastRelatedTab = b._lastRelatedTab;
- mydump('TSTBrowser_onTabOpen\n ' + [
+ log('onTabOpen\n ' + [
'readiedToAttachNewTab: '+this.readiedToAttachNewTab,
'parentTab: '+this.parentTab + ' (' + this.getTabById(this.parentTab) + ')',
'insertBefore: '+this.insertBefore,
'treeStructure: '+this.treeStructure
- ].join('\n ') + '\n');
+ ].join('\n '));
+
+ if (utils.getTreePref('autoAttach') &&
+ typeof this.readiedToAttachNewTab !== 'boolean') {
+ this.window.setTimeout((function() {
+ if (!tab.owner || tab != b._lastRelatedTab)
+ return;
+ log('onTabOpen: new child tab opened by browser.tabs.insertRelatedAfterCurrent=true');
+ var nextTab = this.findNextTabForNewChild(tab, tab.owner);
+ log(' next tab: '+(nextTab && nextTab._tPos));
+ this.attachTabTo(tab, tab.owner, {
+ insertBefore: nextTab
+ });
+ }).bind(this), 0);
+ }
if (this.readiedToAttachNewTab) {
if (pareintIndexInTree < 0) { // there is no parent, so this is a new parent!
@@ -3193,7 +3248,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
else if (
parent &&
utils.getTreePref('insertNewChildAt') == this.kINSERT_FISRT &&
- (this.multipleCount <= 0 || this._addedCountInThisLoop <= 0)
+ (typeof this.multipleCount !== 'number' || this._addedCountInThisLoop <= 0)
) {
/* 複数の子タブを一気に開く場合、最初に開いたタブだけを
子タブの最初の位置に挿入し、続くタブは「最初の開いたタブ」と
@@ -3202,13 +3257,18 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
if (refTab = this.getFirstChildTab(parent))
this.insertBefore = refTab.getAttribute(this.kID);
}
+ else {
+ refTab = this.findNextTabForNewChild(tab, parent);
+ if (refTab)
+ nextIndex = refTab._tPos;
+ }
if (newIndex > -1) {
if (newIndex > tab._tPos)
newIndex--;
- this.internallyTabMovingCount++;
+ tab.__treestyletab__internallyTabMovingCount++;
b.moveTabTo(tab, newIndex);
- this.internallyTabMovingCount--;
+ tab.__treestyletab__internallyTabMovingCount--;
}
if (this.shouldExpandAllTree)
@@ -3217,10 +3277,10 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
this._addedCountInThisLoop++;
if (!this._addedCountClearTimer) {
- this._addedCountClearTimer = this.window.setTimeout(function(aSelf) {
- aSelf._addedCountInThisLoop = 0;
- aSelf._addedCountClearTimer = null;
- }, 0, this);
+ this._addedCountClearTimer = this.window.setTimeout((function() {
+ this._addedCountInThisLoop = 0;
+ this._addedCountClearTimer = null;
+ }).bind(this), 0);
}
if (!this.readiedToAttachMultiple) {
@@ -3269,12 +3329,41 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
*/
b._lastRelatedTab = lastRelatedTab;
+ // this is the first tab of loading group.
+ if (this.nextOpenedTabToBeParent) {
+ this.readyToOpenChildTab(tab, true);
+ }
+ delete this.nextOpenedTabToBeParent;
+
+ tab.__treestyletab__isOpening = true;
+ this.window.setTimeout((function() {
+ tab.__treestyletab__isOpening = false;
+ }).bind(this), 0);
+
return true;
},
+ loadingMultipleTabs : false,
_addedCountInThisLoop : 0,
_addedCountClearTimer : null,
_checkRestoringWindowTimerOnTabAdded : null,
+ findNextTabForNewChild : function TSTBrowser_findNextTabForNewChild(aTab, aParent)
+ {
+ if (!aParent)
+ return this.getNextTab(aTab);
+
+ var nextTab;
+ if (utils.getTreePref('insertNewChildAt') === this.kINSERT_FISRT)
+ nextTab = this.getFirstChildTab(aParent);
+ else
+ nextTab = this.getNextSiblingTab(aParent) || this.getNextTab(this.getLastDescendantTab(aParent));
+
+ if (nextTab == aTab)
+ nextTab = this.getNextTab(nextTab);
+
+ return nextTab;
+ },
+
scrollToNewTab : function TSTBrowser_scrollToNewTab(aTab)
{
if (!aTab.parentNode) // do nothing for closed tab!
@@ -3347,7 +3436,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
var closeParentBehavior = this.getCloseParentBehaviorForTab(tab);
var backupAttributes = this._collectBackupAttributes(tab);
- mydump('onTabClose: backupAttributes = '+JSON.stringify(backupAttributes)+'\n');
+ log('onTabClose: backupAttributes = ', backupAttributes);
if (closeParentBehavior == this.kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN ||
this.isSubtreeCollapsed(tab))
@@ -3574,7 +3663,16 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
var b = this.mTabBrowser;
var prevPosition = aEvent.detail;
+ if (tab.__treestyletab__isOpening && !this.isTabInternallyMoving(tab)) {
+ log('onTabMove for new child tab: move back '+tab._tPos+' => '+prevPosition);
+ tab.__treestyletab__internallyTabMovingCount++;
+ b.moveTabTo(tab, prevPosition);
+ tab.__treestyletab__internallyTabMovingCount--;
+ return;
+ }
+
tab.__treestyletab__previousPosition = prevPosition;
+ logWithStackTrace('onTabMove '+prevPosition+' => '+tab._tPos+' (internal moving count='+tab.__treestyletab__internallyTabMovingCount+', owner='+String(tab.owner)+')');
// When the tab was moved before TabOpen event is fired, we have to update manually.
var newlyOpened = !this.isTabInitialized(tab) && this.onTabOpen(null, tab);
@@ -3597,8 +3695,11 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
if (storedId && tab.getAttribute(this.kID) != storedId)
restored = this.onTabRestoring(aEvent);
}
+ log(' newlyOpened: '+newlyOpened);
+ log(' restored: '+restored);
if (this.hasChildTabs(tab) && !this.subTreeMovingCount) {
+ log(' => move sub tree');
this.moveTabSubtreeTo(tab, tab._tPos);
}
@@ -3634,6 +3735,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
if (!this.subTreeChildrenMovingCount)
this.updateChildrenArray(parentTab);
}
+ log(' tabsToBeUpdated: '+tabsToBeUpdated.map(function(aTab) { return aTab._tPos; }));
var updatedTabs = new WeakMap();
tabsToBeUpdated.forEach(function(aTab) {
@@ -3651,7 +3753,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
if (
this.subTreeMovingCount ||
- this.internallyTabMovingCount ||
+ this.isTabInternallyMoving(tab) ||
// We don't have to fixup tree structure for a NEW TAB
// which has already been structured.
(newlyOpened && this.getParentTab(tab))
@@ -3666,15 +3768,18 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
attachTabFromPosition : function TSTBrowser_attachTabFromPosition(aTab, aOldPosition)
{
+ log('attachTabFromPosition '+aOldPosition+' => '+aTab._tPos);
var parent = this.getParentTab(aTab);
if (aOldPosition === void(0))
aOldPosition = aTab._tPos;
var pos = this.getChildIndex(aTab, parent);
- var oldPos = this.getChildIndex(this.getAllTabs(this.mTabBrowser)[aOldPosition], parent);
+ var oldPositionTab = this.getAllTabs(this.mTabBrowser)[aOldPosition];
+ var oldPos = this.getChildIndex(oldPositionTab, parent);
var delta;
- if (pos == oldPos) { // no move?
+ if (oldPositionTab == aTab && pos == oldPos) { // no move?
+ log(' => no move');
return;
}
else if (pos < 0 || oldPos < 0) {
@@ -3684,51 +3789,54 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
delta = Math.abs(pos - oldPos);
}
- mydump('attachTabFromPosition '+aTab._tPos+' / '+aOldPosition+'\n');
- mydump((new Error()).stack.replace(/^/gm, ' ')+'\n');
+ logWithStackTrace(' moving');
- var prevTab = this.getPreviousTab(aTab);
- var nextTab = this.getNextTab(aTab);
+ var prevTab = this.getPreviousVisibleTab(aTab);
+ var nextTab = this.getNextVisibleTab(aTab);
var tabs = this.getDescendantTabs(aTab);
if (tabs.length) {
nextTab = this.getNextTab(tabs[tabs.length-1]);
}
+ log(' prevTab: '+(prevTab&&(prevTab._tPos+'('+prevTab.linkedBrowser.currentURI.spec+')')));
+ log(' nextTab: '+(nextTab&&(nextTab._tPos+'('+nextTab.linkedBrowser.currentURI.spec+')')));
var prevParent = this.getParentTab(prevTab);
var nextParent = this.getParentTab(nextTab);
var prevLevel = prevTab ? Number(prevTab.getAttribute(this.kNEST)) : -1 ;
var nextLevel = nextTab ? Number(nextTab.getAttribute(this.kNEST)) : -1 ;
+ log(' prevLevel: '+prevLevel);
+ log(' nextLevel: '+nextLevel);
var newParent;
if (!prevTab) {
- mydump(' => moved to topmost position\n');
+ log(' => moved to topmost position');
newParent = null;
}
else if (!nextTab) {
- mydump(' => movedmoved to last position\n');
+ log(' => movedmoved to last position');
newParent = (delta > 1) ? prevParent : parent ;
}
else if (prevParent == nextParent) {
- mydump(' => moved into existing tree\n');
+ log(' => moved into existing tree');
newParent = prevParent;
}
else if (prevLevel > nextLevel) {
- mydump(' => moved to end of existing tree\n');
+ log(' => moved to end of existing tree');
if (this.mTabBrowser.selectedTab != aTab) {
- mydump(' => maybe newly opened tab\n');
+ log(' => maybe newly opened tab');
newParent = prevParent;
}
else {
- mydump(' => maybe drag and drop\n');
+ log(' => maybe drag and drop');
var realDelta = Math.abs(aTab._tPos - aOldPosition);
newParent = realDelta < 2 ? prevParent : (parent || nextParent) ;
}
}
else if (prevLevel < nextLevel) {
- mydump(' => moved to first child position of existing tree\n');
+ log(' => moved to first child position of existing tree');
newParent = prevTab || parent || nextParent;
}
@@ -4043,7 +4151,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
handleRestoredTab : function TSTBrowser_handleRestoredTab(aTab)
{
if (aTab.__treestyletab__restoreState === undefined) {
- mydump('handleRestoredTab: ' + aTab._tPos + ' is already restored!\n');
+ log('handleRestoredTab: ' + aTab._tPos + ' is already restored!');
return false;
}
@@ -4271,7 +4379,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
var restoringMultipleTabs = this.windowService.restoringTree;
var position = this._prepareInsertionPosition(aTab, aMayBeDuplicated);
var parent = position.parent;
- mydump('handleRestoredTab: found parent = ' + parent+'\n');
+ log('handleRestoredTab: found parent = ' + parent);
if (parent) {
aTab.removeAttribute(this.kPARENT);
parent = this.getTabById(parent);
@@ -4317,7 +4425,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
}
var ancestors = (this.getTabValue(aTab, this.kANCESTORS) || this.getTabValue(aTab, this.kPARENT)).split('|');
- mydump('handleRestoredTab: ancestors = ' + ancestors+'\n');
+ log('handleRestoredTab: ancestors = ' + ancestors);
var parent = null;
for (let i in ancestors)
{
@@ -4339,7 +4447,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
*/
if (!parent) {
parent = aTab.getAttribute(this.kPARENT);
- mydump('handleRestoredTab: parent = ' + parent+'\n');
+ log('handleRestoredTab: parent = ' + parent);
if (parent && !next)
next = this.getNextSiblingTab(aTab);
}
@@ -5044,6 +5152,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
if (aEvent.type == 'overflow') {
tabs.setAttribute('overflow', 'true');
this.scrollBoxObject.ensureElementIsVisible(tabs.selectedItem);
+ utils.updateNarrowScrollbarStyle(this.browser);
}
else {
tabs.removeAttribute('overflow');
@@ -5095,9 +5204,9 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
}
if (isContentResize || isChromeResize) {
- mydump('TSTBrowser_onResize\n');
- mydump(' isContentResize = '+isContentResize+'\n');
- mydump(' isChromeResize = '+isChromeResize+'\n');
+ log('TSTBrowser_onResize');
+ log(' isContentResize = '+isContentResize);
+ log(' isChromeResize = '+isChromeResize);
this.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
this.updateInvertedTabContentsOrder(true);
this.mTabBrowser.mTabContainer.adjustTabstrip();
@@ -5259,10 +5368,10 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
onBeforeFullScreenToggle : function TSTBrowser_onBeforeFullScreenToggle(aEnterFS)
{
- mydump('onBeforeFullScreenToggle / ' + this.position + '\n');
+ log('onBeforeFullScreenToggle / ' + this.position);
if (this.position != 'top') {
- mydump(' this.document.mozFullScreen => ' + this.document.mozFullScreen + '\n');
- mydump(' aEnterFS => ' + aEnterFS + '\n');
+ log(' this.document.mozFullScreen => ' + this.document.mozFullScreen);
+ log(' aEnterFS => ' + aEnterFS);
// ignore entering to the DOM-fullscreen (ex. YouTube Player)
if (!this.document.mozFullScreen) {
if (aEnterFS)
@@ -5667,6 +5776,29 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
!utils.getTreePref('closeParentBehavior.moveDetachedTabsToBottom')) {
insertBefore = this.getNextSiblingTab(this.getRootTab(aTab));
}
+
+ if (aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_REPLACE_WITH_GROUP_TAB) {
+ let uri = utils.getGroupTabURI({
+ title: aTab.label,
+ temporary: true
+ });
+ let groupTab = b.addTab(uri);
+ if (parentTab) {
+ this.attachTabTo(groupTab, parentTab, {
+ insertBefore : aTab,
+ dontAnimate : true
+ });
+ }
+ else {
+ this.moveTabSubtreeTo(groupTab, aTab._tPos);
+ }
+ this.attachTabTo(aTab, groupTab, {
+ dontAnimate : true
+ });
+ parentTab = groupTab;
+ aInfo.behavior = this.kCLOSE_PARENT_BEHAVIOR_PROMOTE_ALL_CHILDREN;
+ }
+
for (let i = 0, maxi = children.length; i < maxi; i++)
{
let tab = children[i];
@@ -6220,7 +6352,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
sourceService.getAllTabs(sourceBrowser).length == aTabs.length
);
var newTabs = [];
- var treeStructure = sourceService.getTreeStructureFromTabs(aTabs);
+ var treeStructure = utils.getTreeStructureFromTabs(aTabs);
// Firefox fails to "move" collapsed tabs. So, expand them first
// and collapse them after they are moved.
@@ -6395,7 +6527,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
var id = this.getTabValue(aTab, this.kID);
aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave = function checkTabsIndentOverflowOnMouseLeave(aEvent, aDelayed) {
if (aEvent.type == 'mouseover') {
- if (self.evaluateXPath(
+ if (utils.evaluateXPath(
'ancestor-or-self::*[@' + self.kID + '="' + id + '"]',
aEvent.originalTarget || aEvent.target,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
@@ -6682,7 +6814,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
}, this)
.join('|');
- var xpathResult = this.evaluateXPath(
+ var xpathResult = utils.evaluateXPath(
'child::xul:tab[@'+this.kCHILDREN+' and not(@'+this.kCOLLAPSED+'="true") and not(@'+this.kSUBTREE_COLLAPSED+'="true") and @'+this.kID+' and not(contains("'+expandedAncestors+'", @'+this.kID+')) and not(@hidden="true")]',
b.mTabContainer
);
@@ -6925,7 +7057,8 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
scrollToTabs : function TSTBrowser_scrollToTabs(aTabs)
{
var firstTab = aTabs[0];
- if (!firstTab.parentNode) // do nothing for closed tab!
+ if (!firstTab ||
+ !firstTab.parentNode) // do nothing for closed tab!
return;
var b = this.mTabBrowser;
@@ -7013,6 +7146,23 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
}).bind(this));
}).bind(this), 0);
},
+
+ highlightTab : function TSTBrowser_highlightTab(aTab)
+ {
+ aTab.setAttribute(this.kHIGHLIGHTED, 'ready');
+ wait(0)
+ .then((function() {
+ aTab.setAttribute(this.kHIGHLIGHTED, 'notifying');
+ return wait(500);
+ }).bind(this))
+ .then((function() {
+ aTab.setAttribute(this.kHIGHLIGHTED, 'finish');
+ return wait(1000);
+ }).bind(this))
+ .then((function() {
+ aTab.removeAttribute(this.kHIGHLIGHTED);
+ }).bind(this));
+ },
restoreTree : function TSTBrowser_restoreTree()
{
@@ -7039,9 +7189,9 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
Components.utils.reportError(new Error('There is no property named "_browserEpochs"!!'));
}
- mydump('TSTBrowser::restoreTree\n');
- mydump(' level = '+level+'\n');
- mydump(' tabsToRestore = '+tabsToRestore+'\n');
+ log('TSTBrowser::restoreTree');
+ log(' level = '+level);
+ log(' tabsToRestore = '+tabsToRestore);
if (
level <= this.kRESTORE_TREE_LEVEL_NONE ||
@@ -7064,7 +7214,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
);
});
- mydump(' restoring member tabs = '+tabs.length+' ('+tabs.map(function(aTab) { return aTab._tPos; })+')\n');
+ log(' restoring member tabs = '+tabs.length+' ('+tabs.map(function(aTab) { return aTab._tPos; })+')');
if (tabs.length <= 1)
return;
diff --git a/modules/browserUIShowHideObserver.js b/modules/browserUIShowHideObserver.js
index ac5b391..9932f82 100644
--- a/modules/browserUIShowHideObserver.js
+++ b/modules/browserUIShowHideObserver.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2014-2015
+ * Portions created by the Initial Developer are Copyright (C) 2014-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -42,6 +42,13 @@ Components.utils.import('resource://treestyletab-modules/constants.js');
XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
+function log(...aArgs) {
+ utils.log.apply(utils, ['browserUIShowHideObserver'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['browserUIShowHideObserver'].concat(aArgs));
+}
+
function BrowserUIShowHideObserver(aOwner, aBox, aOptions) {
this.owner = aOwner;
this.box = aBox;
@@ -91,7 +98,7 @@ BrowserUIShowHideObserver.prototype = {
{
case 'childList':
if (aMutation.target == this.box) {
- this.dumpMutation(aMutation, 'BrowserUIShowHideObserver_onMutation/childList');
+ this.logMutation(aMutation, 'onMutation/childList');
this.owner.browser.treeStyleTab.updateFloatingTabbar(TreeStyleTabConstants.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
}
return;
@@ -102,7 +109,7 @@ BrowserUIShowHideObserver.prototype = {
}
}
catch(error) {
- this.dumpMutation(aMutation, 'BrowserUIShowHideObserver_onMutation(error)');
+ this.logMutation(aMutation, 'onMutation(error)');
Components.utils.reportError(error);
}
}, this);
@@ -118,7 +125,7 @@ BrowserUIShowHideObserver.prototype = {
delete this.owner;
},
- dumpMutation : function BrowserUIShowHideObserver_dumpMutation(aMutation, aDescription)
+ logMutation : function BrowserUIShowHideObserver_logMutation(aMutation, aDescription)
{
if (!utils.isDebugging('browserUIShowHideObserver'))
return;
@@ -132,10 +139,10 @@ BrowserUIShowHideObserver.prototype = {
aMutation.attributeName + ', ' +
aMutation.oldValue + ' => ' +
target.getAttribute(aMutation.attributeName);
- dump(aDescription + ' ' +
+ log(aDescription + ' ' +
ownerInformation + ' / ' +
targetInformation +
- attributeInformation + '\n');
+ attributeInformation);
},
onAttributeModified : function BrowserUIShowHideObserver_onAttributeModified(aMutation, aObserver)
@@ -146,22 +153,35 @@ BrowserUIShowHideObserver.prototype = {
return;
var target = aMutation.target;
- var state = this.serializeBoxState(target);
- if (target.__treestyletab_mutationObserver_lastState == state)
- return;
-
if (
// ignore modifications of each tab
TST.getTabFromChild(target) ||
- // ignore modifications in the location bar (ex. identity icon)
- TST.evaluateXPath(
- 'ancestor-or-self::xul:textbox',
+ utils.evaluateXPath(
+ // ignore modifications in the location bar (ex. identity icon)
+ 'ancestor-or-self::xul:textbox |' +
+ // or menu items
+ 'ancestor-or-self::xul:menupopup |' +
+ // or scrollable indicator in the vertical tab bar
+ 'ancestor-or-self::xul:spacer[' +
+ 'contains(@class, "arrowscrollbox-overflow-start-indicator") or ' +
+ 'contains(@class, "arrowscrollbox-overflow-end-indicator")' +
+ '][ancestor::xul:tabs[@' + TreeStyleTabConstants.kMODE + ' = "vertical"]]',
target,
Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
- ).singleNodeValue
+ ).singleNodeValue ||
+ // value is not changed
+ aMutation.oldValue == target.getAttribute(aMutation.attributeName)
)
return;
+ this.logMutation(aMutation, 'onAttributeModified');
+
+ var state = this.serializeBoxState(target);
+ if (target.__treestyletab_mutationObserver_lastState == state) {
+ log(' => skip modification with no state change');
+ return;
+ }
+
var tabbar = this.owner.browser.tabContainer;
var placeHolder = TST.tabStripPlaceHolder;
@@ -198,7 +218,7 @@ BrowserUIShowHideObserver.prototype = {
if (
// I must ignore show/hide of elements managed by TST,
// to avoid infinity loop.
- TST.evaluateXPath(
+ utils.evaluateXPath(
'ancestor-or-self::xul:*[@' + TreeStyleTabConstants.kTAB_STRIP_ELEMENT + '="true"]',
target,
Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -210,13 +230,14 @@ BrowserUIShowHideObserver.prototype = {
// (Pale Moon, Tab Mix Plus, etc.)
!tabbarVisibilityMismatching &&
!tabbarMatrixMismatching
- )
+ ) {
+ log(' => skip modifications around controlled element');
return;
-
- this.dumpMutation(aMutation, 'BrowserUIShowHideObserver_onAttributeModified');
+ }
this.handlingAttrChange = true;
+ log(' => update floating tab bar');
TST.updateFloatingTabbar(TreeStyleTabConstants.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
var w = this.box.ownerDocument.defaultView;
diff --git a/modules/constants.js b/modules/constants.js
index 9cc4c25..7405919 100644
--- a/modules/constants.js
+++ b/modules/constants.js
@@ -82,6 +82,7 @@ var TreeStyleTabConstants = Object.freeze({
kINVERT_SCROLLBAR : 'treestyletab-invert-scrollbar',
kNARROW_SCROLLBAR : 'treestyletab-narrow-scrollbar',
kFAVICONIZED : 'treestyletab-faviconized',
+ kHIGHLIGHTED : 'treestyletab-highlighted',
kBG_NOTIFY_PHASE : 'treestyletab-notifybgtab-phase',
kIGNORE_POPUP_STATE : 'treestyletab-ignore-state',
@@ -198,6 +199,7 @@ var TreeStyleTabConstants = Object.freeze({
kCLOSE_PARENT_BEHAVIOR_DETACH_ALL_CHILDREN : 1,
kCLOSE_PARENT_BEHAVIOR_SIMPLY_DETACH_ALL_CHILDREN : 4,
kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN : 2, // onTabRemoved only
+ kCLOSE_PARENT_BEHAVIOR_REPLACE_WITH_GROUP_TAB : 5,
kRESTORE_TREE_LEVEL_NONE : 0,
kRESTORE_TREE_ONLY_VISIBLE : 1,
@@ -220,6 +222,22 @@ var TreeStyleTabConstants = Object.freeze({
RESTORE_STATE_STRUCTURE_RESTORED : 2,
+ kDROPLINK_ASK : 0,
+ kDROPLINK_FIXED : 1 + 2,
+ kDROPLINK_LOAD : 1,
+ kDROPLINK_NEWTAB : 2,
+
+
+ kGROUP_BOOKMARK_ASK : 0,
+ kGROUP_BOOKMARK_FIXED : 1 + 2 + 4,
+ kGROUP_BOOKMARK_SUBTREE : 1,
+ kGROUP_BOOKMARK_SEPARATE : 2,
+ kGROUP_BOOKMARK_USE_DUMMY : 256,
+ kGROUP_BOOKMARK_USE_DUMMY_FORCE : 1024,
+ kGROUP_BOOKMARK_DONT_RESTORE_TREE_STRUCTURE : 512,
+ kGROUP_BOOKMARK_EXPAND_ALL_TREE : 2048,
+
+
CONTENT_SCRIPT : 'chrome://treestyletab/content/content-utils.js',
CONTENT_SCRIPT_AUTOHIDE : 'chrome://treestyletab/content/content-utils-autohide.js',
MESSAGE_TYPE : 'treestyletab',
diff --git a/modules/contentBridge.js b/modules/contentBridge.js
index d7f34a4..d40246b 100644
--- a/modules/contentBridge.js
+++ b/modules/contentBridge.js
@@ -46,6 +46,13 @@ Cu.import('resource://gre/modules/Promise.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
+function log(...aArgs) {
+ utils.log.apply(utils, ['contentBridge'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['contentBridge'].concat(aArgs));
+}
+
function ContentBridge(aTab, aTabBrowser)
{
this.init(aTab, aTabBrowser);
@@ -107,11 +114,9 @@ ContentBridge.prototype = inherit(TreeStyleTabConstants, {
},
handleMessage : function CB_handleMessage(aMessage)
{
- if (utils.isDebugging('contentBridge')) {
- dump('*********************handleMessage*******************\n');
- dump('TARGET IS: '+aMessage.target.localName+'\n');
- dump(JSON.stringify(aMessage.json)+'\n');
- }
+ log('*********************handleMessage*******************');
+ log('TARGET IS: '+aMessage.target.localName);
+ log(JSON.stringify(aMessage.json));
if (aMessage.target != this.mTab.linkedBrowser)
return;
diff --git a/modules/fullTooltip.js b/modules/fullTooltip.js
index 9457d87..7529688 100644
--- a/modules/fullTooltip.js
+++ b/modules/fullTooltip.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2011-2014
+ * Portions created by the Initial Developer are Copyright (C) 2011-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -148,7 +148,7 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
getFullTooltipFromEvent : function FTM_getFullTooltipFromEvent(aEvent)
{
- return this.evaluateXPath(
+ return utils.evaluateXPath(
'ancestor-or-self::xul:tooltip[@id="'+this.tabFullTooltip.id+'"]',
aEvent.target,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
@@ -188,10 +188,46 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
this.cancel();
},
+ getCurrentScreen : function FTM_getCurrentScreen(aBox)
+ {
+ var currentScreen = Cc['@mozilla.org/gfx/screenmanager;1']
+ .getService(Ci.nsIScreenManager)
+ .screenForRect(aBox.screenX, aBox.screenY, aBox.width, aBox.height);
+ var screenLeft = {},
+ screenTop = {},
+ screenWidth = {},
+ screenHeight = {};
+ currentScreen.GetRect(screenLeft, screenTop, screenWidth, screenHeight);
+ return {
+ left : screenLeft.value,
+ top : screenTop.value,
+ width : screenWidth.value,
+ height : screenHeight.value,
+ allowedWidth : Math.ceil(screenWidth.value * 0.8),
+ allowedHeight : Math.ceil(screenHeight.value * 0.7)
+ };
+ },
+
onShown : function FTM_onShown(aEvent)
{
this.startListenTooltipEvents();
+ if (utils.getTreePref('tooltip.columnize')) {
+ let tooltip = this.tabFullTooltip;
+ let currentScreen = this.getCurrentScreen(tooltip.boxObject);
+ let tree = tooltip.lastChild.lastChild.lastChild;
+ PseudoTreeBuilder.columnizeTree(tree, {
+ width : currentScreen.allowedWidth,
+ height : currentScreen.allowedHeight
+ });
+ this.window.setTimeout(this.resizeTooltip.bind(this), 0);
+ }
+ else {
+ this.resizeTooltip();
+ }
+ },
+ resizeTooltip : function FTM_resizeTooltip()
+ {
var tooltip = this.tabFullTooltip;
tooltip.setAttribute('popup-shown', true);
@@ -205,24 +241,17 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
var currentX = box.screenX;
var currentY = box.screenY;
- var currentScreen = Cc['@mozilla.org/gfx/screenmanager;1']
- .getService(Ci.nsIScreenManager)
- .screenForRect(box.screenX, box.screenY, box.width, box.height);
- var screenLeft = {},
- screenTop = {},
- screenWidth = {},
- screenHeight = {};
- currentScreen.GetRect(screenLeft, screenTop, screenWidth, screenHeight);
+ var currentScreen = this.getCurrentScreen(box);
var style = tooltip.style;
- style.maxWidth = screenWidth.value+'px';
- style.maxHeight = screenHeight.value+'px';
+ style.maxWidth = currentScreen.allowedWidth+'px';
+ style.maxHeight = currentScreen.allowedHeight+'px';
style.minWidth = 0;
style.minHeight = 0;
- if (currentX + currentW + screenLeft.value >= screenWidth.value)
- style.marginLeft = (Math.max(screenLeft.value, screenWidth.value - currentW) - this.window.screenX)+'px';
- if (currentY + currentH + screenTop.value >= screenHeight.value)
- style.marginTop = (Math.max(screenTop.value, screenHeight.value - currentH) - this.window.screenY)+'px';
+ if (currentX + currentW + currentScreen.left >= currentScreen.allowedWidth)
+ style.marginLeft = (Math.max(currentScreen.left, currentScreen.allowedWidth - currentW) - this.window.screenX)+'px';
+ if (currentY + currentH + currentScreen.top >= currentScreen.allowedHeight)
+ style.marginTop = (Math.max(currentScreen.top, currentScreen.allowedHeight - currentH) - this.window.screenY)+'px';
},
onHidden : function FTM_onHidden(aEvent)
@@ -449,9 +478,12 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
var tree = PseudoTreeBuilder.build(aTab);
var root = this.document.createElement('arrowscrollbox');
- root.setAttribute('orient', 'vertical');
+ var orient = utils.getTreePref('tooltip.columnize') ? 'horizontal' : 'vertical' ;
+ root.setAttribute('orient', orient);
root.setAttribute('flex', 1);
+ var container = root.appendChild(this.document.createElement('vbox'));
+
if (aExtraLabels) {
if (typeof aExtraLabels == 'string')
aExtraLabels = [aExtraLabels];
@@ -461,12 +493,13 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
label = label.trim();
if (!label)
continue;
- root.appendChild(this.document.createElement('description'))
+ container.appendChild(this.document.createElement('description'))
.appendChild(this.document.createTextNode(label));
}
}
- root.insertBefore(tree, root.firstChild && root.firstChild.nextSibling);
+ container.insertBefore(tree, container.firstChild && container.firstChild.nextSibling);
+ root.appendChild(container);
this.tabFullTooltip.appendChild(root);
},
diff --git a/modules/fullscreenObserver.js b/modules/fullscreenObserver.js
index 6dcd7de..54210dc 100644
--- a/modules/fullscreenObserver.js
+++ b/modules/fullscreenObserver.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2013-2015
+ * Portions created by the Initial Developer are Copyright (C) 2013-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -39,6 +39,13 @@ Components.utils.import('resource://treestyletab-modules/constants.js');
Components.utils.import('resource://treestyletab-modules/utils.js');
+function log(...aArgs) {
+ TreeStyleTabUtils.log.apply(TreeStyleTabUtils, ['fullscreenObserver'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ TreeStyleTabUtils.logWithStackTrace.apply(TreeStyleTabUtils, ['fullscreenObserver'].concat(aArgs));
+}
+
function FullscreenObserver(aWindow) {
this.window = aWindow;
this.init();
@@ -90,6 +97,7 @@ FullscreenObserver.prototype = {
onSizeModeChange : function FullscreenObserver_onSizeModeChange()
{
+ log('onSizeModeChange: ', this.window.document.documentElement.getAttribute('sizemode'));
this.updateToolboxPosition();
if (!this.window.gBrowser.treeStyleTab.notifyingRenderedEvent)
this.window.gBrowser.treeStyleTab.updateFloatingTabbar(TreeStyleTabConstants.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
diff --git a/modules/groupTab.js b/modules/groupTab.js
index 080f1b4..fba531f 100644
--- a/modules/groupTab.js
+++ b/modules/groupTab.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2014
+ * Portions created by the Initial Developer are Copyright (C) 2010-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -39,11 +39,15 @@ var EXPORTED_SYMBOLS = ['GroupTab'];
const Cc = Components.classes;
const Ci = Components.interfaces;
+Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
+
Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm');
Components.utils.import('resource://treestyletab-modules/base.js');
Components.utils.import('resource://treestyletab-modules/pseudoTreeBuilder.js');
Components.utils.import('resource://treestyletab-modules/tabAttributesObserver.js');
+XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
+
function GroupTab(aWindow)
{
this.window = aWindow;
@@ -234,6 +238,8 @@ GroupTab.prototype = inherit(TreeStyleTabBase, {
var contents = PseudoTreeBuilder.build(this.getOwnerTab());
if (contents)
tree.appendChild(contents);
+
+ this.onResize();
},
checkUpdateTreeNow : function GT_checkUpdateTreeNow()
@@ -272,6 +278,9 @@ GroupTab.prototype = inherit(TreeStyleTabBase, {
case 'TabSelect':
return this.onTabSelect(aEvent);
+ case 'resize':
+ return this.onResize();
+
case this.kEVENT_TYPE_ATTACHED:
return this.onTabAttached(aEvent);
case this.kEVENT_TYPE_DETACHED:
@@ -293,15 +302,20 @@ GroupTab.prototype = inherit(TreeStyleTabBase, {
this.window.addEventListener('unload', this, false);
this.window.addEventListener('click', this, false);
this.window.addEventListener('dblclick', this, false);
+ this.window.addEventListener('resize', this, false);
tab.addEventListener('TabSelect', this, false);
tab.addEventListener('TabClose', this, false);
tab.parentNode.addEventListener(this.kEVENT_TYPE_ATTACHED, this, false);
tab.parentNode.addEventListener(this.kEVENT_TYPE_DETACHED, this, false);
- this.tabsObserver = new TabAttributesObserver(this.browser.tabContainer, (function(aTab) {
- this.onTabModified(aTab);
- }).bind(this));
+ this.tabsObserver = new TabAttributesObserver({
+ container : this.browser.tabContainer,
+ attributes : 'label,visibleLabel,image',
+ callback : (function(aTab) {
+ this.onTabModified(aTab);
+ }).bind(this)
+ });
this.editor.addEventListener('keypress', this, false);
@@ -320,6 +334,7 @@ GroupTab.prototype = inherit(TreeStyleTabBase, {
this.window.removeEventListener('unload', this, false);
this.window.removeEventListener('click', this, false);
this.window.removeEventListener('dblclick', this, false);
+ this.window.removeEventListener('resize', this, false);
tab.removeEventListener('TabSelect', this, false);
tab.removeEventListener('TabClose', this, false);
@@ -390,6 +405,15 @@ GroupTab.prototype = inherit(TreeStyleTabBase, {
this.shouldUpdate = false;
},
+ onResize : function GT_onResize()
+ {
+ if (!utils.getTreePref('groupTab.columnize'))
+ return;
+ var container = this.document.getElementById('tree');
+ var tree = container.firstChild;
+ PseudoTreeBuilder.columnizeTree(tree);
+ },
+
onTabAttached : function GT_onTabAttached(aEvent)
{
var tab = aEvent.detail.parentTab;
diff --git a/modules/pseudoTreeBuilder.js b/modules/pseudoTreeBuilder.js
index 5907d54..018becf 100644
--- a/modules/pseudoTreeBuilder.js
+++ b/modules/pseudoTreeBuilder.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2011-2015
+ * Portions created by the Initial Developer are Copyright (C) 2011-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -44,8 +44,10 @@ Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabBase', 'resource://treestyletab-modules/base.js');
var PseudoTreeBuilder = {
+ XHTMLNS : 'http://www.w3.org/1999/xhtml',
kFAVICON : 'treestyletab-pseudo-tree-favicon',
+ kROOT : 'treestyletab-pseudo-tree-root',
kROOTITEM : 'treestyletab-pseudo-tree-root-item',
kTREEITEM : 'treestyletab-pseudo-tree-item',
kTREEROW : 'treestyletab-pseudo-tree-row',
@@ -59,8 +61,9 @@ var PseudoTreeBuilder = {
return null;
var tree = this.createTabItem(aTab);
+ tree.className = this.kROOT;
- var row = tree.querySelector("."+this.kTREEROW);
+ var row = tree.querySelector("*|*."+this.kTREEROW);
if (!row)
return;
@@ -95,31 +98,36 @@ var PseudoTreeBuilder = {
var doc = aTab.ownerDocument;
var w = doc.defaultView;
- var item = doc.createElement('hbox');
- item.setAttribute('class', this.kTREEROW);
+ var item = doc.createElementNS(this.XHTMLNS, 'div');
+ item.setAttribute('class', this.kTREEITEM);
- var favicon = item.appendChild(doc.createElement('image'));
+ var favicon = item.appendChild(doc.createElementNS(this.XHTMLNS, 'img'));
favicon.setAttribute('src', aTab.getAttribute('image') || 'chrome://mozapps/skin/places/defaultFavicon.png');
favicon.setAttribute('class', this.kFAVICON);
var label = item.appendChild(doc.createElement('label'));
- label.setAttribute('value', aTab.label);
+ label.setAttribute('flex', 1);
+ label.textContent = aTab.label;
var tooltip = aTab.label;
var uri = aTab.linkedBrowser.currentURI.spec;
if (w.isBlankPageURL ? !w.isBlankPageURL(uri) : (uri != 'about:blank')) tooltip += '\n' + uri;
label.setAttribute('tooltiptext', tooltip);
- label.setAttribute('class', 'text-link '+this.kTREEITEM);
+ label.setAttribute('class', 'text-link');
label.setAttribute('tab-id', TreeStyleTabBase.getTabValue(aTab, TreeStyleTabBase.kID));
+ var row = doc.createElementNS(this.XHTMLNS, 'div');
+ row.setAttribute('class', this.kTREEROW);
+ row.appendChild(item);
+
var children = this.createTabChildren(aTab);
if (children) {
- let container = doc.createElement('vbox');
- container.appendChild(item);
+ let container = doc.createElementNS(this.XHTMLNS, 'div');
+ container.appendChild(row);
container.appendChild(children);
return container;
}
else {
- return item;
+ return row;
}
},
@@ -131,12 +139,46 @@ var PseudoTreeBuilder = {
if (!children.length)
return null;
- var container = doc.createElement('vbox');
+ var container = doc.createElementNS(this.XHTMLNS, 'div');
+ container.setAttribute('class', this.kTREECHILDREN);
for (let i = 0, maxi = children.length; i < maxi; i++)
{
container.appendChild(this.createTabItem(children[i]));
}
- container.setAttribute('class', this.kTREECHILDREN);
return container;
+ },
+
+ columnizeTree : function TB_columnizeTree(aTree, aContainerBox)
+ {
+ aContainerBox = aContainerBox || aTree.parentNode.boxObject;
+
+ var style = aTree.style;
+ var height = aTree.clientHeight * (aTree.columnCount || 1);
+ if (height > aContainerBox.height &&
+ aContainerBox.height < aContainerBox.width) {
+ let maxWidth = aContainerBox.width;
+ aTree.columnWidth = Math.floor(maxWidth * 0.9 / 2.5);
+ let count = Math.ceil(
+ (aTree.clientWidth * aTree.clientHeight) /
+ (aTree.columnWidth * aTree.clientHeight)
+ );
+ aTree.columnCount = style.columnCount = style.MozColumnCount = count;
+ style.columnWidth = style.MozColumnWidth = aTree.columnWidth+'px';
+ style.columnGap = style.MozColumnGap = '0';
+ }
+ else {
+ aTree.columnCount = 1;
+ style.columnCount = style.MozColumnCount =
+ style.columnWidth = style.MozColumnWidth =
+ style.columnGap = style.MozColumnGap = '';
+ }
+
+ if (aTree.columnCount > 1) {
+ style.height = style.maxHeight =
+ Math.floor(aContainerBox.height * 0.9) + 'px';
+ }
+ else {
+ style.height = style.maxHeight = '';
+ }
}
};
diff --git a/modules/tabAttributesObserver.js b/modules/tabAttributesObserver.js
index 8a62231..f03a79e 100644
--- a/modules/tabAttributesObserver.js
+++ b/modules/tabAttributesObserver.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2014
+ * Portions created by the Initial Developer are Copyright (C) 2014-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -37,9 +37,12 @@ var EXPORTED_SYMBOLS = ['TabAttributesObserver'];
Components.utils.import('resource://treestyletab-modules/constants.js');
-function TabAttributesObserver(aContainer, aCallback) {
- this.container = aContainer;
- this.callback = aCallback;
+function TabAttributesObserver(aParams) {
+ this.container = aParams.container;
+ this.attributes = aParams.attributes;
+ if (typeof this.attributes == 'string')
+ this.attributes = this.attributes.split(',');
+ this.callback = aParams.callback;
this.init();
}
TabAttributesObserver.prototype = {
diff --git a/modules/tabAttributesObserver.js b/modules/tabContentsObserver.js
similarity index 54%
copy from modules/tabAttributesObserver.js
copy to modules/tabContentsObserver.js
index 8a62231..8592f91 100644
--- a/modules/tabAttributesObserver.js
+++ b/modules/tabContentsObserver.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2014
+ * Portions created by the Initial Developer are Copyright (C) 2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -33,74 +33,102 @@
*
* ***** END LICENSE BLOCK ******/
-var EXPORTED_SYMBOLS = ['TabAttributesObserver'];
+var EXPORTED_SYMBOLS = ['TabContentsObserver'];
+
+Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
Components.utils.import('resource://treestyletab-modules/constants.js');
-function TabAttributesObserver(aContainer, aCallback) {
- this.container = aContainer;
- this.callback = aCallback;
- this.init();
+XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
+
+function log(...aArgs) {
+ utils.log.apply(utils, ['tabContentsObserver'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['tabContentsObserver'].concat(aArgs));
+}
+
+function TabContentsObserver(aOwner, aBox, aOptions) {
+ this.owner = aOwner;
+ this.box = aBox;
+ this.init(aOptions);
}
-TabAttributesObserver.prototype = {
+TabContentsObserver.prototype = {
get MutationObserver()
{
- var w = this.container.ownerDocument.defaultView;
+ var w = this.box.ownerDocument.defaultView;
return w.MutationObserver || w.MozMutationObserver;
},
- init : function TabAttributesObserver_onInit()
+ init : function TabContentsObserver_onInit(aOptions)
{
if (!this.MutationObserver)
return;
this.observer = new this.MutationObserver((function(aMutations, aObserver) {
this.onMutation(aMutations, aObserver);
}).bind(this));
- this.observer.observe(this.container, {
- childList : false,
- attributes : true,
- subtree : true,
- attributeFilter : [
- 'label',
- 'visibleLabel',
- 'image'
- ]
- });
+ var options = {
+ childList : true,
+ attributes : false,
+ subtree : true
+ };
+ if (aOptions) {
+ Object.keys(options).forEach(function(aKey) {
+ if (aKey in aOptions)
+ options[aKey] = aOptions[aKey];
+ });
+ }
+ this.observer.observe(this.box, options);
},
- onMutation : function TabAttributesObserver_onMutation(aMutations, aObserver)
+ onMutation : function TabContentsObserver_onMutation(aMutations, aObserver)
{
aMutations.forEach(function(aMutation) {
- switch (aMutation.type)
- {
- case 'attributes':
- this.onAttributeModified(aMutation, aObserver);
- return;
+ try {
+ switch (aMutation.type)
+ {
+ case 'childList':
+ this.onTabContentsModified(aMutation, aObserver);
+ return;
+ }
+ }
+ catch(error) {
+ this.logMutation(aMutation, 'onMutation(error)');
+ Components.utils.reportError(error);
}
}, this);
},
- destroy : function TabAttributesObserver_destroy()
+ destroy : function TabContentsObserver_destroy()
{
if (this.observer) {
this.observer.disconnect();
delete this.observer;
}
- delete this.container;
+ delete this.box;
+ delete this.owner;
},
- onAttributeModified : function TabAttributesObserver_onAttributeModified(aMutation, aObserver)
+ onTabContentsModified : function TabContentsObserver_onTabContentsModified(aMutation, aObserver)
{
- if (this.handlingAttrChange ||
- aMutation.target.localName != 'tab')
+ var TST = this.owner.browser.treeStyleTab;
+ if (this.handlingChange ||
+ TST.notifyingRenderedEvent)
return;
- this.handlingAttrChange = true;
+ var target = aMutation.target;
+ var tab = TST.getTabFromChild(target);
+ if (!tab)
+ return;
+
+ log('onTabContentsModified on the tab '+tab._tPos);
+
+ this.handlingChange = true;
- this.callback(aMutation.target);
+ TST.initTabContentsOrder(tab, true);
- var w = this.container.ownerDocument.defaultView;
+ var w = this.box.ownerDocument.defaultView;
w.setTimeout((function() {
- this.handlingAttrChange = false;
+ this.handlingChange = false;
}).bind(this), 10);
}
};
diff --git a/modules/tabbarDNDObserver.js b/modules/tabbarDNDObserver.js
index e45033e..da0b61d 100644
--- a/modules/tabbarDNDObserver.js
+++ b/modules/tabbarDNDObserver.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2015
+ * Portions created by the Initial Developer are Copyright (C) 2010-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -63,6 +63,13 @@ const SSS = Cc['@mozilla.org/content/style-sheet-service;1']
const SecMan = Cc['@mozilla.org/scriptsecuritymanager;1']
.getService(Ci.nsIScriptSecurityManager);
+function log(...aArgs) {
+ utils.log.apply(utils, ['tabbarDNDObserver'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['tabbarDNDObserver'].concat(aArgs));
+}
+
function TabbarDNDObserver(aTabBrowser)
{
this.init(aTabBrowser);
@@ -72,14 +79,14 @@ TabbarDNDObserver.prototype = {
readyToStartTabbarDrag : function TabbarDND_readyToStartTabbarDrag()
{
- var sheet = this.treeStyleTab.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
+ var sheet = utils.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
if (!SSS.sheetRegistered(sheet, SSS.AGENT_SHEET))
SSS.loadAndRegisterSheet(sheet, SSS.AGENT_SHEET);
},
readyToEndTabbarDrag : function TabbarDND_readyToEndTabbarDrag()
{
- var sheet = this.treeStyleTab.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
+ var sheet = utils.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
if (SSS.sheetRegistered(sheet, SSS.AGENT_SHEET))
SSS.unregisterSheet(sheet, SSS.AGENT_SHEET);
},
@@ -89,7 +96,7 @@ TabbarDNDObserver.prototype = {
var sv = this.treeStyleTab;
if (
- sv.evaluateXPath(
+ utils.evaluateXPath(
'ancestor-or-self::*[' +
'contains(" scrollbar popup menupopup panel tooltip ", concat(" ", local-name(), " ")) or' +
'(local-name()="toolbarbutton" and @type="menu")' +
@@ -187,8 +194,7 @@ try{
return info.canDrop;
}
catch(e) {
- if (utils.isDebugging('tabbarDNDObserver'))
- dump('TabbarDND::canDrop\n'+e+'\n');
+ log('canDrop', e);
return false;
}
},
@@ -262,8 +268,7 @@ catch(e) {
getDropActionInternal : function TabbarDND_getDropActionInternal(aEvent, aSourceTab)
{
- if (utils.isDebugging('tabbarDNDObserver'))
- dump('getDropActionInternal: start\n');
+ log('getDropActionInternal: start');
var sv = this.treeStyleTab;
var b = this.browser;
var d = this.document;
@@ -304,21 +309,18 @@ catch(e) {
var isNewTabAction = !aSourceTab || aSourceTab.ownerDocument != d;
if (!tab || tab.localName != 'tab') {
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' not on a tab\n');
+ log(' not on a tab');
let action = isTabMoveFromOtherWindow ? sv.kACTION_STAY : (sv.kACTION_MOVE | sv.kACTION_PART) ;
if (isNewTabAction) action |= sv.kACTION_NEWTAB;
if (aEvent[sv.screenPositionProp] < sv.getTabActualScreenPosition(firstTab)) {
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' above the first tab\n');
+ log(' above the first tab');
info.target = info.parent = info.insertBefore = firstTab;
info.position = isInverted ? sv.kDROP_AFTER : sv.kDROP_BEFORE ;
info.action = action;
return info;
}
else if (aEvent[sv.screenPositionProp] > sv.getTabActualScreenPosition(tabs[lastTabIndex]) + tabs[lastTabIndex].boxObject[sv.sizeProp]) {
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' below the last tab\n');
+ log(' below the last tab');
info.target = info.parent = tabs[lastTabIndex];
info.position = isInverted ? sv.kDROP_BEFORE : sv.kDROP_AFTER ;
info.action = action;
@@ -328,30 +330,25 @@ catch(e) {
let index = b.getNewIndex ?
b.getNewIndex(aEvent) :
b.tabContainer._getDropIndex(aEvent) ;
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' on the tab '+index+'\n');
+ log(' on the tab '+index);
index = Math.min(index, lastTabIndex);
info.target = tab = tabs[index];
if (index == tabs[lastTabIndex]._tPos) {
if (index > 0)
info.target = tab = tabs[index - 1];
info.position = sv.kDROP_AFTER;
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' => after the last tab\n');
+ log(' => after the last tab');
} else if (index == firstTab._tPos) {
if (index < lastTabIndex - 1)
info.target = tab = tabs[index + 1];
info.position = sv.kDROP_BEFORE;
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' => before the first tab\n');
+ log(' => before the first tab');
}
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' info.target = ' + info.target._tPos + '\n');
+ log(' info.target = ' + info.target._tPos);
}
}
else {
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' on the tab '+tab._tPos+'\n');
+ log(' on the tab '+tab._tPos);
sv.ensureTabInitialized(tab);
info.target = tab;
}
@@ -387,21 +384,19 @@ catch(e) {
switch (info.position)
{
case sv.kDROP_ON:
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' position = on the tab\n');
+ log(' position = on the tab');
var visible = sv.getNextVisibleTab(tab);
info.action = sv.kACTION_STAY | sv.kACTION_ATTACH;
info.parent = tab;
info.insertBefore = utils.getTreePref('insertNewChildAt') == sv.kINSERT_FISRT ?
(sv.getFirstChildTab(tab) || visible) :
(sv.getNextSiblingTab(tab) || sv.getNextTab(sv.getLastDescendantTab(tab) || tab));
- if (utils.isDebugging('tabbarDNDObserver') && info.insertBefore)
- dump(' insertBefore = '+info.insertBefore._tPos+'\n');
+ if (info.insertBefore)
+ log(' insertBefore = '+info.insertBefore._tPos);
break;
case sv.kDROP_BEFORE:
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' position = before the tab\n');
+ log(' position = before the tab');
/*
<= detach from parent, and move
[TARGET ]
@@ -437,13 +432,12 @@ catch(e) {
info.action = sv.kACTION_MOVE | (info.parent ? sv.kACTION_ATTACH : sv.kACTION_PART );
info.insertBefore = tab;
}
- if (utils.isDebugging('tabbarDNDObserver') && info.insertBefore)
- dump(' insertBefore = '+info.insertBefore._tPos+'\n');
+ if (info.insertBefore)
+ log(' insertBefore = '+info.insertBefore._tPos);
break;
case sv.kDROP_AFTER:
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' position = after the tab\n');
+ log(' position = after the tab');
/*
[TARGET ]
<= if the target has a parent, attach to it and and move
@@ -487,8 +481,8 @@ catch(e) {
}
}
}
- if (utils.isDebugging('tabbarDNDObserver') && info.insertBefore)
- dump(' insertBefore = '+info.insertBefore._tPos+'\n');
+ if (info.insertBefore)
+ log(' insertBefore = '+info.insertBefore._tPos);
break;
}
@@ -499,16 +493,14 @@ catch(e) {
performDrop : function TabbarDND_performDrop(aInfo, aDraggedTab)
{
- if (utils.isDebugging('tabbarDNDObserver'))
- dump('performDrop: start\n');
+ log('performDrop: start');
var sv = this.treeStyleTab;
var b = this.browser;
var w = this.window;
var tabsInfo = this.getDraggedTabsInfoFromOneTab(aDraggedTab, aInfo);
if (!tabsInfo.draggedTab) {
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' => no dragged tab\n');
+ log(' => no dragged tab');
return false;
}
@@ -565,14 +557,13 @@ catch(e) {
sourceBrowser == targetBrowser &&
sourceService.getNextVisibleTab(draggedTabs[draggedTabs.length-1]) == aInfo.insertBefore
) {
- if (utils.isDebugging('tabbarDNDObserver'))
- dump(' => no change\n');
+ log(' => no change');
// then, do nothing
return true;
}
}
- var treeStructure = sourceService.getTreeStructureFromTabs(draggedTabs);
+ var treeStructure = utils.getTreeStructureFromTabs(draggedTabs);
var newTabs = sv.moveTabsInternal(draggedTabs, {
duplicate : aInfo.action & sv.kACTION_DUPLICATE,
@@ -1053,8 +1044,7 @@ try{
return (info.position == sv.kDROP_ON || sv.position != 'top')
}
catch(e) {
- if (utils.isDebugging('tabbarDNDObserver'))
- dump('TabbarDND::onDragOver\n'+e+'\n');
+ log('onDragOver', e);
}
},
@@ -1100,10 +1090,9 @@ catch(e) {
var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
- if (utils.isDebugging('tabbarDNDObserver'))
- dump('TabbarDND::onDrop\n' +
- ' dt.dropEffect: ' + dt.dropEffect + '\n' +
- ' draggedTab: ' + draggedTab + '\n');
+ log('TabbarDND::onDrop',
+ ' dt.dropEffect: ' + dt.dropEffect,
+ ' draggedTab: ' + draggedTab);
if (dt.dropEffect != 'link' &&
dt.dropEffect != 'move' &&
@@ -1173,9 +1162,8 @@ catch(e) {
if (aURI.indexOf(this.BOOKMARK_FOLDER) == 0) {
let newTabs = sv.getNewTabsWithOperation(function() {
var data = aURI.replace(self.BOOKMARK_FOLDER, '');
- if (utils.isDebugging('tabbarDNDObserver'))
- dump('TabbarDND::handleLinksOrBookmarks\n' +
- ' bookmark folder data: ' + data + '\n');
+ log('TabbarDND::handleLinksOrBookmarks' +
+ ' bookmark folder data: ' + data);
data = JSON.parse(data);
w.PlacesUIUtils._openTabset(data.children, { type : 'drop' }, w, data.title);
}, b);
@@ -1231,7 +1219,7 @@ catch(e) {
}
let normalizedURI;
try {
- normalizedURI = this.treeStyleTab.makeURIFromSpec(aURI);
+ normalizedURI = utils.makeURIFromSpec(aURI);
}
catch(e) {
}
@@ -1303,7 +1291,7 @@ catch(e) {
}
// When a blank folder is dropped, just open a dummy tab with the folder name.
if (children && children.length == 0) {
- let uri = this.treeStyleTab.getGroupTabURI({ title: item.title });
+ let uri = utils.getGroupTabURI({ title: item.title });
return [uri];
}
}
diff --git a/modules/utils.js b/modules/utils.js
index 240602f..368318b 100644
--- a/modules/utils.js
+++ b/modules/utils.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2015
+ * Portions created by the Initial Developer are Copyright (C) 2010-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -63,11 +63,13 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Task',
'resource://gre/modules/Task.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Promise',
'resource://gre/modules/Promise.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Services',
+ 'resource://gre/modules/Services.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabConstants',
'resource://treestyletab-modules/constants.js', 'TreeStyleTabConstants');
const TST_PREF_PREFIX = 'extensions.treestyletab.';
-const TST_PREF_VERSION = 11;
+const TST_PREF_VERSION = 12;
var TreeStyleTabUtils = {
@@ -221,6 +223,13 @@ var TreeStyleTabUtils = {
this.setTreePref('maxTreeLevel.physical', physical);
this.clearTreePref('maxTreeLevel.phisical');
}
+ case 11:
+ {
+ prefs.clearPref('browser.tabs.insertRelatedAfterCurrent');
+ let backupValue = prefs.getPref('browser.tabs.insertRelatedAfterCurrent.backup');
+ if (backupValue !== null)
+ prefs.setPref('browser.tabs.insertRelatedAfterCurrent', backupValue);
+ }
default:
for (let i = 0, maxi = orientalPrefs.length; i < maxi; i++)
{
@@ -243,6 +252,81 @@ var TreeStyleTabUtils = {
return this.getTreePref('debug.' + aModule) || this.getTreePref('debug.all');
},
+ log : function utils_log(aModule, ...aArgs)
+ {
+ if (!this.isDebugging(aModule))
+ return;
+
+ var logString = '[treestyletab:' + aModule+'] '+ aArgs.map(this.objectToLogString, this).join('');
+ Services.console.logStringMessage(logString);
+ dump(logString+'\n');
+ },
+ logWithStackTrace : function utils_logWithStackTrace(aModule, ...aArgs)
+ {
+ var stack = (new Error()).stack.replace(/^/gm, ' ');
+ return this.log.apply(this, [aModule].concat(aArgs).concat([stack]));
+ },
+ objectToLogString : function utils_objectToLogString(aObject)
+ {
+ if (!aObject)
+ return JSON.stringify(aObject);
+
+ if (/^(string|number|boolean)$/.test(typeof aObject))
+ return aObject;
+
+ return this.objectToString(aObject);
+ },
+ objectToString : function utils_objectToString(aObject)
+ {
+ try {
+ if (!aObject ||
+ /^(string|number|boolean)$/.test(typeof aObject))
+ return JSON.stringify(aObject);
+
+ if (Array.isArray(aObject))
+ return '['+aObject.map(this.objectToString, this).join(', ')+']';
+
+ var constructor = String(aObject.constructor).match(/^function ([^\(]+)/);
+ if (constructor) {
+ constructor = constructor[1];
+ switch (constructor)
+ {
+ case 'String':
+ case 'Number':
+ case 'Boolean':
+ return JSON.stringify(aObject);
+
+ case 'Object':
+ return '{' + Object.keys(aObject).map(function(aKey) {
+ return '"' + aKey + '":' + this.objectToString(aObject[aKey]);
+ }, this).join(', ') + '}';
+
+ default:
+ break;
+ }
+
+ if (/Element$/.test(constructor)) {
+ let id = '';
+ if (aObject.hasAttribute('id'))
+ id = '#' + aObject.getAttribute('id');
+
+ let classes = '';
+ if (aObject.className)
+ classes = '.' + aObject.className.replace(/\s+/g, '.');
+
+ return '<' + aObject.localName + id + classes + '>';
+ }
+
+ return '<object '+constructor+'>';
+ }
+
+ return String(aObject);
+ }
+ catch(e) {
+ return String(e);
+ }
+ },
+
/* string bundle */
get treeBundle () {
return stringBundle.get('chrome://treestyletab/locale/treestyletab.properties');
@@ -328,6 +412,288 @@ var TreeStyleTabUtils = {
this.isPrefChanging(aKey);
},
+
+// xpath
+
+ NSResolver : {
+ lookupNamespaceURI : function(aPrefix)
+ {
+ switch (aPrefix)
+ {
+ case 'xul':
+ return 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
+ case 'html':
+ case 'xhtml':
+ return 'http://www.w3.org/1999/xhtml';
+ case 'xlink':
+ return 'http://www.w3.org/1999/xlink';
+ default:
+ return '';
+ }
+ }
+ },
+
+ evaluateXPath : function utils_evaluateXPath(aExpression, aContext, aType)
+ {
+ if (!aType)
+ aType = Ci.nsIDOMXPathResult.ORDERED_NODE_SNAPSHOT_TYPE;
+ try {
+ var XPathResult = (aContext.ownerDocument || aContext).evaluate(
+ aExpression,
+ (aContext || document),
+ this.NSResolver,
+ aType,
+ null
+ );
+ }
+ catch(e) {
+ return {
+ singleNodeValue : null,
+ snapshotLength : 0,
+ snapshotItem : function() {
+ return null
+ }
+ };
+ }
+ return XPathResult;
+ },
+
+ getArrayFromXPathResult : function utils_getArrayFromXPathResult(aXPathResult)
+ {
+ var max = aXPathResult.snapshotLength;
+ var array = new Array(max);
+ if (!max)
+ return array;
+
+ for (var i = 0; i < max; i++)
+ {
+ array[i] = aXPathResult.snapshotItem(i);
+ }
+
+ return array;
+ },
+
+
+ getTabBrowserFromChild : function utils_getTabBrowserFromChild(aTabBrowserChild)
+ {
+ if (!aTabBrowserChild)
+ return null;
+
+ if (aTabBrowserChild.__treestyletab__linkedTabBrowser) // tab
+ return aTabBrowserChild.__treestyletab__linkedTabBrowser;
+
+ if (aTabBrowserChild.localName == 'tabbrowser') // itself
+ return aTabBrowserChild;
+
+ if (aTabBrowserChild.tabbrowser) // tabs
+ return aTabBrowserChild.tabbrowser;
+
+ if (aTabBrowserChild.localName == 'toolbar') // tabs toolbar
+ return aTabBrowserChild.getElementsByTagName('tabs')[0].tabbrowser;
+
+ // tab context menu
+ var popup = this.evaluateXPath(
+ 'ancestor-or-self::xul:menupopup[@id="tabContextMenu"]',
+ aTabBrowserChild,
+ Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
+ ).singleNodeValue;
+ if (popup && 'TabContextMenu' in aTabBrowserChild.ownerDocument.defaultView)
+ return this.getTabBrowserFromChild(aTabBrowserChild.ownerDocument.defaultView.TabContextMenu.contextTab);
+
+ var b = this.evaluateXPath(
+ 'ancestor::xul:tabbrowser | '+
+ 'ancestor::xul:tabs[@tabbrowser] |'+
+ 'ancestor::xul:toolbar/descendant::xul:tabs',
+ aTabBrowserChild,
+ Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
+ ).singleNodeValue;
+ return (b && b.tabbrowser) || b;
+ },
+
+
+
+ getTreeStructureFromTabs : function TSTUtils_getTreeStructureFromTabs(aTabs)
+ {
+ if (!aTabs || !aTabs.length)
+ return [];
+
+ /* this returns...
+ [A] => -1 (parent is not in this tree)
+ [B] => 0 (parent is 1st item in this tree)
+ [C] => 0 (parent is 1st item in this tree)
+ [D] => 2 (parent is 2nd in this tree)
+ [E] => -1 (parent is not in this tree, and this creates another tree)
+ [F] => 0 (parent is 1st item in this another tree)
+ */
+ var browser = this.getTabBrowserFromChild(aTabs[0]);
+ return this.cleanUpTreeStructureArray(
+ aTabs.map(function(aTab, aIndex) {
+ let tab = browser.treeStyleTab.getParentTab(aTab);
+ let index = tab ? aTabs.indexOf(tab) : -1 ;
+ return index >= aIndex ? -1 : index ;
+ }, this),
+ -1
+ );
+ },
+ cleanUpTreeStructureArray : function TSTUtils_cleanUpTreeStructureArray(aTreeStructure, aDefaultParent)
+ {
+ var offset = 0;
+ aTreeStructure = aTreeStructure
+ .map(function(aPosition, aIndex) {
+ return (aPosition == aIndex) ? -1 : aPosition ;
+ })
+ .map(function(aPosition, aIndex) {
+ if (aPosition == -1) {
+ offset = aIndex;
+ return aPosition;
+ }
+ return aPosition - offset;
+ });
+
+ /* The final step, this validates all of values.
+ Smaller than -1 is invalid, so it becomes to -1. */
+ aTreeStructure = aTreeStructure.map(function(aIndex) {
+ return aIndex < -1 ? aDefaultParent : aIndex ;
+ }, this);
+ return aTreeStructure;
+ },
+
+
+ updateNarrowScrollbarStyle : function utils_updateNarrowScrollbarStyle(aTabBrowser)
+ {
+ if (this.updatingNarrowScrollbarStyle)
+ return;
+
+ this.updatingNarrowScrollbarStyle = true;
+ setTimeout((function() {
+ this.updatingNarrowScrollbarStyle = false;
+ }).bind(this), 100);
+
+ const SSS = Cc['@mozilla.org/content/style-sheet-service;1']
+ .getService(Ci.nsIStyleSheetService);
+
+ if (this.lastAgentSheetForNarrowScrollbar &&
+ SSS.sheetRegistered(this.lastAgentSheetForNarrowScrollbar, SSS.AGENT_SHEET))
+ SSS.unregisterSheet(this.lastAgentSheetForNarrowScrollbar, SSS.AGENT_SHEET);
+
+ var scrollbox = aTabBrowser.tabContainer.mTabstrip._scrollbox;
+ var d = scrollbox.ownerDocument;
+
+ // We have to calculate the width of the scroll bar indirectly
+ // based on the width of the container and the scrollable contents,
+ // because the scrollbar is not accessible via public APIs.
+ var scrollbarSize = this.lastOriginalScrollbarSize;
+ if (scrollbarSize == 0) {
+ let nodes = d.getAnonymousNodes(scrollbox);
+ if (nodes) {
+ for (let i = 0, maxi = nodes.length; i < maxi; i++)
+ {
+ if (nodes[i].localName != 'box')
+ continue;
+ scrollbarSize = scrollbox.boxObject.width - nodes[i].boxObject.width;
+ break;
+ }
+ }
+ }
+
+ var size = this.getTreePref('tabbar.narrowScrollbar.width');
+ var rulesToSizeScrollbar;
+ var rulesToSizeScrollbarContents;
+ if (scrollbarSize) {
+ let overWidth = size - scrollbarSize;
+ let leftMargin = Math.floor(overWidth / 2);
+ let rightMargin = overWidth - leftMargin;
+ rulesToSizeScrollbar = 'margin-left: '+leftMargin+'px;' +
+ 'margin-right: '+rightMargin+'px;';
+ }
+ else {
+ rulesToSizeScrollbar = 'font-size: '+size+'px;';
+ rulesToSizeScrollbarContents = 'max-width: '+size+'px;' +
+ 'min-width: '+size+'px;';
+ }
+
+ const style = 'data:text/css,'+encodeURIComponent(
+ ('@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");' +
+
+ (rulesToSizeScrollbarContents ?
+ 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
+ ' .tabbrowser-arrowscrollbox' +
+ ' > scrollbox' +
+ ' > scrollbar[orient="vertical"],' +
+ 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
+ ' .tabbrowser-arrowscrollbox' +
+ ' > scrollbox' +
+ ' > scrollbar[orient="vertical"] * {' + rulesToSizeScrollbarContents + '}' : '' ) +
+
+ 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
+ ' .tabbrowser-arrowscrollbox' +
+ ' > scrollbox' +
+ ' > scrollbar[orient="vertical"] {' + rulesToSizeScrollbar + '}' +
+
+ 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
+ ' .tabbrowser-arrowscrollbox' +
+ ' > scrollbox' +
+ ' > scrollbar[orient="vertical"] * {' +
+ ' padding-left: 0;' +
+ ' padding-right: 0;' +
+ ' margin-left: 0;' +
+ ' margin-right: 0;' +
+ '}' +
+
+ '%FORCE_NARROW_SCROLLBAR%')
+ .replace(/%FORCE_NARROW_SCROLLBAR%/g,
+ this.getTreePref('tabbar.narrowScrollbar.overrideSystemAppearance') ?
+ TreeStyleTabConstants.kOVERRIDE_SYSTEM_SCROLLBAR_APPEARANCE : '' )
+ .replace(/%MODE%/g, TreeStyleTabConstants.kMODE)
+ .replace(/%NARROW%/g, TreeStyleTabConstants.kNARROW_SCROLLBAR)
+ .replace(/%SIZE%/g, size)
+ );
+ this.lastAgentSheetForNarrowScrollbar = this.makeURIFromSpec(style);
+ SSS.loadAndRegisterSheet(this.lastAgentSheetForNarrowScrollbar, SSS.AGENT_SHEET);
+ },
+ kOVERRIDE_SYSTEM_SCROLLBAR_APPEARANCE :
+ 'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
+ ' .tabbrowser-arrowscrollbox' +
+ ' > scrollbox' +
+ ' > scrollbar[orient="vertical"] {' +
+ ' appearance: none;' +
+ ' -moz-appearance: none;' +
+ ' background: ThreeDFace;' +
+ ' border: 1px solid ThreeDShadow;' +
+ '}',
+ lastAgentSheetForNarrowScrollbar : null,
+ lastOriginalScrollbarSize : 0,
+
+
+
+
+ makeURIFromSpec : function utils_makeURIFromSpec(aURI)
+ {
+ var newURI;
+ aURI = aURI || '';
+ if (aURI && String(aURI).indexOf('file:') == 0) {
+ var fileHandler = Services.io.getProtocolHandler('file').QueryInterface(Ci.nsIFileProtocolHandler);
+ var tempLocalFile = fileHandler.getFileFromURLSpec(aURI);
+ newURI = Services.io.newFileURI(tempLocalFile);
+ }
+ else {
+ if (!/^\w+\:/.test(aURI))
+ aURI = 'http://'+aURI;
+ newURI = Services.io.newURI(aURI, null, null);
+ }
+ return newURI;
+ },
+
+ getGroupTabURI : function utils_getGroupTabURI(aOptions)
+ {
+ aOptions = aOptions || {};
+ var parameters = [];
+ parameters.push('title=' + encodeURIComponent(aOptions.title || ''));
+ parameters.push('temporary=' + !!aOptions.temporary);
+ return 'about:treestyletab-group?' + parameters.join('&');
+ },
+
+
/* Pref Listener */
domains : [
'extensions.treestyletab.'
diff --git a/modules/window.js b/modules/window.js
index d9b15dd..5624ac5 100644
--- a/modules/window.js
+++ b/modules/window.js
@@ -14,7 +14,7 @@
* The Original Code is the Tree Style Tab.
*
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2012-2015
+ * Portions created by the Initial Developer are Copyright (C) 2012-2016
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
@@ -71,6 +71,13 @@ XPCOMUtils.defineLazyModuleGetter(this, 'ContentBridge', 'resource://treestyleta
XPCOMUtils.defineLazyServiceGetter(this, 'SessionStore',
'@mozilla.org/browser/sessionstore;1', 'nsISessionStore');
+function log(...aArgs) {
+ utils.log.apply(utils, ['window'].concat(aArgs));
+}
+function logWithStackTrace(...aArgs) {
+ utils.logWithStackTrace.apply(utils, ['window'].concat(aArgs));
+}
+
function TreeStyleTabWindow(aWindow)
{
this.window = aWindow;
@@ -714,7 +721,12 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
return this.onKeyRelease(aEvent);
case 'blur':
- return this.simulateKeyRelease();
+ let activeWindow = Cc['@mozilla.org/focus-manager;1']
+ .getService(Ci.nsIFocusManager)
+ .activeWindow;
+ if (!activeWindow || activeWindow != this.window)
+ this.simulateKeyRelease();
+ return;
case 'mousedown':
return this.onTabbarResizeStart(aEvent);
@@ -729,7 +741,11 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
return this.onTabbarReset(aEvent);
case 'click':
- return this.handleNewTabActionOnButton(aEvent);
+ if (aEvent.currentTarget.localName == 'splitter')
+ this.onTabbarSplitterClick(aEvent);
+ else
+ this.handleNewTabActionOnButton(aEvent);
+ return;
case 'beforecustomization':
@@ -964,18 +980,11 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
get shouldListenKeyEventsForAutoExpandByFocusChange()
{
- return !this.ctrlTabPreviewsEnabled &&
- (
+ return (
utils.getTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut') ||
utils.getTreePref('autoCollapseExpandSubtreeOnSelect')
);
},
-
- get ctrlTabPreviewsEnabled()
- {
- return 'allTabs' in this.window &&
- prefs.getPref('browser.ctrlTab.previews');
- },
receiveMessage : function TSTWindow_receiveMessage(aMessage)
{
@@ -1104,6 +1113,44 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
}
},
+ onTabbarSplitterClick : function TSTWindow_onTabbarSplitterClick(aEvent)
+ {
+ if (
+ aEvent.button != 1 ||
+ (aEvent.button == 0 && !isAccelKeyPressed(aEvent))
+ )
+ return;
+
+ var grippy = utils.evaluateXPath(
+ 'ancestor-or-self::*[local-name()="grippy"]',
+ aEvent.originalTarget || aEvent.target,
+ Ci.nsIDOMXPathResult.BOOLEAN_TYPE
+ ).booleanValue;
+ if (grippy && aEvent.button == 0)
+ return;
+
+ this.onTabbarToggleCollapsed(aEvent.currentTarget);
+ },
+ onTabbarToggleCollapsed : function TSTWindow_onTabbarToggleCollapsed(aTarget)
+ {
+ var b = this.getTabBrowserFromChild(aTarget);
+ var splitter = b.treeStyleTab.splitter;
+
+ var state = splitter.getAttribute('state');
+ var newState = state == 'collapsed' ? 'open' : 'collapsed';
+ splitter.setAttribute('state', newState);
+
+ // Workaround for bugs:
+ // * https://github.com/piroor/treestyletab/issues/593
+ // * https://github.com/piroor/treestyletab/issues/783
+ b.ownerDocument.defaultView.setTimeout(function() {
+ var visible = splitter.getAttribute('state') != 'collapsed';
+ var tabContainer = b.tabContainer;
+ if (visible != tabContainer.visible)
+ tabContainer.visible = visible;
+ }, 0);
+ },
+
onFocusNextTab : function TSTWindow_onFocusNextTab(aEvent)
{
var tab = aEvent.originalTarget;
@@ -1238,7 +1285,7 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
onPopupShown : function TSTWindow_onPopupShown(aPopup)
{
if (!aPopup.boxObject ||
- this.evaluateXPath(
+ utils.evaluateXPath(
'parent::*/ancestor-or-self::*[local-name()="tooltip" or local-name()="panel" or local-name()="popup" or local-name()="menupopup"]',
aPopup,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
@@ -1333,29 +1380,44 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
this.handleNewTabFromCurrent(aOwner);
},
- onBeforeOpenLinkWithTab : function TSTWindow_onBeforeOpenLinkWithTab(aTab, aFromChrome)
+ onBeforeOpenLinkWithTab : function TSTWindow_onBeforeOpenLinkWithTab(aTab, aParams)
{
- if (!aFromChrome && aTab && !this.checkToOpenChildTab(aTab))
- this.handleNewTabFromCurrent(aTab);
+ if (!aTab)
+ return;
+
+ log('onBeforeOpenLinkWithTab: ', [aTab, aParams, this.checkToOpenChildTab(aTab)]);
+
+ if (!this.checkToOpenChildTab(aTab)) {
+ if (!aParams.fromChrome)
+ this.handleNewTabFromCurrent(aTab);
+ else if (!aParams.relatedToCurrent && !aParams.referrerURI)
+ this.readyToOpenOrphanTabNow(aTab);
+ }
},
onBeforeOpenNewTabByThirdParty : function TSTWindow_onBeforeOpenNewTabByThirdParty(aOwner)
{
- if (!this.checkToOpenChildTab(aOwner))
+ log('onBeforeOpenNewTabByThirdParty: ', [aOwner, this.checkToOpenChildTab(aTab)]);
+
+ if (!this.checkToOpenChildTab(aOwner)) {
this.handleNewTabFromCurrent(aOwner);
+ }
},
- onBeforeBrowserAccessOpenURI : function TSTWindow_onBeforeBrowserAccessOpenURI(aOpener, aWhere, aContext)
+ onBeforeBrowserAccessOpenURI : function TSTWindow_onBeforeBrowserAccessOpenURI(aOpener, aWhere)
{
var hasOwnerTab = false;
var opener = null;
if (aOpener) {
if (aOpener instanceof Ci.nsIDOMWindow) {
+ log('onBeforeBrowserAccessOpenURI: opener is DOMWindow');
opener = aOpener;
hasOwnerTab = this.getTabFromFrame(opener.top);
+ log(' opener =>', [opener, hasOwnerTab]);
}
else if (Ci.nsIOpenURIInFrameParams &&
aOpener instanceof Ci.nsIOpenURIInFrameParams) {
+ log('TSTWindow_onBeforeBrowserAccessOpenURI: opener is nsIOpenURIInFrameParams');
// from remote contents, we have to detect its opener from the URI.
let referrer = aOpener.referrer;
if (referrer) {
@@ -1370,25 +1432,53 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
break;
}
}
+ log(' opener =>', [opener, hasOwnerTab]);
}
}
- var internalOpen = aContext != Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL;
- if ((hasOwnerTab || internalOpen) &&
+ if (aOpener &&
+ hasOwnerTab &&
aWhere == Ci.nsIBrowserDOMWindow.OPEN_NEWTAB)
this.handleNewTabFromCurrent(opener);
+ else
+ this.readyToOpenOrphanTabNow(opener);
+ },
+
+ onBeforeGoHome : function TSTWindow_onBeforeGoHome(aEvent, aTabBrowser)
+ {
+ if (!aEvent || aEvent.button === 2 || !aTabBrowser)
+ return;
+
+ var where = this.window.whereToOpenLink(aEvent, false, true);
+ if (where == 'current' && aTabBrowser.selectedTab.pinned)
+ where = 'tab';
+
+ if (where.indexOf('tab') === 0)
+ this.readyToOpenNewTabGroupNow(aTabBrowser);
+ else
+ this.readyToOpenOrphanTabNow(aTabBrowser);
},
onBeforeViewMedia : function TSTWindow_onBeforeViewMedia(aEvent, aOwner)
{
- if (String(this.window.whereToOpenLink(aEvent, false, true)).indexOf('tab') == 0)
+ var where = String(this.window.whereToOpenLink(aEvent, false, true));
+
+ log('onBeforeViewMedia: ', [aEvent, aOwner, where]);
+
+ if (where.indexOf('tab') == 0)
this.handleNewTabFromCurrent(aOwner);
+ else
+ this.readyToOpenOrphanTabNow(aOwner);
},
onBeforeBrowserSearch : function TSTWindow_onBeforeBrowserSearch(aTerm, aForceNewTab)
{
+ log('onBeforeBrowserSearch: ', [aTerm, aForceNewTab, this.shouldOpenSearchResultAsChild(aTerm)]);
+
if ((arguments.length == 1 || aForceNewTab) &&
this.shouldOpenSearchResultAsChild(aTerm))
this.handleNewTabFromCurrent();
+ else
+ this.readyToOpenOrphanTabNow();
},
/* Tree Style Tabの初期化が行われる前に復元されたセッションについてツリー構造を復元 */
@@ -1575,6 +1665,10 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
createSubtree : function TSTWindow_createSubtree(aTabs)
{
+ log('TSTWindow_createSubtree\n'+aTabs.map(function(aTab) {
+ return ' '+aTab._tPos+': '+aTab.linkedBrowser.currentURI.spec;
+ }).join('\n'));
+
var rootTabs = this.getRootTabs(aTabs);
var parent = this.getParentTab(aTabs[0]);
@@ -1594,6 +1688,7 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
var parentInTargets = aTabs.indexOf(this.getParentTab(aDescendantTab)) > -1;
if (inTargets || (inTargets == parentInTargets))
return;
+ log(' detaching unselected descendant: '+aDescendantTab._tPos+': '+aDescendantTab.linkedBrowser.currentURI.spec);
if (parentTab)
b.treeStyleTab.attachTabTo(aDescendantTab, parentTab, {
dontExpand : true,
@@ -1609,7 +1704,7 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
var shouldCreateGroup = aTabs.length > 1 && utils.getTreePref('createSubtree.underParent');
var root = shouldCreateGroup ?
- b.addTab(this.getGroupTabURI({
+ b.addTab(utils.getGroupTabURI({
temporary: utils.getTreePref('createSubtree.underParent.temporaryGroup')
})) :
aTabs.shift() ;
@@ -1880,8 +1975,7 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
/* Pref Listener */
domains : [
- 'extensions.treestyletab',
- 'browser.ctrlTab.previews'
+ 'extensions.treestyletab'
],
onPrefChange : function TSTWindow_onPrefChange(aPrefName)
@@ -1894,7 +1988,6 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, {
this.themeManager.set(prefs.getPref('extensions.treestyletab.tabbar.style'), this.position);
break;
- case 'browser.ctrlTab.previews':
case 'extensions.treestyletab.autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut':
case 'extensions.treestyletab.autoCollapseExpandSubtreeOnSelect':
if (this.shouldListenKeyEventsForAutoExpandByFocusChange)
diff --git a/skin/classic/treestyletab/group.css b/skin/classic/treestyletab/group.css
index eb4457d..14d1d8d 100644
--- a/skin/classic/treestyletab/group.css
+++ b/skin/classic/treestyletab/group.css
@@ -1,3 +1,6 @@
+ at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+ at namespace xhtml url("http://www.w3.org/1999/xhtml");
+
:root {
appearance: window;
-moz-appearance: window;
@@ -57,12 +60,16 @@
#tree {
- margin-top: 1em;
+ margin: 1em 0 0 0.5em;
overflow: auto;
box-flex: 1;
-moz-box-flex: 1;
}
-.treestyletab-pseudo-tree-root-item {
- display: none;
+*|*.treestyletab-pseudo-tree-root-item {
+ display: none !important;
+}
+*|*.treestyletab-pseudo-tree-root-item +
+ *|*.treestyletab-pseudo-tree-children > *|* {
+ margin-left: 0 !important;
}
diff --git a/skin/classic/treestyletab/license.txt b/skin/classic/treestyletab/license.txt
index 6f14a29..023b08a 100644
--- a/skin/classic/treestyletab/license.txt
+++ b/skin/classic/treestyletab/license.txt
@@ -14,7 +14,7 @@ License.
The Original Code is the Tree Style Tab.
The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
-Portions created by the Initial Developer are Copyright (C) 2007-2013
+Portions created by the Initial Developer are Copyright (C) 2007-2016
the Initial Developer. All Rights Reserved.
Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex at gmail.com>
diff --git a/skin/classic/treestyletab/metal/base.css b/skin/classic/treestyletab/metal/base.css
index d38fe58..5977ab5 100644
--- a/skin/classic/treestyletab/metal/base.css
+++ b/skin/classic/treestyletab/metal/base.css
@@ -40,6 +40,23 @@
border-width: 1px 0 0 !important;
padding: 0 !important;
}
+/* these styles are required to cover narrow scrollbars. */
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to left,
+ rgba(121,121,121,1) 0%,
+ rgba(121,121,121,1) 10%,
+ rgba(121,121,121,0) 11%,
+ rgba(121,121,121,0) 100%) !important;
+}
+.tabbrowser-tabs[treestyletab-tabbar-position="left"][treestyletab-invert-scrollbar="true"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to right,
+ rgba(121,121,121,1) 0%,
+ rgba(121,121,121,1) 10%,
+ rgba(121,121,121,0) 11%,
+ rgba(121,121,121,0) 100%) !important;
+}
.tabbrowser-tabs[treestyletab-mode="vertical"] {
appearance: none !important;
@@ -51,14 +68,20 @@
.tabbrowser-tabs[treestyletab-mode="vertical"]:not([overflow="true"])
.tabbrowser-arrowscrollbox,
.tabbrowser-tabs[treestyletab-mode="vertical"][overflow="true"]
- .tabbrowser-arrowscrollbox .scrollbox-innerbox {
- background: url("shadow-active-l.png") repeat-y top right !important;
+ .tabbrowser-arrowscrollbox
+ scrollbox {
+ background-image: url("shadow-active-l.png") !important;
+ background-repeat: repeat-y !important;
+ background-position: top right !important;
}
.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]:not([overflow="true"])
.tabbrowser-arrowscrollbox,
.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"][overflow="true"]
- .tabbrowser-arrowscrollbox .scrollbox-innerbox {
- background: url("shadow-active-r.png") repeat-y top left !important;
+ .tabbrowser-arrowscrollbox
+ scrollbox {
+ background-image: url("shadow-active-r.png") !important;
+ background-repeat: repeat-y !important;
+ background-position: top left !important;
}
.tabbrowser-tabs[treestyletab-mode="vertical"]
@@ -100,8 +123,30 @@ tabbrowser[treestyletab-tabbar-position="right"]
background: #acacac !important;
border-color: #797979 !important;
}
+/* these styles are required to cover narrow scrollbars. */
:root:-moz-window-inactive
- .tabbrowser-strip[treestyletab-mode="vertical"][treestyletab-style~="aero"] {
+ .tabbrowser-tabs[treestyletab-mode="vertical"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to left,
+ rgba(172,172,172,1) 0%,
+ rgba(172,172,172,1) 10%,
+ rgba(172,172,172,0) 11%,
+ rgba(172,172,172,0) 100%) !important;
+}
+:root:-moz-window-inactive
+ .tabbrowser-tabs[treestyletab-tabbar-position="left"][treestyletab-invert-scrollbar="true"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to right,
+ rgba(172,172,172,1) 0%,
+ rgba(172,172,172,1) 10%,
+ rgba(172,172,172,0) 11%,
+ rgba(172,172,172,0) 100%) !important;
+}
+:root:-moz-window-inactive
+ .tabbrowser-strip[treestyletab-mode="vertical"][treestyletab-style~="aero"],
+:root:-moz-window-inactive
+ .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style~="aero"]
+ .scrollbox-innerbox {
background: transparent !important;
}
@@ -110,8 +155,11 @@ tabbrowser[treestyletab-tabbar-position="right"]
.tabbrowser-arrowscrollbox,
:root:-moz-window-inactive
.tabbrowser-tabs[treestyletab-mode="vertical"][overflow="true"]
- .tabbrowser-arrowscrollbox .scrollbox-innerbox {
- background: url("shadow-inactive-l.png") repeat-y top right !important;
+ .tabbrowser-arrowscrollbox
+ scrollbox {
+ background-image: url("shadow-inactive-l.png") !important;
+ background-repeat: repeat-y !important;
+ background-position: top right !important;
}
:root:-moz-window-inactive
.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]:not([overflow="true"])
@@ -119,8 +167,10 @@ tabbrowser[treestyletab-tabbar-position="right"]
:root:-moz-window-inactive
.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"][overflow="true"]
.tabbrowser-arrowscrollbox
- .scrollbox-innerbox {
- background: url("shadow-inactive-r.png") repeat-y top left !important;
+ scrollbox {
+ background-image: url("shadow-inactive-r.png") !important;
+ background-repeat: repeat-y !important;
+ background-position: top left !important;
}
:root:-moz-window-inactive
diff --git a/skin/classic/treestyletab/pseudo-tree.css b/skin/classic/treestyletab/pseudo-tree.css
index 311bf76..73ae9a8 100644
--- a/skin/classic/treestyletab/pseudo-tree.css
+++ b/skin/classic/treestyletab/pseudo-tree.css
@@ -1,25 +1,35 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+ at namespace xhtml url("http://www.w3.org/1999/xhtml");
-.treestyletab-pseudo-tree-favicon {
+*|*.treestyletab-pseudo-tree-favicon {
height: 16px;
max-width: 16px;
max-height: 16px;
+ position: relative;
+ top: 0.25em;
width: 16px;
}
-.treestyletab-pseudo-tree-row {
- box-align: center;
- -moz-box-align: center;
+*|*.treestyletab-pseudo-tree-item {
+ display: block;
+ line-height: 1.5;
+ margin-bottom: 0.15em;
+ white-space: pre;
}
-.treestyletab-pseudo-tree-row label.text-link {
- box-crop: end;
- -moz-box-crop: end;
+*|*.treestyletab-pseudo-tree-row {
+ display: block;
}
-.treestyletab-pseudo-tree-children {
+*|*.treestyletab-pseudo-tree-row label.text-link {
+ display: inline-block;
+ margin: 0;
+ padding: 0 0 0 0.25em;
+ vertical-align: text-top;
+ white-space: pre-wrap;
+}
+
+*|*.treestyletab-pseudo-tree-children > *|* {
margin-left: 1.5em;
- box-align: stretch;
- -moz-box-align: stretch;
}
diff --git a/skin/classic/treestyletab/sidebar/sidebar.css b/skin/classic/treestyletab/sidebar/sidebar.css
index 16189a8..4ef8ba6 100644
--- a/skin/classic/treestyletab/sidebar/sidebar.css
+++ b/skin/classic/treestyletab/sidebar/sidebar.css
@@ -18,12 +18,54 @@
/* Background colour for the tree sidebar (light blue when window is
active, grey otherwise) */
.tabbrowser-strip[treestyletab-mode="vertical"] {
- background: transparent !important;
- background-color: #d4dde5 !important;
+ background: #d4dde5 !important;
+}
+/* these styles are required to cover narrow scrollbars. */
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to left,
+ rgba(212,221,229,1) 0%,
+ rgba(212,221,229,1) 10%,
+ rgba(212,221,229,0) 11%,
+ rgba(212,221,229,0) 100%) !important;
+}
+.tabbrowser-tabs[treestyletab-tabbar-position="left"][treestyletab-invert-scrollbar="true"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to right,
+ rgba(212,221,229,1) 0%,
+ rgba(212,221,229,1) 10%,
+ rgba(212,221,229,0) 11%,
+ rgba(212,221,229,0) 100%) !important;
+}
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to left,
+ rgba(212,221,229,1) 0%,
+ rgba(212,221,229,1) 10%,
+ rgba(212,221,229,0) 11%,
+ rgba(212,221,229,0) 100%) !important;
+}
+.tabbrowser-tabs[treestyletab-tabbar-position="left"][treestyletab-invert-scrollbar="true"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to right,
+ rgba(212,221,229,1) 0%,
+ rgba(212,221,229,1) 10%,
+ rgba(212,221,229,0) 11%,
+ rgba(212,221,229,0) 100%) !important;
}
+
#main-window:-moz-window-inactive
.tabbrowser-strip:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"] {
- background-color: #e8e8e8 !important;
+ background: #e8e8e8 !important;
+}
+#main-window:-moz-window-inactive
+ .tabbrowser-tabs:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to right,
+ rgba(232,232,232,1) 0%,
+ rgba(232,232,232,1) 10%,
+ rgba(232,232,232,0) 11%,
+ rgba(232,232,232,0) 100%) !important;
}
/* autohide */
.treestyletab-tabbar-toolbar[treestyletab-tabbar-autohide][treestyletab-mode="vertical"]
diff --git a/skin/classic/treestyletab/square/base.css b/skin/classic/treestyletab/square/base.css
index 6d1adb2..3d1487d 100644
--- a/skin/classic/treestyletab/square/base.css
+++ b/skin/classic/treestyletab/square/base.css
@@ -17,6 +17,23 @@
-moz-appearance: none;
background: darkgray !important;
}
+/* these styles are required to cover narrow scrollbars. */
+.tabbrowser-tabs[treestyletab-style~="border"][treestyletab-mode="vertical"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to left,
+ rgba(169,169,169,1) 0%,
+ rgba(169,169,169,1) 10%,
+ rgba(169,169,169,0) 11%,
+ rgba(169,169,169,0) 100%) !important;
+}
+.tabbrowser-tabs[treestyletab-style~="border"][treestyletab-tabbar-position="left"][treestyletab-invert-scrollbar="true"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to right,
+ rgba(169,169,169,1) 0%,
+ rgba(169,169,169,1) 10%,
+ rgba(169,169,169,0) 11%,
+ rgba(169,169,169,0) 100%) !important;
+}
.tabbrowser-strip[treestyletab-mode="vertical"],
.treestyletab-tabbar-toolbar[treestyletab-mode="vertical"],
diff --git a/skin/classic/treestyletab/square/vertigo.css b/skin/classic/treestyletab/square/vertigo.css
index 68bd86b..2d8ecb9 100644
--- a/skin/classic/treestyletab/square/vertigo.css
+++ b/skin/classic/treestyletab/square/vertigo.css
@@ -1,5 +1,23 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+/* these styles are required to cover narrow scrollbars. */
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to left,
+ -moz-dialog 0%,
+ -moz-dialog 10%,
+ transparent 11%,
+ transparent 100%) !important;
+}
+.tabbrowser-tabs[treestyletab-tabbar-position="left"][treestyletab-invert-scrollbar="true"]
+ .scrollbox-innerbox {
+ background: linear-gradient(to right,
+ -moz-dialog 0%,
+ -moz-dialog 10%,
+ transparent 11%,
+ transparent 100%) !important;
+}
+
.tabbrowser-tabs:not([treestyletab-tabbar-position="top"]),
.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
.tabbrowser-tab:not([pinned]),
diff --git a/skin/classic/treestyletab/ui-base.css b/skin/classic/treestyletab/ui-base.css
index 600a32b..3a31d5f 100644
--- a/skin/classic/treestyletab/ui-base.css
+++ b/skin/classic/treestyletab/ui-base.css
@@ -419,3 +419,13 @@ tabbrowser[treestyletab-tabbar-position="bottom"]
> .scrollbutton-down > * {
display: none;
}
+
+.tabbrowser-tab[treestyletab-highlighted] {
+ outline: transparent solid 0.2em;
+ outline-offset: -0.2em;
+ -moz-outline-radius: 0.25em;
+ outline-radius: 0.25em;
+}
+.tabbrowser-tab[treestyletab-highlighted='notifying'] {
+ outline: Highlight solid 0.2em;
+}
diff --git a/treestyletab.update.rdf b/treestyletab.update.rdf
new file mode 100644
index 0000000..161072f
--- /dev/null
+++ b/treestyletab.update.rdf
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <rdf:Description rdf:about="urn:mozilla:extension:treestyletab at piro.sakura.ne.jp">
+ <em:updates>
+ <rdf:Seq>
+ <rdf:li>
+ <rdf:Description>
+ <em:version>0.16.2016021602</em:version>
+ <em:targetApplication>
+ <rdf:Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+ <em:minVersion>38.0</em:minVersion>
+ <em:maxVersion>46.0a1</em:maxVersion>
+ <em:updateLink>http://piro.sakura.ne.jp/xul/xpi/treestyletab.xpi?version=0.16.2016021602</em:updateLink>
+ <em:updateHash>sha1:7fb200bbf69bc1f103df2630234183f9310511f2</em:updateHash>
+ </rdf:Description>
+ </em:targetApplication>
+ </rdf:Description>
+ </rdf:li>
+ </rdf:Seq>
+ </em:updates>
+ <em:signature>
+ MIGRMAsGCSqGSIb3DQEBDQOBgQB/n6kVPTDADsmj0/gvaPxVLLLuUCYKmEiTOzMG
+ ujOVtb86gl7U7yRRkV71LVPAjxSmOc6oKhAVO5wcIua2DlmNsO1wg9xXGnVa4/ub
+ zFxNi1+bPAJtLn3rebkx0aoTSPSy42WLz7zr5YbpQqEyfb+RbHY7oWI5qierVCFD
+ U5iJ4g==
+ </em:signature>
+ </rdf:Description>
+</rdf:RDF>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/tree-style-tab.git
More information about the Pkg-mozext-commits
mailing list