diff options
author | snej@chromium.org <snej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-05 19:46:04 +0000 |
---|---|---|
committer | snej@chromium.org <snej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-05 19:46:04 +0000 |
commit | 2f7b27eec08656852564942e09af296a76e6dc1f (patch) | |
tree | a6df8de35ccb816c487cffb88959c8f4d71865a5 | |
parent | cdaea9737d39a207240be700f3436e2a2929424e (diff) | |
download | chromium_src-2f7b27eec08656852564942e09af296a76e6dc1f.zip chromium_src-2f7b27eec08656852564942e09af296a76e6dc1f.tar.gz chromium_src-2f7b27eec08656852564942e09af296a76e6dc1f.tar.bz2 |
Native Cocoa bookmark manager, part 1
Most features are implemented, but Recents, Search and Undo are still missing.
MainMenu.xib: Just added "Bookmark Manager" menu item at top of "Bookmarks" menu.
BookmarkManager.xib: New file, containing Bookmark Manager panel, owned by BookmarkManagerController class.
BUG=13149
TEST=New unit tests for each new class.
Review URL: http://codereview.chromium.org/501073
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35546 0039d316-1c4b-4281-b951-d872f2087c98
18 files changed, 3347 insertions, 83 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index cd34c8e..321e85d 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -5984,6 +5984,9 @@ Keep your key file in a safe place. You will need it to create new versions of y Recently Closed </message> <!-- Bookmarks menu --> + <message name="IDS_BOOKMARK_MANAGER_MAC" desc="The Mac menu item for opening the bookmark manager, in the bookmark menu."> + Bookmark Manager + </message> <message name="IDS_BOOKMARK_CURRENT_PAGE_MAC" desc="The Mac menu item for bookmarking the current page in the bookmark menu."> Bookmark This Page... </message> diff --git a/chrome/app/nibs/BookmarkManager.xib b/chrome/app/nibs/BookmarkManager.xib new file mode 100644 index 0000000..63f72bd --- /dev/null +++ b/chrome/app/nibs/BookmarkManager.xib @@ -0,0 +1,1535 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03"> + <data> + <int key="IBDocument.SystemTarget">1050</int> + <string key="IBDocument.SystemVersion">9L31a</string> + <string key="IBDocument.InterfaceBuilderVersion">677</string> + <string key="IBDocument.AppKitVersion">949.54</string> + <string key="IBDocument.HIToolboxVersion">353.00</string> + <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> + <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="1" id="9"/> + <integer value="7"/> + </object> + <object class="NSArray" key="IBDocument.PluginDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + <object class="NSMutableDictionary" key="IBDocument.Metadata"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSCustomObject" id="1001"> + <string key="NSClassName">BookmarkManagerController</string> + </object> + <object class="NSCustomObject" id="1003"> + <string key="NSClassName">FirstResponder</string> + </object> + <object class="NSCustomObject" id="1004"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSWindowTemplate" id="801612057"> + <int key="NSWindowStyleMask">15</int> + <int key="NSWindowBacking">2</int> + <string key="NSWindowRect">{{915, 545}, {689, 592}}</string> + <int key="NSWTFlags">880280576</int> + <string key="NSWindowTitle">^IDS_BOOKMARK_MANAGER_TITLE</string> + <string key="NSWindowClass">NSWindow</string> + <object class="NSToolbar" key="NSViewClass" id="1046399320"> + <object class="NSMutableString" key="NSToolbarIdentifier"> + <characters key="NS.bytes">20D49B48-6DB8-4131-A3FF-BF487B04ABF6</characters> + </object> + <nil key="NSToolbarDelegate"/> + <bool key="NSToolbarPrefersToBeShown">NO</bool> + <bool key="NSToolbarShowsBaselineSeparator">YES</bool> + <bool key="NSToolbarAllowsUserCustomization">YES</bool> + <bool key="NSToolbarAutosavesConfiguration">YES</bool> + <int key="NSToolbarDisplayMode">2</int> + <int key="NSToolbarSizeMode">2</int> + <object class="NSMutableDictionary" key="NSToolbarIBIdentifiedItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>19533CC3-98F5-4A6C-B821-B785FC97D55D</string> + <string>83403F3E-2F03-4DB5-A1F0-CA564DEFC3CD</string> + <string>NSToolbarCustomizeToolbarItem</string> + <string>NSToolbarFlexibleSpaceItem</string> + <string>NSToolbarSeparatorItem</string> + <string>NSToolbarSpaceItem</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSToolbarItem" id="933364437"> + <object class="NSMutableString" key="NSToolbarItemIdentifier"> + <characters key="NS.bytes">19533CC3-98F5-4A6C-B821-B785FC97D55D</characters> + </object> + <string key="NSToolbarItemLabel">New Folder</string> + <string key="NSToolbarItemPaletteLabel">New Folder</string> + <string key="NSToolbarItemToolTip"/> + <nil key="NSToolbarItemView"/> + <nil key="NSToolbarItemImage"/> + <nil key="NSToolbarItemTarget"/> + <nil key="NSToolbarItemAction"/> + <string key="NSToolbarItemMinSize">{0, 0}</string> + <string key="NSToolbarItemMaxSize">{0, 0}</string> + <bool key="NSToolbarItemEnabled">YES</bool> + <bool key="NSToolbarItemAutovalidates">YES</bool> + <int key="NSToolbarItemTag">-1</int> + <bool key="NSToolbarIsUserRemovable">YES</bool> + <int key="NSToolbarItemVisibilityPriority">0</int> + </object> + <object class="NSToolbarItem" id="1000628990"> + <object class="NSMutableString" key="NSToolbarItemIdentifier"> + <characters key="NS.bytes">83403F3E-2F03-4DB5-A1F0-CA564DEFC3CD</characters> + </object> + <string key="NSToolbarItemLabel">Search</string> + <string key="NSToolbarItemPaletteLabel">Search</string> + <string key="NSToolbarItemToolTip"/> + <nil key="NSToolbarItemView"/> + <nil key="NSToolbarItemImage"/> + <nil key="NSToolbarItemTarget"/> + <nil key="NSToolbarItemAction"/> + <string key="NSToolbarItemMinSize">{0, 0}</string> + <string key="NSToolbarItemMaxSize">{0, 0}</string> + <bool key="NSToolbarItemEnabled">YES</bool> + <bool key="NSToolbarItemAutovalidates">YES</bool> + <int key="NSToolbarItemTag">-1</int> + <bool key="NSToolbarIsUserRemovable">YES</bool> + <int key="NSToolbarItemVisibilityPriority">0</int> + </object> + <object class="NSToolbarItem" id="384214618"> + <string key="NSToolbarItemIdentifier">NSToolbarCustomizeToolbarItem</string> + <string key="NSToolbarItemLabel">Customize</string> + <string key="NSToolbarItemPaletteLabel">Customize</string> + <string key="NSToolbarItemToolTip">Customize Toolbar</string> + <nil key="NSToolbarItemView"/> + <object class="NSImage" key="NSToolbarItemImage"> + <int key="NSImageFlags">683671552</int> + <string key="NSSize">{32, 32}</string> + <object class="NSMutableArray" key="NSReps"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray"> + <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="0" id="8"/> + <object class="NSBitmapImageRep"> + <object class="NSData" key="NSTIFFRepresentation"> + <bytes key="NS.bytes">TU0AKgAAEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAICAgbAAAABAAAAAAEBAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAQEBAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAENDQ0dJSUlW11dXbBpaWnDb29vzyAgIGUPDw8xAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAABsbGyUoKChIHh4ePSkpKUonJycsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDCEJCQoWvr6/i9fX1/fX19f7h4eH82dnZ+YODg9sYGBg8 +AAAAAAAAAAAAAAAAAAAAAAAAAAJFRUV6ZGRkvf39/f/+/v7//////0NDQ7QAAAAEAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PDx9ISEiH2tra8/7+/v/j4+P/2NjY/7a2tv+ysrL/ +i4uL7j09PeUKCgoSAAAAAAAAAAAAAAAAUVFRlo2NjfTIyMj6x8fH/56env97e3v/ISEhMAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8lRUVFjtDQ0Pb+/v7/4eHh/dDQ0P+NjY3/ +Tk5O6yoqKrIfHx+gGhoarCIiImwAAAABAAAAADg4OGWenp7/y8vL/d3d3f+8vLz/hYWF/0RERE0AAAAA +AAAAAAAAAAAfHx8sAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj8/P2za2try9/f3/+vr6/7Kysr/ +dnZ2/D4+PvwgICB+EBAQNAICAgcAAAAPERERPQMDAwkQEBASh4eH2MHBwf/o6Oj/39/f/3R0dP88PDxO +AAAAAAAAAAAAAAAAcnJylkNDQ58HBwcIAAAAAAAAAAAAAAAAAAAAAAAAAAAGBgYMfn5+uMvLy/3Hx8f+ +u7u7/5OTk/9CQkL7HRYL7AICAgQAAAAAAAAAAAAAAAAAAAAAAgICBS4uLjOWlpbz6urq/+7u7v+rq6v/ +IyMj0wAAAAAAAAAAAAAAAIGBgZGLi4v/QkJC2Q0NDSYAAAAAAAAAAAAAAAAAAAAAGRkZJF5eXoylpaXz +pqam/4qKiv91dXX/YWFh+iwkHvojEADrJhcGoAgICA0AAAAAAAAAAAAAAAAAAAAAPj4+RJaWlvr19fX/ +6+vr/7W1tfVaWlrlAwMDbAAAAACKioqcoqKi/7+/v/9HR0fnDg4OJwAAAAAAAAAAHR0dK3V1dZ+pqanC ++vr6/9vb2/99fX3+Y2Nj+EhISOgMCAP4JhIA8jgaAPBxNADsNyMMjgcHBwsAAAAAAAAAAAAAAAAMDAwO +m5ub+Orq6v/y8vL/0NDQ7ICAgMtkZGTqcHBwzLOzs//Pz8//0tLS/0xMTNoJCQkhAAAAABoaGjZ/f3+4 +//////j4+P/9/f3/9vb2/0dHR/8oKCjkKSkpoAQCAJUNBQDXVSgA5XY5AOuTSADcOiUOewYGBgoAAAAA +AAAAAB4eHmFlZWX76Ojo/+7u7v/5+fn/5OTk9Li4uO3f39//8PDw/+Hh4f/Ly8v/Ozs7rQICAgMAAAAA +GBgYL3x8fP///////////7S0tP+np6f/QEBA+xUVFXUJCQkkBAQEDgcFA20jEQC7YzIA3n9BAOiiUwDK +NiMObgYGBgoTExNIOzs74bGxsf3Dw8P/1dXV////////////////////////////8/Pz/3R0dOcPDw9H +AAAAAQAAAAAAAAAAVVVVooCAgP/v7+//v7+//2VlZf86OjrLAQEBBgAAAAAAAAAAAAAAABENCVctFwCl +ZTQA1oZFAOCqWgDAMiMTgzExMcKzs7P4wcHB/5+fn//W1tb///////v7+/v//////////729vfOFhYXy +IyMjdAAAAAMAAAABAAAAAAAAAAAAAAAASkpKmlpaWv+RkZH/Nzc38hgYGG4AAAABAAAAAAAAAAAAAAAA +AAAAAAsFAEUwGACbaDcAzXpCAOFnRiLjs7Kx+MTExP+pqan/09PT/3p6evpdXV3rbGxs6l1dXfVXV1fs +UlJSxykpKWMAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBmiMjI/8cHBysBQUFHQAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAsFAEAuGACfSzAT47y4s/24uLj/lJSU/9TU1P+Dg4PkMzMzzwYGBgw6OjpB +QEBASQ8PDxYbGxshAAAAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIimgoKCi4AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAwJBYS9u7n4r6+v/4GBgf/Pz8//iISB6CYmJqoDAwMK +AAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAABUwcHB7qurq/9ubm7/zs7O/5yOgPhlPhbf +MhsCegAAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMnCgoKZsvLy++pqan/Wlpa/9LS0v+Nh4Hq +SCYE4IdDAeSbTgDLNxsAhwAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMOxoaGobV1dXzq6ur/0ZGRv/Z2dn/ +hoaGxQkEAIY6HgCyaDMA2YVAAOuWSQDZPh4AngAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYGFEoKCio0tLS86urq/8xMTH/ +4uLi/4+Pj84AAABIAAAAAg8HAGg6HQDKaDIA4YI+APCVRQDsRSEAuAAAABMAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWFhYrNTU1z9ra2vb8/Pz/ +FxcX/+rq6v+amprZAAAASAAAAAIAAAAAAAAAABAIAIY4GwDiaTEA6X46APeVRAD/SyIA0gAAABIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICBT8/P4asrKz3 +0dHR//39/f/z8/P/paWl5gUFBVkAAAACAAAAAAAAAAAAAAAAAAAAABIJAKUxFgD6bTMA9no4AP9uLwD/ +KxIAxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBwcO +QUFBmpqamv+pqan/+Pj4/7GxsfIXFxeBAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAHAMogDgD/ +WSkA/zwaAPcuEwCyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAEBAQMnJydWUFBQ85aWlvqoqKjfKioqrQEBAQUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAsFAOUXCQD6IA4AwgQCADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAgICBBR0dHmi4uLnACAgIHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAgDAMwFAgA9AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE +AAAACQAAABAAAAAYAAAAIAAAACoAAAAxAAAANgAAADkAAAA4AQEBOQAAAC8AAAAnAAAAHQAAABUAAAAO +AAAACgAAAAsAAAAPAAAAFwAAACAAAAAqAAAAMQAAADQAAAAzAAAALQAAACQAAAAbAAAAEgAAAAsAAAAA +AAAAAAAAAAQAAAAJAAAAEAAAABgAAAAgAAAAKgAAADEAAAA2AAAAOQAAADgAAAA1AAAALwAAACcAAAAd +AAAAFQAAAA4AAAAKAAAACwAAAA8AAAAXAAAAIAAAACoAAAAxAAAANAAAADMAAAAtAAAAJAAAABsAAAAS +AAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0BAAADAAAAAQAgAAABAQADAAAAAQAgAAABAgADAAAABAAA +EKoBAwADAAAAAQABAAABBgADAAAAAQACAAABEQAEAAAAAQAAAAgBEgADAAAAAQABAAABFQADAAAAAQAE +AAABFgADAAAAAQD8AAABFwAEAAAAAQAAEAABHAADAAAAAQABAAABUgADAAAAAQABAAABUwADAAAABAAA +ELIAAAAAAAgACAAIAAgAAQABAAEAAQ</bytes> + </object> + </object> + </object> + <object class="NSArray"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="8"/> + <object class="NSBitmapImageRep"> + <object class="NSData" key="NSTIFFRepresentation"> + <bytes key="NS.bytes">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 +cHlyaWdodCBBcHBsZSwgSW5jLiwgMjAxMAA</bytes> + </object> + </object> + </object> + </object> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MCAwAA</bytes> + </object> + </object> + <nil key="NSToolbarItemTarget"/> + <string key="NSToolbarItemAction">runToolbarCustomizationPalette:</string> + <string key="NSToolbarItemMinSize">{0, 0}</string> + <string key="NSToolbarItemMaxSize">{0, 0}</string> + <bool key="NSToolbarItemEnabled">YES</bool> + <bool key="NSToolbarItemAutovalidates">YES</bool> + <int key="NSToolbarItemTag">-1</int> + <bool key="NSToolbarIsUserRemovable">YES</bool> + <int key="NSToolbarItemVisibilityPriority">0</int> + </object> + <object class="NSToolbarFlexibleSpaceItem" id="52444271"> + <string key="NSToolbarItemIdentifier">NSToolbarFlexibleSpaceItem</string> + <string key="NSToolbarItemLabel"/> + <string key="NSToolbarItemPaletteLabel">Flexible Space</string> + <nil key="NSToolbarItemToolTip"/> + <nil key="NSToolbarItemView"/> + <nil key="NSToolbarItemImage"/> + <nil key="NSToolbarItemTarget"/> + <nil key="NSToolbarItemAction"/> + <string key="NSToolbarItemMinSize">{1, 5}</string> + <string key="NSToolbarItemMaxSize">{20000, 32}</string> + <bool key="NSToolbarItemEnabled">YES</bool> + <bool key="NSToolbarItemAutovalidates">YES</bool> + <int key="NSToolbarItemTag">-1</int> + <bool key="NSToolbarIsUserRemovable">YES</bool> + <int key="NSToolbarItemVisibilityPriority">0</int> + <object class="NSMenuItem" key="NSToolbarItemMenuFormRepresentation"> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <object class="NSCustomResource" key="NSOnImage" id="359971663"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSMenuCheckmark</string> + </object> + <object class="NSCustomResource" key="NSMixedImage" id="412846030"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSMenuMixedState</string> + </object> + </object> + </object> + <object class="NSToolbarSeparatorItem" id="228408183"> + <string key="NSToolbarItemIdentifier">NSToolbarSeparatorItem</string> + <string key="NSToolbarItemLabel"/> + <string key="NSToolbarItemPaletteLabel">Separator</string> + <nil key="NSToolbarItemToolTip"/> + <nil key="NSToolbarItemView"/> + <nil key="NSToolbarItemImage"/> + <nil key="NSToolbarItemTarget"/> + <nil key="NSToolbarItemAction"/> + <string key="NSToolbarItemMinSize">{12, 5}</string> + <string key="NSToolbarItemMaxSize">{12, 1000}</string> + <bool key="NSToolbarItemEnabled">YES</bool> + <bool key="NSToolbarItemAutovalidates">YES</bool> + <int key="NSToolbarItemTag">-1</int> + <bool key="NSToolbarIsUserRemovable">YES</bool> + <int key="NSToolbarItemVisibilityPriority">0</int> + <object class="NSMenuItem" key="NSToolbarItemMenuFormRepresentation"> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="359971663"/> + <reference key="NSMixedImage" ref="412846030"/> + </object> + </object> + <object class="NSToolbarSpaceItem" id="904990067"> + <string key="NSToolbarItemIdentifier">NSToolbarSpaceItem</string> + <string key="NSToolbarItemLabel"/> + <string key="NSToolbarItemPaletteLabel">Space</string> + <nil key="NSToolbarItemToolTip"/> + <nil key="NSToolbarItemView"/> + <nil key="NSToolbarItemImage"/> + <nil key="NSToolbarItemTarget"/> + <nil key="NSToolbarItemAction"/> + <string key="NSToolbarItemMinSize">{32, 5}</string> + <string key="NSToolbarItemMaxSize">{32, 32}</string> + <bool key="NSToolbarItemEnabled">YES</bool> + <bool key="NSToolbarItemAutovalidates">YES</bool> + <int key="NSToolbarItemTag">-1</int> + <bool key="NSToolbarIsUserRemovable">YES</bool> + <int key="NSToolbarItemVisibilityPriority">0</int> + <object class="NSMenuItem" key="NSToolbarItemMenuFormRepresentation"> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="359971663"/> + <reference key="NSMixedImage" ref="412846030"/> + </object> + </object> + </object> + </object> + <object class="NSArray" key="NSToolbarIBAllowedItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="228408183"/> + <reference ref="904990067"/> + <reference ref="52444271"/> + <reference ref="384214618"/> + <reference ref="1000628990"/> + <reference ref="933364437"/> + </object> + <object class="NSMutableArray" key="NSToolbarIBDefaultItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="933364437"/> + <reference ref="52444271"/> + <reference ref="1000628990"/> + </object> + <object class="NSMutableArray" key="NSToolbarIBSelectableItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string> + <string key="NSWindowContentMinSize">{500, 250}</string> + <object class="NSView" key="NSWindowView" id="775220953"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">256</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSSplitView" id="8907081"> + <reference key="NSNextResponder" ref="775220953"/> + <int key="NSvFlags">274</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSScrollView" id="251317961"> + <reference key="NSNextResponder" ref="8907081"/> + <int key="NSvFlags">274</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSClipView" id="764939157"> + <reference key="NSNextResponder" ref="251317961"/> + <int key="NSvFlags">2304</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSTableView" id="580246752"> + <reference key="NSNextResponder" ref="764939157"/> + <int key="NSvFlags">274</int> + <string key="NSFrameSize">{142, 592}</string> + <reference key="NSSuperview" ref="764939157"/> + <bool key="NSEnabled">YES</bool> + <object class="_NSCornerView" key="NSCornerView"> + <nil key="NSNextResponder"/> + <int key="NSvFlags">-2147483392</int> + <string key="NSFrame">{{-26, 0}, {16, 17}}</string> + </object> + <object class="NSMutableArray" key="NSTableColumns"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSTableColumn" id="1069362144"> + <string key="NSIdentifier">name</string> + <double key="NSWidth">1.390000e+02</double> + <double key="NSMinWidth">2.000000e+01</double> + <double key="NSMaxWidth">1.000000e+04</double> + <object class="NSTableHeaderCell" key="NSHeaderCell"> + <int key="NSCellFlags">75628096</int> + <int key="NSCellFlags2">2048</int> + <string key="NSContents">Group</string> + <object class="NSFont" key="NSSupport" id="26"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.100000e+01</double> + <int key="NSfFlags">3100</int> + </object> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes> + </object> + <object class="NSColor" key="NSTextColor" id="317609481"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">headerTextColor</string> + <object class="NSColor" key="NSColor" id="420147826"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MAA</bytes> + </object> + </object> + </object> + <object class="NSTextFieldCell" key="NSDataCell" id="987232547"> + <int key="NSCellFlags">337772096</int> + <int key="NSCellFlags2">133120</int> + <string key="NSContents">Text Cell</string> + <reference key="NSSupport" ref="26"/> + <reference key="NSControlView" ref="580246752"/> + <object class="NSColor" key="NSBackgroundColor" id="774691543"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlBackgroundColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor" id="220007638"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <reference key="NSColor" ref="420147826"/> + </object> + </object> + <int key="NSResizingMask">1</int> + <bool key="NSIsResizeable">YES</bool> + <reference key="NSTableView" ref="580246752"/> + </object> + </object> + <double key="NSIntercellSpacingWidth">3.000000e+00</double> + <double key="NSIntercellSpacingHeight">2.000000e+00</double> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">_sourceListBackgroundColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">1</int> + <bytes key="NSRGB">MC44MzkyMTU3IDAuODY2NjY2NjcgMC44OTgwMzkyMgA</bytes> + </object> + </object> + <object class="NSColor" key="NSGridColor" id="173030864"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">gridColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC41AA</bytes> + </object> + </object> + <double key="NSRowHeight">1.600000e+01</double> + <int key="NSTvFlags">-767557632</int> + <int key="NSColumnAutoresizingStyle">4</int> + <int key="NSDraggingSourceMaskForLocal">15</int> + <int key="NSDraggingSourceMaskForNonLocal">0</int> + <bool key="NSAllowsTypeSelect">YES</bool> + <int key="NSTableViewSelectionHighlightStyle">1</int> + </object> + </object> + <string key="NSFrame">{{1, 1}, {142, 592}}</string> + <reference key="NSSuperview" ref="251317961"/> + <reference key="NSNextKeyView" ref="580246752"/> + <reference key="NSDocView" ref="580246752"/> + <reference key="NSBGColor" ref="774691543"/> + <int key="NScvFlags">4</int> + </object> + <object class="NSScroller" id="865256551"> + <reference key="NSNextResponder" ref="251317961"/> + <int key="NSvFlags">-2147483392</int> + <string key="NSFrame">{{128, 1}, {15, 592}}</string> + <reference key="NSSuperview" ref="251317961"/> + <reference key="NSTarget" ref="251317961"/> + <string key="NSAction">_doScroller:</string> + <double key="NSPercent">9.983137e-01</double> + </object> + <object class="NSScroller" id="752357220"> + <reference key="NSNextResponder" ref="251317961"/> + <int key="NSvFlags">-2147483392</int> + <string key="NSFrame">{{-100, -100}, {223, 15}}</string> + <reference key="NSSuperview" ref="251317961"/> + <int key="NSsFlags">1</int> + <reference key="NSTarget" ref="251317961"/> + <string key="NSAction">_doScroller:</string> + <double key="NSPercent">9.958159e-01</double> + </object> + </object> + <string key="NSFrameSize">{144, 594}</string> + <reference key="NSSuperview" ref="8907081"/> + <reference key="NSNextKeyView" ref="764939157"/> + <int key="NSsFlags">530</int> + <reference key="NSVScroller" ref="865256551"/> + <reference key="NSHScroller" ref="752357220"/> + <reference key="NSContentView" ref="764939157"/> + <bytes key="NSScrollAmts">QSAAAEEgAABBkAAAQZAAAA</bytes> + </object> + <object class="NSScrollView" id="111232465"> + <reference key="NSNextResponder" ref="8907081"/> + <int key="NSvFlags">274</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSClipView" id="416243018"> + <reference key="NSNextResponder" ref="111232465"/> + <int key="NSvFlags">2304</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSOutlineView" id="105944579"> + <reference key="NSNextResponder" ref="416243018"/> + <int key="NSvFlags">256</int> + <string key="NSFrameSize">{543, 576}</string> + <reference key="NSSuperview" ref="416243018"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTableHeaderView" key="NSHeaderView" id="833839723"> + <reference key="NSNextResponder" ref="682782591"/> + <int key="NSvFlags">256</int> + <string key="NSFrameSize">{543, 17}</string> + <reference key="NSSuperview" ref="682782591"/> + <reference key="NSTableView" ref="105944579"/> + </object> + <object class="_NSCornerView" key="NSCornerView" id="401707793"> + <reference key="NSNextResponder" ref="111232465"/> + <int key="NSvFlags">-2147483392</int> + <string key="NSFrame">{{-26, 0}, {16, 17}}</string> + <reference key="NSSuperview" ref="111232465"/> + </object> + <object class="NSMutableArray" key="NSTableColumns"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSTableColumn" id="502561775"> + <string key="NSIdentifier">title</string> + <double key="NSWidth">3.210000e+02</double> + <double key="NSMinWidth">1.600000e+01</double> + <double key="NSMaxWidth">1.000000e+03</double> + <object class="NSTableHeaderCell" key="NSHeaderCell"> + <int key="NSCellFlags">75628096</int> + <int key="NSCellFlags2">2048</int> + <string key="NSContents">^IDS_BOOKMARK_TABLE_TITLE</string> + <reference key="NSSupport" ref="26"/> + <object class="NSColor" key="NSBackgroundColor" id="41737130"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes> + </object> + <reference key="NSTextColor" ref="317609481"/> + </object> + <object class="NSTextFieldCell" key="NSDataCell" id="485613605"> + <int key="NSCellFlags">337772096</int> + <int key="NSCellFlags2">133120</int> + <string key="NSContents">Text Cell</string> + <reference key="NSSupport" ref="26"/> + <reference key="NSControlView" ref="105944579"/> + <reference key="NSBackgroundColor" ref="774691543"/> + <reference key="NSTextColor" ref="220007638"/> + </object> + <int key="NSResizingMask">3</int> + <bool key="NSIsResizeable">YES</bool> + <bool key="NSIsEditable">YES</bool> + <reference key="NSTableView" ref="105944579"/> + </object> + <object class="NSTableColumn" id="930615590"> + <string key="NSIdentifier">url</string> + <double key="NSWidth">2.160000e+02</double> + <double key="NSMinWidth">4.000000e+01</double> + <double key="NSMaxWidth">1.000000e+03</double> + <object class="NSTableHeaderCell" key="NSHeaderCell"> + <int key="NSCellFlags">75628096</int> + <int key="NSCellFlags2">2048</int> + <string key="NSContents">^IDS_BOOKMARK_TABLE_URL</string> + <reference key="NSSupport" ref="26"/> + <reference key="NSBackgroundColor" ref="41737130"/> + <reference key="NSTextColor" ref="317609481"/> + </object> + <object class="NSTextFieldCell" key="NSDataCell" id="294074504"> + <int key="NSCellFlags">337772096</int> + <int key="NSCellFlags2">133120</int> + <string key="NSContents">Text Cell</string> + <reference key="NSSupport" ref="26"/> + <reference key="NSControlView" ref="105944579"/> + <reference key="NSBackgroundColor" ref="774691543"/> + <reference key="NSTextColor" ref="220007638"/> + </object> + <int key="NSResizingMask">3</int> + <bool key="NSIsResizeable">YES</bool> + <bool key="NSIsEditable">YES</bool> + <reference key="NSTableView" ref="105944579"/> + </object> + </object> + <double key="NSIntercellSpacingWidth">3.000000e+00</double> + <double key="NSIntercellSpacingHeight">2.000000e+00</double> + <object class="NSColor" key="NSBackgroundColor" id="497939779"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MQA</bytes> + </object> + <reference key="NSGridColor" ref="173030864"/> + <double key="NSRowHeight">1.600000e+01</double> + <int key="NSTvFlags">-608174080</int> + <string key="NSAutosaveName">bookmarks</string> + <int key="NSColumnAutoresizingStyle">5</int> + <int key="NSDraggingSourceMaskForLocal">15</int> + <int key="NSDraggingSourceMaskForNonLocal">0</int> + <bool key="NSAllowsTypeSelect">YES</bool> + </object> + </object> + <string key="NSFrame">{{1, 17}, {543, 576}}</string> + <reference key="NSSuperview" ref="111232465"/> + <reference key="NSNextKeyView" ref="105944579"/> + <reference key="NSDocView" ref="105944579"/> + <reference key="NSBGColor" ref="774691543"/> + <int key="NScvFlags">4</int> + </object> + <object class="NSScroller" id="585875894"> + <reference key="NSNextResponder" ref="111232465"/> + <int key="NSvFlags">-2147483392</int> + <string key="NSFrame">{{224, 17}, {15, 102}}</string> + <reference key="NSSuperview" ref="111232465"/> + <reference key="NSTarget" ref="111232465"/> + <string key="NSAction">_doScroller:</string> + <double key="NSCurValue">3.700000e+01</double> + <double key="NSPercent">1.390978e-01</double> + </object> + <object class="NSScroller" id="1062246906"> + <reference key="NSNextResponder" ref="111232465"/> + <int key="NSvFlags">-2147483392</int> + <string key="NSFrame">{{-100, -100}, {223, 15}}</string> + <reference key="NSSuperview" ref="111232465"/> + <int key="NSsFlags">1</int> + <reference key="NSTarget" ref="111232465"/> + <string key="NSAction">_doScroller:</string> + <double key="NSPercent">5.714286e-01</double> + </object> + <object class="NSClipView" id="682782591"> + <reference key="NSNextResponder" ref="111232465"/> + <int key="NSvFlags">2304</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="833839723"/> + </object> + <string key="NSFrame">{{1, 0}, {543, 17}}</string> + <reference key="NSSuperview" ref="111232465"/> + <reference key="NSNextKeyView" ref="833839723"/> + <reference key="NSDocView" ref="833839723"/> + <reference key="NSBGColor" ref="774691543"/> + <int key="NScvFlags">4</int> + </object> + <reference ref="401707793"/> + </object> + <string key="NSFrame">{{145, 0}, {545, 594}}</string> + <reference key="NSSuperview" ref="8907081"/> + <reference key="NSNextKeyView" ref="416243018"/> + <int key="NSsFlags">530</int> + <reference key="NSVScroller" ref="585875894"/> + <reference key="NSHScroller" ref="1062246906"/> + <reference key="NSContentView" ref="416243018"/> + <reference key="NSHeaderClipView" ref="682782591"/> + <reference key="NSCornerView" ref="401707793"/> + <bytes key="NSScrollAmts">QSAAAEEgAABBkAAAQZAAAA</bytes> + </object> + </object> + <string key="NSFrame">{{-1, -2}, {690, 594}}</string> + <reference key="NSSuperview" ref="775220953"/> + <bool key="NSIsVertical">YES</bool> + <int key="NSDividerStyle">2</int> + </object> + </object> + <string key="NSFrameSize">{689, 592}</string> + <reference key="NSSuperview"/> + </object> + <string key="NSScreenRect">{{0, 0}, {2560, 1578}}</string> + <string key="NSMinSize">{500, 272}</string> + <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string> + <string key="NSFrameAutosaveName">bookmark_manager</string> + </object> + <object class="NSCustomObject" id="221366305"> + <string key="NSClassName">BookmarkTreeController</string> + </object> + <object class="NSCustomObject" id="506845861"> + <string key="NSClassName">BookmarkGroupsController</string> + </object> + <object class="NSCustomView" id="372717701"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">268</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSSearchField" id="159839204"> + <reference key="NSNextResponder" ref="372717701"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{38, 102}, {165, 22}}</string> + <reference key="NSSuperview" ref="372717701"/> + <bool key="NSEnabled">YES</bool> + <object class="NSSearchFieldCell" key="NSCell" id="1043792166"> + <int key="NSCellFlags">343014976</int> + <int key="NSCellFlags2">268436480</int> + <string key="NSContents">^IDS_BOOKMARK_MANAGER_SEARCH_TITLE</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.300000e+01</double> + <int key="NSfFlags">1044</int> + </object> + <string key="NSPlaceholderString">Search</string> + <reference key="NSControlView" ref="159839204"/> + <bool key="NSDrawsBackground">YES</bool> + <int key="NSTextBezelStyle">1</int> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">textBackgroundColor</string> + <reference key="NSColor" ref="497939779"/> + </object> + <reference key="NSTextColor" ref="220007638"/> + <object class="NSButtonCell" key="NSSearchButtonCell"> + <int key="NSCellFlags">130560</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents">search</string> + <string key="NSAction">_searchFieldSearch:</string> + <reference key="NSTarget" ref="1043792166"/> + <reference key="NSControlView" ref="159839204"/> + <int key="NSButtonFlags">138690815</int> + <int key="NSButtonFlags2">0</int> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">400</int> + <int key="NSPeriodicInterval">75</int> + </object> + <object class="NSButtonCell" key="NSCancelButtonCell"> + <int key="NSCellFlags">130560</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents">clear</string> + <object class="NSMutableArray" key="NSAccessibilityOverriddenAttributes"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableDictionary"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>AXDescription</string> + <string>NSAccessibilityEncodedAttributesValueType</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>cancel</string> + <reference ref="9"/> + </object> + </object> + </object> + <string key="NSAction">_searchFieldCancel:</string> + <reference key="NSTarget" ref="1043792166"/> + <reference key="NSControlView" ref="159839204"/> + <int key="NSButtonFlags">138690815</int> + <int key="NSButtonFlags2">0</int> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">400</int> + <int key="NSPeriodicInterval">75</int> + </object> + <int key="NSMaximumRecents">10</int> + <bytes key="NSSearchFieldFlags">CAAAAA</bytes> + </object> + </object> + </object> + <string key="NSFrameSize">{277, 169}</string> + <reference key="NSSuperview"/> + <string key="NSClassName">NSView</string> + </object> + <object class="NSCustomObject" id="16155636"> + <string key="NSClassName">ChromeUILocalizer</string> + </object> + </object> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <object class="NSMutableArray" key="connectionRecords"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">dataSource</string> + <reference key="source" ref="105944579"/> + <reference key="destination" ref="221366305"/> + </object> + <int key="connectionID">34</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">delegate</string> + <reference key="source" ref="580246752"/> + <reference key="destination" ref="506845861"/> + </object> + <int key="connectionID">36</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">delegate</string> + <reference key="source" ref="105944579"/> + <reference key="destination" ref="221366305"/> + </object> + <int key="connectionID">39</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">window</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="801612057"/> + </object> + <int key="connectionID">40</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">delegate</string> + <reference key="source" ref="801612057"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">41</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">delegate</string> + <reference key="source" ref="1046399320"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">47</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">searchFieldChanged:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="159839204"/> + </object> + <int key="connectionID">48</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">groupsTable_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="580246752"/> + </object> + <int key="connectionID">49</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">treeController_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="221366305"/> + </object> + <int key="connectionID">51</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">toolbarSearchView_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="159839204"/> + </object> + <int key="connectionID">52</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">outline_</string> + <reference key="source" ref="221366305"/> + <reference key="destination" ref="105944579"/> + </object> + <int key="connectionID">53</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">groupsTable_</string> + <reference key="source" ref="506845861"/> + <reference key="destination" ref="580246752"/> + </object> + <int key="connectionID">54</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">dataSource</string> + <reference key="source" ref="580246752"/> + <reference key="destination" ref="506845861"/> + </object> + <int key="connectionID">56</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">tableClicked:</string> + <reference key="source" ref="506845861"/> + <reference key="destination" ref="580246752"/> + </object> + <int key="connectionID">57</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">groupsController_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="506845861"/> + </object> + <int key="connectionID">58</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">manager_</string> + <reference key="source" ref="221366305"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">59</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">manager_</string> + <reference key="source" ref="506845861"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">60</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">owner_</string> + <reference key="source" ref="16155636"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">62</int> + </object> + </object> + <object class="IBMutableOrderedSet" key="objectRecords"> + <object class="NSArray" key="orderedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBObjectRecord"> + <int key="objectID">0</int> + <object class="NSArray" key="object" id="904321106"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="children" ref="1000"/> + <nil key="parent"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-2</int> + <reference key="object" ref="1001"/> + <reference key="parent" ref="904321106"/> + <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-1</int> + <reference key="object" ref="1003"/> + <reference key="parent" ref="904321106"/> + <string key="objectName">First Responder</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-3</int> + <reference key="object" ref="1004"/> + <reference key="parent" ref="904321106"/> + <string key="objectName">Application</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">1</int> + <reference key="object" ref="801612057"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1046399320"/> + <reference ref="775220953"/> + </object> + <reference key="parent" ref="904321106"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">3</int> + <reference key="object" ref="221366305"/> + <reference key="parent" ref="904321106"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">4</int> + <reference key="object" ref="506845861"/> + <reference key="parent" ref="904321106"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">5</int> + <reference key="object" ref="372717701"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="159839204"/> + </object> + <reference key="parent" ref="904321106"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">6</int> + <reference key="object" ref="159839204"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1043792166"/> + </object> + <reference key="parent" ref="372717701"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">7</int> + <reference key="object" ref="1043792166"/> + <reference key="parent" ref="159839204"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">8</int> + <reference key="object" ref="1046399320"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="933364437"/> + <reference ref="1000628990"/> + <reference ref="384214618"/> + <reference ref="52444271"/> + <reference ref="904990067"/> + <reference ref="228408183"/> + </object> + <reference key="parent" ref="801612057"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">9</int> + <reference key="object" ref="775220953"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="8907081"/> + </object> + <reference key="parent" ref="801612057"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">10</int> + <reference key="object" ref="8907081"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="111232465"/> + <reference ref="251317961"/> + </object> + <reference key="parent" ref="775220953"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">11</int> + <reference key="object" ref="111232465"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="585875894"/> + <reference ref="1062246906"/> + <reference ref="105944579"/> + <reference ref="833839723"/> + </object> + <reference key="parent" ref="8907081"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">12</int> + <reference key="object" ref="251317961"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="865256551"/> + <reference ref="752357220"/> + <reference ref="580246752"/> + </object> + <reference key="parent" ref="8907081"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">14</int> + <reference key="object" ref="865256551"/> + <reference key="parent" ref="251317961"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">15</int> + <reference key="object" ref="752357220"/> + <reference key="parent" ref="251317961"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">16</int> + <reference key="object" ref="580246752"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1069362144"/> + </object> + <reference key="parent" ref="251317961"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">17</int> + <reference key="object" ref="1069362144"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="987232547"/> + </object> + <reference key="parent" ref="580246752"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">18</int> + <reference key="object" ref="987232547"/> + <reference key="parent" ref="1069362144"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">19</int> + <reference key="object" ref="585875894"/> + <reference key="parent" ref="111232465"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">20</int> + <reference key="object" ref="1062246906"/> + <reference key="parent" ref="111232465"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">21</int> + <reference key="object" ref="105944579"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="502561775"/> + <reference ref="930615590"/> + </object> + <reference key="parent" ref="111232465"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">22</int> + <reference key="object" ref="833839723"/> + <reference key="parent" ref="111232465"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">23</int> + <reference key="object" ref="502561775"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="485613605"/> + </object> + <reference key="parent" ref="105944579"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">24</int> + <reference key="object" ref="930615590"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="294074504"/> + </object> + <reference key="parent" ref="105944579"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">25</int> + <reference key="object" ref="294074504"/> + <reference key="parent" ref="930615590"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">26</int> + <reference key="object" ref="485613605"/> + <reference key="parent" ref="502561775"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">27</int> + <reference key="object" ref="933364437"/> + <reference key="parent" ref="1046399320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">28</int> + <reference key="object" ref="1000628990"/> + <reference key="parent" ref="1046399320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">29</int> + <reference key="object" ref="384214618"/> + <reference key="parent" ref="1046399320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">30</int> + <reference key="object" ref="52444271"/> + <reference key="parent" ref="1046399320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">31</int> + <reference key="object" ref="904990067"/> + <reference key="parent" ref="1046399320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">32</int> + <reference key="object" ref="228408183"/> + <reference key="parent" ref="1046399320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">61</int> + <reference key="object" ref="16155636"/> + <reference key="parent" ref="904321106"/> + </object> + </object> + </object> + <object class="NSMutableDictionary" key="flattenedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>-1.IBPluginDependency</string> + <string>-2.IBPluginDependency</string> + <string>-3.IBPluginDependency</string> + <string>1.IBEditorWindowLastContentRect</string> + <string>1.IBPluginDependency</string> + <string>1.IBWindowTemplateEditedContentRect</string> + <string>1.NSWindowTemplate.visibleAtLaunch</string> + <string>1.editorWindowContentRectSynchronizationRect</string> + <string>1.windowTemplate.hasMinSize</string> + <string>1.windowTemplate.maxSize</string> + <string>1.windowTemplate.minSize</string> + <string>10.IBPluginDependency</string> + <string>11.IBPluginDependency</string> + <string>12.IBPluginDependency</string> + <string>14.IBPluginDependency</string> + <string>15.IBPluginDependency</string> + <string>16.CustomClassName</string> + <string>16.IBPluginDependency</string> + <string>17.IBPluginDependency</string> + <string>18.CustomClassName</string> + <string>18.IBPluginDependency</string> + <string>19.IBPluginDependency</string> + <string>20.IBPluginDependency</string> + <string>21.CustomClassName</string> + <string>21.IBPluginDependency</string> + <string>22.IBPluginDependency</string> + <string>23.IBPluginDependency</string> + <string>24.IBPluginDependency</string> + <string>25.IBPluginDependency</string> + <string>26.CustomClassName</string> + <string>26.IBPluginDependency</string> + <string>27.IBPluginDependency</string> + <string>28.IBPluginDependency</string> + <string>28.designableToolbarItemIdentifier</string> + <string>29.IBPluginDependency</string> + <string>5.IBEditorWindowLastContentRect</string> + <string>5.IBPluginDependency</string> + <string>6.IBPluginDependency</string> + <string>61.IBPluginDependency</string> + <string>7.IBPluginDependency</string> + <string>8.IBEditorWindowLastContentRect</string> + <string>8.IBPluginDependency</string> + <string>8.designableToolbarIdentifier</string> + <string>9.IBPluginDependency</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{112, 245}, {689, 592}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{112, 245}, {689, 592}}</string> + <boolean value="NO"/> + <string>{{33, 99}, {480, 360}}</string> + <boolean value="YES"/> + <string>{3.40282e+38, 3.40282e+38}</string> + <string>{500, 250}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>BookmarksTableView</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>ImageAndTextCell</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>BookmarksOutlineView</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>ImageAndTextCell</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>search</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{614, 49}, {277, 169}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{92, 786}, {617, 0}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>bookmarksToolbar</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + </object> + <object class="NSMutableDictionary" key="unlocalizedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="activeLocalization"/> + <object class="NSMutableDictionary" key="localizations"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="sourceID"/> + <int key="maxID">62</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <object class="NSMutableArray" key="referencedPartialClassDescriptions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">BookmarkGroupsController</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">tableClicked:</string> + <string key="NS.object.0">id</string> + </object> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>groupsTable_</string> + <string>manager_</string> + <string>selectedGroup_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSTableView</string> + <string>BookmarkManagerController</string> + <string>id</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="867038439"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/bookmark_groups_controller.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarkManagerController</string> + <string key="superclassName">NSWindowController</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">searchFieldChanged:</string> + <string key="NS.object.0">id</string> + </object> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>groupsController_</string> + <string>groupsTable_</string> + <string>toolbarSearchView_</string> + <string>treeController_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>BookmarkGroupsController</string> + <string>NSTableView</string> + <string>NSSearchField</string> + <string>BookmarkTreeController</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/bookmark_manager_controller.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarkTreeController</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="actions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>copy:</string> + <string>cut:</string> + <string>delete:</string> + <string>paste:</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + </object> + </object> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>group_</string> + <string>manager_</string> + <string>outline_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>BookmarkManagerController</string> + <string>NSOutlineView</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="706533809"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/bookmark_tree_controller.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarkTreeController</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBUserSource</string> + <string key="minorKey"/> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarksOutlineView</string> + <string key="superclassName">NSOutlineView</string> + <reference key="sourceIdentifier" ref="706533809"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarksOutlineView</string> + <string key="superclassName">NSOutlineView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBUserSource</string> + <string key="minorKey"/> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarksTableView</string> + <string key="superclassName">NSTableView</string> + <reference key="sourceIdentifier" ref="867038439"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarksTableView</string> + <string key="superclassName">NSTableView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBUserSource</string> + <string key="minorKey"/> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">ChromeUILocalizer</string> + <string key="superclassName">GTMUILocalizer</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/ui_localizer.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">GTMUILocalizer</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>otherObjectToLocalize_</string> + <string>owner_</string> + <string>yetAnotherObjectToLocalize_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>id</string> + <string>id</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">../third_party/GTM/AppKit/GTMUILocalizer.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">ImageAndTextCell</string> + <string key="superclassName">NSTextFieldCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">../third_party/apple/ImageAndTextCell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">ImageAndTextCell</string> + <string key="superclassName">NSTextFieldCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBUserSource</string> + <string key="minorKey"/> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/status_bubble_mac.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/tab_strip_model_observer_bridge.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSWindow</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/nswindow_local_state.h</string> + </object> + </object> + </object> + </object> + <int key="IBDocument.localizationMode">0</int> + <string key="IBDocument.LastKnownRelativeProjectPath">../../chrome.xcodeproj</string> + <int key="IBDocument.defaultPropertyAccessControl">3</int> + </data> +</archive> diff --git a/chrome/app/nibs/MainMenu.xib b/chrome/app/nibs/MainMenu.xib index 7a0e62f..4fabcb9 100644 --- a/chrome/app/nibs/MainMenu.xib +++ b/chrome/app/nibs/MainMenu.xib @@ -8,7 +8,7 @@ <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="296"/> + <integer value="504"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -954,6 +954,27 @@ <string key="NSTitle">^IDS_BOOKMARKS_MENU_MAC</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="926580029"> + <reference key="NSMenu" ref="891828782"/> + <string key="NSTitle">^IDS_BOOKMARK_MANAGER</string> + <string key="NSKeyEquiv">b</string> + <int key="NSKeyEquivModMask">1572864</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="353210768"/> + <reference key="NSMixedImage" ref="549394948"/> + <int key="NSTag">40011</int> + </object> + <object class="NSMenuItem" id="226650579"> + <reference key="NSMenu" ref="891828782"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="353210768"/> + <reference key="NSMixedImage" ref="549394948"/> + <int key="NSTag">35000</int> + </object> <object class="NSMenuItem" id="399860348"> <reference key="NSMenu" ref="891828782"/> <string key="NSTitle">^IDS_BOOKMARK_CURRENT_PAGE_MAC</string> @@ -1707,13 +1728,21 @@ </object> <int key="connectionID">671</int> </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">commandDispatch:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="926580029"/> + </object> + <int key="connectionID">673</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBObjectRecord"> <int key="objectID">0</int> - <object class="NSArray" key="object" id="953662269"> + <object class="NSArray" key="object" id="542358269"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <reference key="children" ref="1048"/> @@ -1722,19 +1751,19 @@ <object class="IBObjectRecord"> <int key="objectID">-2</int> <reference key="object" ref="1021"/> - <reference key="parent" ref="953662269"/> + <reference key="parent" ref="542358269"/> <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string> </object> <object class="IBObjectRecord"> <int key="objectID">-1</int> <reference key="object" ref="1014"/> - <reference key="parent" ref="953662269"/> + <reference key="parent" ref="542358269"/> <string key="objectName">First Responder</string> </object> <object class="IBObjectRecord"> <int key="objectID">-3</int> <reference key="object" ref="1050"/> - <reference key="parent" ref="953662269"/> + <reference key="parent" ref="542358269"/> <string key="objectName">Application</string> </object> <object class="IBObjectRecord"> @@ -1751,7 +1780,7 @@ <reference ref="586577488"/> <reference ref="445514911"/> </object> - <reference key="parent" ref="953662269"/> + <reference key="parent" ref="542358269"/> <string key="objectName">Main Menu</string> </object> <object class="IBObjectRecord"> @@ -2190,7 +2219,7 @@ <object class="IBObjectRecord"> <int key="objectID">373</int> <reference key="object" ref="163992474"/> - <reference key="parent" ref="953662269"/> + <reference key="parent" ref="542358269"/> </object> <object class="IBObjectRecord"> <int key="objectID">449</int> @@ -2281,7 +2310,7 @@ <object class="IBObjectRecord"> <int key="objectID">483</int> <reference key="object" ref="168151378"/> - <reference key="parent" ref="953662269"/> + <reference key="parent" ref="542358269"/> </object> <object class="IBObjectRecord"> <int key="objectID">492</int> @@ -2342,6 +2371,8 @@ <reference ref="505033846"/> <reference ref="399860348"/> <reference ref="774017921"/> + <reference ref="926580029"/> + <reference ref="226650579"/> </object> <reference key="parent" ref="299901009"/> </object> @@ -2494,7 +2525,7 @@ <object class="IBObjectRecord"> <int key="objectID">641</int> <reference key="object" ref="979722531"/> - <reference key="parent" ref="953662269"/> + <reference key="parent" ref="542358269"/> </object> <object class="IBObjectRecord"> <int key="objectID">648</int> @@ -2551,6 +2582,16 @@ <reference key="object" ref="737490158"/> <reference key="parent" ref="963351320"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">672</int> + <reference key="object" ref="926580029"/> + <reference key="parent" ref="891828782"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">674</int> + <reference key="object" ref="226650579"/> + <reference key="parent" ref="891828782"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -2745,6 +2786,8 @@ <string>665.IBPluginDependency</string> <string>669.IBPluginDependency</string> <string>670.IBPluginDependency</string> + <string>672.IBPluginDependency</string> + <string>674.IBPluginDependency</string> <string>72.IBPluginDependency</string> <string>72.ImportedFromIB2</string> <string>73.IBPluginDependency</string> @@ -2865,17 +2908,17 @@ <reference ref="9"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <string>{{1382, 97}, {323, 183}}</string> + <string>{{1254, 68}, {326, 183}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> <string>{{525, 802}, {197, 73}}</string> - <string>{{-317, 706}, {1578, 20}}</string> + <string>{{64, 251}, {1578, 20}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> <string>{74, 862}</string> <string>{{11, 977}, {478, 20}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{270, 493}, {383, 213}}</string> + <string>{{651, 38}, {383, 213}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{475, 832}, {234, 43}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2905,7 +2948,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{965, 284}, {361, 53}}</string> + <string>{{1026, 168}, {361, 83}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> @@ -2916,7 +2959,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{761, 184}, {301, 153}}</string> + <string>{{825, 98}, {304, 153}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2961,6 +3004,8 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> @@ -3006,7 +3051,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">671</int> + <int key="maxID">674</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -3048,6 +3093,102 @@ </object> </object> <object class="IBPartialClassDescription"> + <string key="className">BookmarkGroupsController</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">tableClicked:</string> + <string key="NS.object.0">id</string> + </object> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>groupsTable_</string> + <string>manager_</string> + <string>selectedGroup_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSTableView</string> + <string>BookmarkManagerController</string> + <string>id</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/bookmark_groups_controller.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarkManagerController</string> + <string key="superclassName">NSWindowController</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">searchFieldChanged:</string> + <string key="NS.object.0">id</string> + </object> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>groupsController_</string> + <string>groupsTable_</string> + <string>toolbarSearchView_</string> + <string>treeController_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>BookmarkGroupsController</string> + <string>NSTableView</string> + <string>NSSearchField</string> + <string>BookmarkTreeController</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/bookmark_manager_controller.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">BookmarkTreeController</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="actions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>copy:</string> + <string>cut:</string> + <string>delete:</string> + <string>paste:</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + </object> + </object> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>group_</string> + <string>manager_</string> + <string>outline_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>BookmarkManagerController</string> + <string>NSOutlineView</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/bookmark_tree_controller.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> <string key="className">BrowserCrApplication</string> <string key="superclassName">CrApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> @@ -3112,31 +3253,6 @@ </object> </object> <object class="IBPartialClassDescription"> - <string key="className">ExtensionShelfController</string> - <string key="superclassName">NSViewController</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSMutableArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>hide:</string> - <string>show:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>id</string> - <string>id</string> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <string key="NS.key.0">resizeDelegate_</string> - <string key="NS.object.0">id</string> - </object> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBProjectSource</string> - <string key="minorKey">browser/cocoa/extension_shelf_controller.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> <string key="className">FirstResponder</string> <string key="superclassName">NSObject</string> <object class="NSMutableDictionary" key="actions"> @@ -3216,46 +3332,6 @@ <string key="minorKey">browser/cocoa/nswindow_local_state.h</string> </object> </object> - <object class="IBPartialClassDescription"> - <string key="className">TabController</string> - <string key="superclassName">NSViewController</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSMutableArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>closeTab:</string> - <string>commandDispatch:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>id</string> - <string>id</string> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSMutableArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>closeButton_</string> - <string>contextMenu_</string> - <string>iconView_</string> - <string>target_</string> - <string>titleView_</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>NSButton</string> - <string>NSMenu</string> - <string>NSView</string> - <string>id</string> - <string>NSTextField</string> - </object> - </object> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBProjectSource</string> - <string key="minorKey">browser/cocoa/tab_controller.h</string> - </object> - </object> </object> </object> <int key="IBDocument.localizationMode">0</int> diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index fac7afd..671f73f 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -2541,9 +2541,7 @@ void Browser::InitCommandState() { command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, true); command_updater_.UpdateCommandEnabled(IDC_SELECT_PROFILE, true); command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true); -#if !defined(OS_MACOSX) // http://crbug.com/13149 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER, true); -#endif command_updater_.UpdateCommandEnabled(IDC_SHOW_EXTENSION_SHELF, true); command_updater_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true); command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE, true); diff --git a/chrome/browser/cocoa/bookmark_groups_controller.h b/chrome/browser/cocoa/bookmark_groups_controller.h new file mode 100644 index 0000000..ccd9e32 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_groups_controller.h @@ -0,0 +1,52 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> + +@class BookmarkManagerController; +class BookmarkModel; +class BookmarkNode; + + +// Controller for the bookmark group list (the left pane). +@interface BookmarkGroupsController : NSObject { + @private + IBOutlet NSTableView* groupsTable_; + IBOutlet BookmarkManagerController* manager_; + + NSMutableArray* groups_; // array of node items ('id's) + id selectedGroup_; // selected item from groups +} + +// The ordered list of groups shown in the table view. Observable. +// Each item is an 'id', as vended by BookmarkManagerController's -itemFromNode: +@property (copy) NSArray* groups; +// The item in -groups currently selected in the table view. Observable. +@property (retain) id selectedGroup; + +// Called by the table view when a row is clicked. +- (IBAction)tableClicked:(id)sender; + +// Reloads the groups property and table contents from the data model. +- (void)reload; + +// Called by BookmarkManagerController to notify that the data model's changed. +- (void)nodeChanged:(const BookmarkNode*)node + childrenChanged:(BOOL)childrenChanged; + +@end + + +// Exposed only for unit tests. +@interface BookmarkGroupsController (UnitTesting) + +@property (readonly) NSTableView* groupsTable; + +@end + + + +// Table view for bookmark group list; handles Cut/Copy/Paste and Delete key. +@interface BookmarksTableView : NSTableView +@end diff --git a/chrome/browser/cocoa/bookmark_groups_controller.mm b/chrome/browser/cocoa/bookmark_groups_controller.mm new file mode 100644 index 0000000..e6b14f3 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_groups_controller.mm @@ -0,0 +1,165 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/bookmark_groups_controller.h" + +#include "base/sys_string_conversions.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#import "chrome/browser/cocoa/bookmark_manager_controller.h" +#import "chrome/browser/cocoa/bookmark_tree_controller.h" +#import "third_party/apple/ImageAndTextCell.h" + + +@interface BookmarkGroupsController () +- (void)syncSelection; +- (void)reload; +@end + + +@implementation BookmarkGroupsController + +@synthesize groups = groups_, selectedGroup = selectedGroup_; + +-(void)dealloc { + [groups_ release]; + [selectedGroup_ release]; + [super dealloc]; +} + +// Completely reloads the contents of the table view. +- (void)reload { + NSMutableArray* groups = [NSMutableArray array]; + BookmarkModel* bookmarkModel = [manager_ bookmarkModel]; + const BookmarkNode* node = bookmarkModel->GetBookmarkBarNode(); + [groups addObject:[manager_ itemFromNode:node]]; + node = bookmarkModel->other_node(); + for (int i = 0; i < node->GetChildCount(); i++) { + const BookmarkNode* child = node->GetChild(i); + if (child->is_folder()) { + [groups addObject:[manager_ itemFromNode:child]]; + } + } + //TODO(snej): Append Recents and Search groups + + if (![groups isEqual:[self groups]]) { + [self setGroups:groups]; + [groupsTable_ reloadData]; + [self syncSelection]; + } +} + +// Responds to changes in the bookmark data model. +- (void)nodeChanged:(const BookmarkNode*)node + childrenChanged:(BOOL)childrenChanged { + if (node == [manager_ bookmarkModel]->other_node()) { + [self reload]; + } +} + +// Returns the selected BookmarkNode. +- (const BookmarkNode*)selectedNode { + NSInteger row = [groupsTable_ selectedRow]; + if (row < 0) + return NULL; + id item = [groups_ objectAtIndex:row]; + return [manager_ nodeFromItem:item]; +} + +- (id)selectedGroup { + return selectedGroup_; +} + +- (void)setSelectedGroup:(id)group { + [selectedGroup_ autorelease]; + selectedGroup_ = [group retain]; + + NSInteger row = group ? [groups_ indexOfObject:group] : NSNotFound; + if (row != NSNotFound) + [groupsTable_ selectRow:row byExtendingSelection:NO]; + else + [groupsTable_ deselectAll:self]; +} + +- (NSTableView*)groupsTable { + return groupsTable_; +} + + +#pragma mark - +#pragma mark COMMANDS: + + +// Updates the |selectedGroup| property based on the table view's selection. +- (void)syncSelection { + id selGroup = nil; + NSInteger row = [groupsTable_ selectedRow]; + if (row >= 0) { + selGroup = [groups_ objectAtIndex:row]; + if (![selGroup isKindOfClass:[NSValue class]]) + selGroup = nil; + } + if (selGroup != [self selectedGroup]) + [self setSelectedGroup:selGroup]; +} + +// Called when a row is clicked; updates the |selectedGroup| property. +- (IBAction)tableClicked:(id)sender { + [self syncSelection]; +} + +// The Delete command; also invoked by the delete key. +- (IBAction)delete:(id)sender { + const BookmarkNode* sel = [self selectedNode]; + if (!sel) { + NSBeep(); + return; + } + const BookmarkNode* parent = sel->GetParent(); + [manager_ bookmarkModel]->Remove(parent, parent->IndexOfChild(sel)); +} + + +#pragma mark - +#pragma mark LIST VIEW: + + +// Returns the number of rows in the table (NSTableView data source). +- (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView { + return [groups_ count]; +} + +// Returns the contents of a table cell (NSTableView data source). +- (id) tableView:(NSTableView*)tableView + objectValueForTableColumn:(NSTableColumn*)tableColumn + row:(NSInteger)row { + id item = [groups_ objectAtIndex:row]; + return base::SysWideToNSString([manager_ nodeFromItem:item]->GetTitle()); +} + +// Sets a table cell's icon before it's drawn (NSTableView delegate). +- (void)tableView:(NSTableView*)tableView + willDisplayCell:(id)cell + forTableColumn:(NSTableColumn*)tableColumn + row:(NSInteger)row { + id item = [groups_ objectAtIndex:row]; + [(ImageAndTextCell*)cell setImage:[manager_ iconForItem:item]]; +} + +@end + + +@implementation BookmarksTableView + +- (IBAction)delete:(id)sender { + [(BookmarkGroupsController*)[self delegate] delete:sender]; +} + +- (void)keyDown:(NSEvent*)event { + if ([event keyCode] == 51) // Delete key + [self delete:self]; + else + [super keyDown:event]; +} + +@end diff --git a/chrome/browser/cocoa/bookmark_groups_controller_unittest.mm b/chrome/browser/cocoa/bookmark_groups_controller_unittest.mm new file mode 100644 index 0000000..60427ee --- /dev/null +++ b/chrome/browser/cocoa/bookmark_groups_controller_unittest.mm @@ -0,0 +1,79 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/bookmark_groups_controller.h" +#import "chrome/browser/cocoa/bookmark_manager_controller.h" +#include "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { + +class BookmarkGroupsControllerTest : public CocoaTest { + public: + void SetUp() { + CocoaTest::SetUp(); + manager_ = [BookmarkManagerController showBookmarkManager: + browser_test_helper_.profile()]; + ASSERT_TRUE(manager_); + controller_ = [manager_ groupsController]; + ASSERT_TRUE(controller_); + } + + void TearDown() { + [manager_ close]; + CocoaTest::TearDown(); + } + + BrowserTestHelper browser_test_helper_; + BookmarkManagerController* manager_; + BookmarkGroupsController* controller_; +}; + +TEST_F(BookmarkGroupsControllerTest, Model) { + NSArray *groups = [controller_ groups]; + ASSERT_TRUE(groups); + // TODO(snej): Update this next assertion after I add Search and Recents. + ASSERT_EQ(1U, [groups count]); + id barItem = [groups objectAtIndex:0]; + BookmarkModel* model = [manager_ bookmarkModel]; + const BookmarkNode* barNode = model->GetBookmarkBarNode(); + EXPECT_EQ(barNode, [manager_ nodeFromItem:barItem]); + + // Now add an item to Others: + const BookmarkNode* otherNode = model->other_node(); + const BookmarkNode* wowbagger = model->AddGroup(otherNode, 0, L"Wowbagger"); + + groups = [controller_ groups]; + ASSERT_TRUE(groups); + ASSERT_EQ(2U, [groups count]); + id wowbaggerItem = [groups objectAtIndex:1]; + EXPECT_EQ(wowbagger, [manager_ nodeFromItem:wowbaggerItem]); + + // Now remove it: + model->Remove(otherNode, 0); + + groups = [controller_ groups]; + ASSERT_TRUE(groups); + ASSERT_EQ(1U, [groups count]); + ASSERT_EQ(barItem, [groups objectAtIndex:0]); +} + +TEST_F(BookmarkGroupsControllerTest, Selection) { + // Select nothing: + ASSERT_TRUE([controller_ groupsTable]); + [controller_ setSelectedGroup:nil]; + EXPECT_EQ(nil, [controller_ selectedGroup]); + EXPECT_EQ(-1, [[controller_ groupsTable] selectedRow]); + + // Select bookmarks bar: + id sel = [[controller_ groups] objectAtIndex:0]; + [controller_ setSelectedGroup:sel]; + EXPECT_EQ(sel, [controller_ selectedGroup]); + EXPECT_EQ(0, [[controller_ groupsTable] selectedRow]); +} + +} // namespace diff --git a/chrome/browser/cocoa/bookmark_manager_controller.h b/chrome/browser/cocoa/bookmark_manager_controller.h new file mode 100644 index 0000000..c5b8b73 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_manager_controller.h @@ -0,0 +1,63 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> +#include "base/scoped_nsobject.h" + +@class BookmarkGroupsController; +@class BookmarkTreeController; +class BookmarkManagerBridge; +class BookmarkModel; +class BookmarkNode; +class Profile; + +// Controller for the bookmark manager window. There is at most one instance. +@interface BookmarkManagerController : NSWindowController { + @private + IBOutlet NSTableView* groupsTable_; + IBOutlet NSSearchField* toolbarSearchView_; + IBOutlet BookmarkGroupsController* groupsController_; + IBOutlet BookmarkTreeController* treeController_; + + Profile* profile_; // weak + BookmarkManagerBridge* bridge_; + scoped_nsobject<NSMapTable> nodeMap_; + scoped_nsobject<NSImage> folderIcon_; + scoped_nsobject<NSImage> defaultFavIcon_; +} + +// Opens the bookmark manager window, or brings it to the front if it's open. ++ (BookmarkManagerController*)showBookmarkManager:(Profile*)profile; + +// The BookmarkModel of the manager's Profile. +@property (readonly) BookmarkModel* bookmarkModel; + +// Maps C++ BookmarkNode objects to opaque Objective-C objects. +// This allows nodes to be stored in NSArrays or NSOutlineViews. +- (id)itemFromNode:(const BookmarkNode*)node; + +// Converse of -nodeFromItem: -- maps an opaque item back to a BookmarkNode. +- (const BookmarkNode*)nodeFromItem:(id)item; + +// Returns the icon to be displayed for an item representing a BookmarkNode. +// This will be the URL's favicon, a generic page icon, or a folder icon. +- (NSImage*)iconForItem:(id)item; + +// Opens a URL bookmark in a browser tab. +- (void)openBookmarkItem:(id)item; + +// Called by the toolbar search field after the user changes its text. +- (IBAction)searchFieldChanged:(id)sender; + +@end + + +// Exposed only for unit tests. +@interface BookmarkManagerController (UnitTesting) + +- (void)forgetNode:(const BookmarkNode*)node; +@property (readonly) BookmarkGroupsController* groupsController; +@property (readonly) BookmarkTreeController* treeController; + +@end diff --git a/chrome/browser/cocoa/bookmark_manager_controller.mm b/chrome/browser/cocoa/bookmark_manager_controller.mm new file mode 100644 index 0000000..8b39fb6 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_manager_controller.mm @@ -0,0 +1,261 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/bookmark_manager_controller.h" + +#include "app/resource_bundle.h" +#include "base/mac_util.h" +#include "base/sys_string_conversions.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/bookmarks/bookmark_model_observer.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_window.h" +#import "chrome/browser/cocoa/bookmark_groups_controller.h" +#import "chrome/browser/cocoa/bookmark_tree_controller.h" +#include "chrome/browser/profile.h" +#include "grit/app_resources.h" +#include "grit/theme_resources.h" +#include "skia/ext/skia_utils_mac.h" + + +// There's at most one BookmarkManagerController at a time. This points to it. +static BookmarkManagerController* sInstance; + + +@interface BookmarkManagerController () +- (void)nodeChanged:(const BookmarkNode*)node + childrenChanged:(BOOL)childrenChanged; +@end + + +// Adapter to tell BookmarkManagerController when bookmarks change. +class BookmarkManagerBridge : public BookmarkModelObserver { + public: + BookmarkManagerBridge(BookmarkManagerController* manager) + :manager_(manager) { } + + virtual void Loaded(BookmarkModel* model) { + // Ignore this; model has already loaded by this point. + } + + virtual void BookmarkNodeMoved(BookmarkModel* model, + const BookmarkNode* old_parent, + int old_index, + const BookmarkNode* new_parent, + int new_index) { + [manager_ nodeChanged:old_parent childrenChanged:YES]; + [manager_ nodeChanged:new_parent childrenChanged:YES]; + } + + virtual void BookmarkNodeAdded(BookmarkModel* model, + const BookmarkNode* parent, + int index) { + [manager_ nodeChanged:parent childrenChanged:YES]; + } + + virtual void BookmarkNodeRemoved(BookmarkModel* model, + const BookmarkNode* parent, + int old_index, + const BookmarkNode* node) { + [manager_ nodeChanged:parent childrenChanged:YES]; + [manager_ forgetNode:node]; + } + + virtual void BookmarkNodeChanged(BookmarkModel* model, + const BookmarkNode* node) { + [manager_ nodeChanged:node childrenChanged:NO]; + } + + virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, + const BookmarkNode* node) { + [manager_ nodeChanged:node childrenChanged:NO]; + } + + virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, + const BookmarkNode* node) { + [manager_ nodeChanged:node childrenChanged:YES]; + } + + private: + BookmarkManagerController* manager_; // weak +}; + + +@implementation BookmarkManagerController + + +// Private instance initialization method. +- (id)initWithProfile:(Profile*)profile { + // Use initWithWindowNibPath:: instead of initWithWindowNibName: so we + // can override it in a unit test. + NSString* nibPath = [mac_util::MainAppBundle() + pathForResource:@"BookmarkManager" + ofType:@"nib"]; + self = [super initWithWindowNibPath:nibPath owner:self]; + if (self != nil) { + profile_ = profile; + bridge_ = new BookmarkManagerBridge(self); + profile_->GetBookmarkModel()->AddObserver(bridge_); + + // Initialize some cached icons: + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + folderIcon_.reset([rb.GetNSImageNamed(IDR_BOOKMARK_BAR_FOLDER) retain]); + defaultFavIcon_.reset([rb.GetNSImageNamed(IDR_DEFAULT_FAVICON) retain]); + } + return self; +} + +- (void)dealloc { + if (self == sInstance) { + sInstance = nil; + } + if (bridge_) { + profile_->GetBookmarkModel()->RemoveObserver(bridge_); + delete bridge_; + } + [super dealloc]; +} + +- (void)awakeFromNib { + [groupsController_ reload]; + [treeController_ bind:@"group" + toObject:groupsController_ + withKeyPath:@"selectedGroup" + options:0]; +} + +// can't synthesize category methods, unfortunately +- (BookmarkGroupsController*)groupsController { + return groupsController_; +} + +- (BookmarkTreeController*)treeController { + return treeController_; +} + + +#pragma mark - +#pragma mark DATA MODEL: + + +// Getter for the |bookmarkModel| property. +- (BookmarkModel*)bookmarkModel { + return profile_->GetBookmarkModel(); +} + +// Maps a BookmarkNode to a table/outline row item placeholder. +- (const BookmarkNode*)nodeFromItem:(id)item { + return (const BookmarkNode*)[item pointerValue]; +} + +// Maps a table/outline row item placeholder back to a BookmarkNode. +- (id)itemFromNode:(const BookmarkNode*)node { + if (!nodeMap_) { + nodeMap_.reset([[NSMapTable alloc] + initWithKeyOptions:NSPointerFunctionsOpaqueMemory | + NSPointerFunctionsOpaquePersonality + valueOptions:NSPointerFunctionsStrongMemory + capacity:500]); + } + NSValue* item = (NSValue*)NSMapGet(nodeMap_, node); + if (!item) { + item = [NSValue valueWithPointer:node]; + NSMapInsertKnownAbsent(nodeMap_, node, item); + } + return item; +} + +// Removes a BookmarkNode from the node<->item mapping table. +- (void)forgetNode:(const BookmarkNode*)node { + NSMapRemove(nodeMap_, node); + for (int i = node->GetChildCount() - 1 ; i >= 0 ; i--) { + [self forgetNode:node->GetChild(i)]; + } +} + +// Called when the bookmark model changes; forwards to the sub-controllers. +- (void)nodeChanged:(const BookmarkNode*)node + childrenChanged:(BOOL)childrenChanged { + [groupsController_ nodeChanged:node childrenChanged:childrenChanged]; + // TreeController only cares about nodes we have items for, so don't bother + // creating a new item if the node's never been seen: + id item = (NSValue*)NSMapGet(nodeMap_, node); + if (item) { + [treeController_ itemChanged:item childrenChanged:childrenChanged]; + } +} + + +// Returns the icon (fav- or folder) for a table/outline item. +- (NSImage*)iconForItem:(id)item { + const BookmarkNode* node = [self nodeFromItem:item]; + if (node->is_folder()) { + return folderIcon_; + } else if (node->is_url()) { + const BookmarkNode* node = [self nodeFromItem:item]; + const SkBitmap& skIcon = [self bookmarkModel]->GetFavIcon(node); + if (!skIcon.isNull()) { + return gfx::SkBitmapToNSImage(skIcon); + } + } + return defaultFavIcon_; +} + + +#pragma mark - +#pragma mark WINDOW MANAGEMENT: + + +// Public entry point to open the bookmark manager. ++ (BookmarkManagerController*)showBookmarkManager:(Profile*)profile +{ + if (!sInstance) { + sInstance = [[self alloc] initWithProfile:profile]; + } + [sInstance showWindow:self]; + return sInstance; +} + +// When window closes, get rid of myself too. (NSWindow delegate) +- (void)windowWillClose:(NSNotification*)n { + [self autorelease]; +} + +// Install the search field into the search toolbar item. (NSToolbar delegate) +- (void)toolbarWillAddItem:(NSNotification*)notification { + NSToolbarItem* item = [[notification userInfo] objectForKey:@"item"]; + if ([[item itemIdentifier] isEqualToString:@"search"]) { + [item setView:toolbarSearchView_]; + NSSize size = [toolbarSearchView_ frame].size; + [item setMinSize:size]; + [item setMaxSize:size]; + } +} + +// Called when the user types into the search field. +- (IBAction)searchFieldChanged:(id)sender { + //TODO(snej): Implement this +} + + +// Open a bookmark, by having Chrome open a tab on its URL. +- (void)openBookmarkItem:(id)item { + const BookmarkNode* node = [self nodeFromItem:item]; + DCHECK(node); + if (!node->is_url()) + return; + GURL url = node->GetURL(); + + Browser* browser = BrowserList::GetLastActive(); + // if no browser window exists then create one with no tabs to be filled in + if (!browser) { + browser = Browser::Create(profile_); + browser->window()->Show(); + } + browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, + PageTransition::AUTO_BOOKMARK); +} + +@end diff --git a/chrome/browser/cocoa/bookmark_manager_controller_unittest.mm b/chrome/browser/cocoa/bookmark_manager_controller_unittest.mm new file mode 100644 index 0000000..8a3a00a --- /dev/null +++ b/chrome/browser/cocoa/bookmark_manager_controller_unittest.mm @@ -0,0 +1,73 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/bookmark_manager_controller.h" +#include "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { + +class BookmarkManagerControllerTest : public CocoaTest { + public: + void SetUp() { + CocoaTest::SetUp(); + controller_ = [BookmarkManagerController showBookmarkManager: + browser_test_helper_.profile()]; + ASSERT_TRUE(controller_); + } + + void TearDown() { + [controller_ close]; + CocoaTest::TearDown(); + } + + BrowserTestHelper browser_test_helper_; + BookmarkManagerController* controller_; +}; + +TEST_F(BookmarkManagerControllerTest, IsThisThingTurnedOn) { + NSWindow* w = [controller_ window]; + ASSERT_TRUE(w); + EXPECT_TRUE([w isVisible]); + + ASSERT_TRUE([controller_ groupsController]); + ASSERT_TRUE([controller_ treeController]); +} + +TEST_F(BookmarkManagerControllerTest, Model) { + BookmarkModel* model = [controller_ bookmarkModel]; + ASSERT_EQ(browser_test_helper_.profile()->GetBookmarkModel(), model); + + // Check the bookmarks-bar item: + const BookmarkNode* bar = model->GetBookmarkBarNode(); + ASSERT_TRUE(bar); + id barItem = [controller_ itemFromNode:bar]; + ASSERT_TRUE(barItem); + + // Check the 'others' item: + const BookmarkNode* other = model->other_node(); + ASSERT_TRUE(other); + EXPECT_NE(bar, other); + scoped_nsobject<id> otherItem([[controller_ itemFromNode:other] retain]); + ASSERT_TRUE(otherItem); + + EXPECT_NE(barItem, otherItem); + EXPECT_FALSE([barItem isEqual:otherItem]); + + EXPECT_EQ(bar, [controller_ nodeFromItem:barItem]); + EXPECT_EQ(barItem, [controller_ itemFromNode:bar]); + EXPECT_EQ(other, [controller_ nodeFromItem:otherItem]); + EXPECT_EQ(otherItem, [controller_ itemFromNode:other]); + + // Now tell it to forget 'other' and see if we get a different item id: + [controller_ forgetNode:other]; + id otherItem2 = [controller_ itemFromNode:other]; + EXPECT_TRUE(otherItem2); + EXPECT_NE(otherItem, otherItem2); +} + +} // namespace diff --git a/chrome/browser/cocoa/bookmark_tree_controller.h b/chrome/browser/cocoa/bookmark_tree_controller.h new file mode 100644 index 0000000..5e7b66e --- /dev/null +++ b/chrome/browser/cocoa/bookmark_tree_controller.h @@ -0,0 +1,68 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> +#include <vector> + +@class BookmarkManagerController; +class BookmarkModel; +class BookmarkNode; + + +// Controller for the bookmark tree view (the right pane). +@interface BookmarkTreeController : NSObject { + @private + IBOutlet NSOutlineView* outline_; + IBOutlet BookmarkManagerController* manager_; + id group_; + std::vector<const BookmarkNode*> draggedNodes_; +} + +// The top-level bookmark folder used as the root of the outline's tree. +// Observable, bindable. +@property (assign) id group; +// The currently selected item(s) in the outline. (Not observable.) +@property (retain) NSArray* selectedItems; + +// Action for the Delete command; also invoked by the delete key. +- (IBAction)delete:(id)sender; + +// Maps BookmarkNodes to NSOutlineView items. Equivalent to the method on +// BookmarkManagerController except that it maps the root node to nil. +- (id)itemFromNode:(const BookmarkNode*)node; + +// Maps NSOutlineView items back to BookmarkNodes. Equivalent to the method on +// BookmarkManagerController except that it maps nil back to the root node. +- (const BookmarkNode*)nodeFromItem:(id)item; + +// Called by the BookmarkManagerController to notify the data model's changed. +- (void)itemChanged:(id)nodeItem childrenChanged:(BOOL)childrenChanged; + +@end + + +// Drag/drop and copy/paste methods +// (These are implemented in bookmark_tree_controller_paste.mm.) +@interface BookmarkTreeController (Pasteboard) +// One-time drag-n-drop setup; called from -awakeFromNib. +- (void)registerDragTypes; +- (IBAction)cut:(id)sender; +- (IBAction)copy:(id)sender; +- (IBAction)paste:(id)sender; +@end + + +// Exposed only for unit tests. +@interface BookmarkTreeController (UnitTesting) + +- (BOOL)copyToPasteboard:(NSPasteboard*)pb; +- (BOOL)pasteFromPasteboard:(NSPasteboard*)pb; +@property (readonly) NSOutlineView* outline; + +@end + + +// Outline view for bookmark tree; handles Cut/Copy/Paste and Delete key. +@interface BookmarksOutlineView : NSOutlineView +@end diff --git a/chrome/browser/cocoa/bookmark_tree_controller.mm b/chrome/browser/cocoa/bookmark_tree_controller.mm new file mode 100644 index 0000000..3de9d51 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_tree_controller.mm @@ -0,0 +1,253 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/bookmark_tree_controller.h" + +#include "base/nsimage_cache_mac.h" +#include "base/sys_string_conversions.h" +#import "chrome/browser/cocoa/bookmark_manager_controller.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "googleurl/src/gurl.h" +#import "third_party/apple/ImageAndTextCell.h" + + +@implementation BookmarkTreeController + +// Allow the |group| property to be bound (by BookmarkManagerController.) ++ (void)initialize { + [self exposeBinding:@"group"]; +} + +// Initialization after the nib is loaded. +- (void)awakeFromNib { + [outline_ setTarget:self]; + [outline_ setDoubleAction:@selector(itemDoubleClicked:)]; + [self registerDragTypes]; +} + +- (id)group { + return group_; +} + +- (void)setGroup:(id)group { + if (group != group_) { + group_ = group; + + [outline_ deselectAll:self]; + [outline_ reloadData]; + [outline_ noteNumberOfRowsChanged]; + } +} + +- (NSOutlineView*)outline { + return outline_; +} + +// Updates the tree after the data model has changed. +- (void)itemChanged:(id)nodeItem childrenChanged:(BOOL)childrenChanged { + if (nodeItem == group_) + nodeItem = nil; + [outline_ reloadItem:nodeItem reloadChildren:childrenChanged]; +} + +// Getter for the |selectedItems| property. +- (NSArray*)selectedItems { + NSMutableArray* items = [NSMutableArray array]; + NSIndexSet* selectedRows = [outline_ selectedRowIndexes]; + if (selectedRows != nil) { + for (NSInteger row = [selectedRows firstIndex]; row != NSNotFound; + row = [selectedRows indexGreaterThanIndex:row]) { + [items addObject:[outline_ itemAtRow:row]]; + } + } + return items; +} + +// Setter for the |selectedItems| property. +- (void)setSelectedItems:(NSArray*)items { + NSMutableIndexSet* newSelection = [NSMutableIndexSet indexSet]; + + for (NSUInteger i = 0; i < [items count]; i++) { + NSInteger row = [outline_ rowForItem:[items objectAtIndex:i]]; + if (row >= 0) { + [newSelection addIndex:row]; + } + } + + [outline_ selectRowIndexes:newSelection byExtendingSelection:NO]; +} + + +#pragma mark - +#pragma mark COMMANDS: + + +// Responds to a double-click by opening the selected URL(s). +- (IBAction)itemDoubleClicked:(id)sender { + for (id item in [self selectedItems]) { + [manager_ openBookmarkItem:item]; + } +} + +// The Delete command (also bound to the delete key.) +- (IBAction)delete:(id)sender { + NSIndexSet* selectedRows = [outline_ selectedRowIndexes]; + if (!selectedRows) { + NSBeep(); + return; + } + // Iterate backwards so that any selected children are deleted before + // selected parents (opposite order would cause double-free!) and so each + // deletion doesn't invalidate the remaining row numbers. + for (NSInteger row = [selectedRows lastIndex]; row != NSNotFound; + row = [selectedRows indexLessThanIndex:row]) { + const BookmarkNode* node = [manager_ nodeFromItem: + [outline_ itemAtRow:row]]; + const BookmarkNode* parent = node->GetParent(); + [manager_ bookmarkModel]->Remove(parent, parent->IndexOfChild(node)); + } + + [outline_ reloadData]; + [outline_ deselectAll:self]; +} + + +#pragma mark - +#pragma mark DATA SOURCE: + + +// The NSOutlineView data source methods are called with a nil item to +// represent the root of the tree; this compensates for that. +- (const BookmarkNode*)nodeFromItem:(id)item { + return [manager_ nodeFromItem:(item ? item : group_)]; +} + +- (id)itemFromNode:(const BookmarkNode*)node { + id item = [manager_ itemFromNode:node]; + return item == group_ ? nil : item; +} + +// Returns the children of an item (NSOutlineView data source) +- (NSArray*)childrenOfItem:(id)item { + const BookmarkNode* node = [self nodeFromItem:item]; + if (!node) { + return nil; + } + int nChildren = node->GetChildCount(); + NSMutableArray* children = [NSMutableArray arrayWithCapacity:nChildren]; + for (int i = 0; i < nChildren; i++) { + [children addObject:[self itemFromNode:node->GetChild(i)]]; + } + return children; +} + +// Returns the number of children of an item (NSOutlineView data source) +- (NSInteger) outlineView:(NSOutlineView*)outlineView + numberOfChildrenOfItem:(id)item { + const BookmarkNode* node = [self nodeFromItem:item]; + return node ? node->GetChildCount() : 0; +} + +// Returns a child of an item (NSOutlineView data source) +- (id)outlineView:(NSOutlineView*)outlineView + child:(NSInteger)index + ofItem:(id)item { + const BookmarkNode* node = [self nodeFromItem:item]; + return [self itemFromNode:node->GetChild(index)]; +} + +// Returns whether an item is a folder (NSOutlineView data source) +- (BOOL)outlineView:(NSOutlineView*)outlineView isItemExpandable:(id)item { + return [self nodeFromItem:item]->is_folder(); +} + +// Returns the value to display in a cell (NSOutlineView data source) +- (id) outlineView:(NSOutlineView*)outlineView + objectValueForTableColumn:(NSTableColumn*)tableColumn + byItem:(id)item { + const BookmarkNode* node = [self nodeFromItem:item]; + NSString* ident = [tableColumn identifier]; + if ([ident isEqualToString:@"title"]) { + return base::SysWideToNSString(node->GetTitle()); + } else if ([ident isEqualToString:@"url"]) { + return base::SysUTF8ToNSString(node->GetURL().possibly_invalid_spec()); + } else { + NOTREACHED(); + return nil; + } +} + +// Stores the edited value of a cell (NSOutlineView data source) +- (void)outlineView:(NSOutlineView*)outlineView + setObjectValue:(id)value + forTableColumn:(NSTableColumn*)tableColumn + byItem:(id)item +{ + const BookmarkNode* node = [self nodeFromItem:item]; + NSString* ident = [tableColumn identifier]; + if ([ident isEqualToString:@"title"]) { + [manager_ bookmarkModel]->SetTitle(node, base::SysNSStringToWide(value)); + } else if ([ident isEqualToString:@"url"]) { + GURL url(base::SysNSStringToUTF8(value)); + if (url != node->GetURL()) { + //TODO(snej): Uncomment this once SetURL exists (bug 10603). + // ...or work around it by removing node and adding new one. + //[manager_ bookmarkModel]->SetURL(node, url); + } + } +} + +// Returns whether a cell is editable (NSOutlineView data source) +- (BOOL) outlineView:(NSOutlineView*)outlineView + shouldEditTableColumn:(NSTableColumn*)tableColumn + item:(id)item { + //TODO(snej): Make URL column editable once setter method exists (bug 10603). + NSString* ident = [tableColumn identifier]; + return [ident isEqualToString:@"title"]; +} + +// Sets a cell's icon before it's drawn (NSOutlineView data source) +- (void)outlineView:(NSOutlineView*)outlineView + willDisplayCell:(id)cell + forTableColumn:(NSTableColumn*)tableColumn + item:(id)item +{ + if ([[tableColumn identifier] isEqualToString:@"title"]) { + [(ImageAndTextCell*)cell setImage:[manager_ iconForItem:item]]; + } +} + +@end + + +@implementation BookmarksOutlineView + +- (IBAction)cut:(id)sender { + [(BookmarkTreeController*)[self delegate] cut:sender]; +} + +- (IBAction)copy:(id)sender { + [(BookmarkTreeController*)[self delegate] copy:sender]; +} + +- (IBAction)paste:(id)sender { + [(BookmarkTreeController*)[self delegate] paste:sender]; +} + +- (IBAction)delete:(id)sender { + [(BookmarkTreeController*)[self delegate] delete:sender]; +} + +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem { + return [[self delegate] validateMenuItem:menuItem]; +} + +- (void)keyDown:(NSEvent*)event { + if ([event keyCode] == 51) // Delete key + [self delete:self]; + else + [super keyDown:event]; +} + +@end diff --git a/chrome/browser/cocoa/bookmark_tree_controller_pasteboard.mm b/chrome/browser/cocoa/bookmark_tree_controller_pasteboard.mm new file mode 100644 index 0000000..e617b4c --- /dev/null +++ b/chrome/browser/cocoa/bookmark_tree_controller_pasteboard.mm @@ -0,0 +1,439 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/bookmark_tree_controller.h" + +#include "base/sys_string_conversions.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#import "chrome/browser/cocoa/bookmark_manager_controller.h" +#include "googleurl/src/gurl.h" + + +// Safari uses this type, though it's not declared in any header. +static NSString* const BookmarkDictionaryListPboardType = + @"BookmarkDictionaryListPboardType"; + +// Mac WebKit uses this type, declared in WebKit/mac/History/WebURLsWithTitles.h +static NSString* const WebURLsWithTitlesPboardType = + @"WebURLsWithTitlesPboardType"; + +// Used internally to identify intra-outline drags. +static NSString* const kCustomPboardType = + @"ChromeBookmarkTreeControllerPlaceholderType"; + + +@implementation BookmarkTreeController (Pasteboard) + + +// One-time dnd setup; called from -awakeFromNib. +- (void)registerDragTypes { + [outline_ registerForDraggedTypes:[NSArray arrayWithObjects: + BookmarkDictionaryListPboardType, + WebURLsWithTitlesPboardType, + NSURLPboardType, nil]]; + [outline_ setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES]; + [outline_ setDraggingSourceOperationMask:NSDragOperationEvery forLocal:NO]; +} + +// Selects a range of items in a parent node. +- (void)selectNodesInFolder:(const BookmarkNode*)parent + atIndexes:(NSRange)childRange { + DCHECK(NSMaxRange(childRange) <= (NSUInteger)parent->GetChildCount()); + id parentItem = [self itemFromNode:parent]; + if (parentItem != nil) { + // If parent is not the root, need to offset range by parent's index: + int startRow = [outline_ rowForItem:parentItem]; + if (startRow < 0) { + return; + } + if ([outline_ isItemExpanded:parentItem]) { + childRange.location += startRow + 1; + } else { + childRange.location = startRow; + childRange.length = 1; + } + } + NSIndexSet* indexes = [NSIndexSet indexSetWithIndexesInRange:childRange]; + [outline_ selectRowIndexes:indexes byExtendingSelection:NO]; +} + + +#pragma mark - +#pragma mark DRAGGING OUT AND COPYING: + + +// Generates parallel arrays of URLs and titles for contents of a node. +static void flattenNode(const BookmarkNode* node, + NSMutableArray* urlStrings, + NSMutableArray* titles) { + if (node->is_folder()) { + for (int i = 0; i < node->GetChildCount(); i++) { + flattenNode(node->GetChild(i), urlStrings, titles); + } + } else if (node->is_url()) { + [urlStrings addObject:base::SysUTF8ToNSString( + node->GetURL().possibly_invalid_spec())]; + [titles addObject:base::SysWideToNSString(node->GetTitle())]; + } +} + +// Writes data to the pasteboard given a list of row items. +- (BOOL)writeItems:(NSArray*)items + toPasteboard:(NSPasteboard*)pb + includeCustom:(BOOL)includeCustom { + if ([items count] == 0) { + return NO; + } + + [pb declareTypes:[NSMutableArray arrayWithObjects: + WebURLsWithTitlesPboardType, + NSStringPboardType, nil] + owner:self]; + + // Add URLs and titles: + NSMutableArray* urls = [NSMutableArray array]; + NSMutableArray* titles = [NSMutableArray array]; + for (id item in items) { + flattenNode([self nodeFromItem:item], urls, titles); + } + [pb setPropertyList:[NSArray arrayWithObjects:urls, titles, nil] + forType:WebURLsWithTitlesPboardType]; + + // Add plain text, as one URL per line: + [pb setString:[urls componentsJoinedByString:@"\n"] + forType:NSStringPboardType]; + + // Add custom type. The actual data doesn't matter since kCustomPboardType + // drags aren't recognized by anyone but us. + if (includeCustom) { + draggedNodes_.clear(); + for (id item in items) { + draggedNodes_.push_back([self nodeFromItem:item]); + } + [pb addTypes:[NSArray arrayWithObject: kCustomPboardType] owner: self]; + [pb setData:[NSData data] forType:kCustomPboardType]; + } + + // Add single URL: + if ([urls count] == 1) { + [pb addTypes:[NSArray arrayWithObject: NSURLPboardType] owner: self]; + NSString* firstURLStr = [urls objectAtIndex:0]; + [pb setString:firstURLStr forType:NSURLPboardType]; + } + return YES; +} + +// Invoked when dragging outline-view rows. +- (BOOL)outlineView:(NSOutlineView*)outlineView + writeItems:(NSArray*)items + toPasteboard:(NSPasteboard*)pb { + [self writeItems:items toPasteboard:pb includeCustom:YES]; + return YES; +} + + +// The Cut command. +- (IBAction)cut:(id)sender { + if ([self writeItems:[self selectedItems] + toPasteboard:[NSPasteboard generalPasteboard] + includeCustom:NO]) { + [self delete:self]; + } else { + NSBeep(); + } +} + +// The Copy command. +- (IBAction)copy:(id)sender { + if (![self copyToPasteboard:[NSPasteboard generalPasteboard]]) + NSBeep(); +} + +// Copy to any pasteboard. +- (BOOL)copyToPasteboard:(NSPasteboard*)pb { + return [self writeItems:[self selectedItems] + toPasteboard:pb + includeCustom:NO]; +} + + +#pragma mark - +#pragma mark INCOMING DRAGS AND PASTING: + + +// BookmarkDictionaryListPboardType represents bookmarks as dictionaries, +// which have the following keys. +// Strangely, folder nodes (whose WebBookmarkType is WebBookmarkTypeLeaf) have +// their title under 'Title', while leaf nodes have it in 'URIDictionary.title'. +static const NSString* kTitleKey = @"Title"; +static const NSString* kURIDictionaryKey = @"URIDictionary"; +static const NSString* kURIDictTitleKey = @"title"; +static const NSString* kURLStringKey = @"URLString"; +static const NSString* kTypeKey = @"WebBookmarkType"; +static const NSString* kLeafType = @"WebBookmarkTypeLeaf"; +//static const NSString* kListType = @"WebBookmarkTypeList"; // unused for now +static const NSString* kChildrenKey = @"Children"; + +// Helper that creates a dictionary in BookmarkDictionaryListPboardType format. +// |name| may be nil, but |urlStr| is required. +static NSDictionary* makeBookmarkPlistEntry(NSString* name, NSString* urlStr) { + if (!name) { + name = urlStr; + } + NSDictionary* nameDict = [NSDictionary dictionaryWithObject:name + forKey:kURIDictTitleKey]; + return [NSDictionary dictionaryWithObjectsAndKeys: + kLeafType, kTypeKey, + nameDict, kURIDictionaryKey, + urlStr, kURLStringKey, + nil]; +} + +// Reads URL(s) off the pasteboard and returns them in BookmarkDictionaryList- +// PboardType format, or nil on failure. +- (NSArray*)readPropertyListFromPasteboard:(NSPasteboard*)pb { + NSString* type = [pb availableTypeFromArray: + [outline_ registeredDraggedTypes]]; + if ([type isEqualToString:BookmarkDictionaryListPboardType]) { + // Safari's full bookmark plist type: + return [pb propertyListForType:type]; + + } else if ([type isEqualToString:WebURLsWithTitlesPboardType]) { + // Safari's parallel-URLs-and-titles type: + NSArray* contents = [pb propertyListForType:type]; + NSArray* urlStrings = [contents objectAtIndex:0]; + NSArray* titles = [contents objectAtIndex:1]; + NSUInteger n = [urlStrings count]; + if (n == 0 || [titles count] != n) { + return nil; + } + NSMutableArray* plist = [NSMutableArray array]; + for (NSUInteger i = 0; i < n; i++) { + [plist addObject:makeBookmarkPlistEntry([titles objectAtIndex:i], + [urlStrings objectAtIndex:i])]; + } + return plist; + + } else if ([type isEqualToString:NSURLPboardType]) { + // Standard URL type: + NSString* urlStr = [[NSURL URLFromPasteboard:pb] absoluteString]; + if (!urlStr) { + return nil; + } + NSString* title = [pb stringForType:@"public.url-name"]; + if (!title) + title = [pb stringForType:NSStringPboardType]; + return [NSArray arrayWithObject:makeBookmarkPlistEntry(title, urlStr)]; + + } else { + return nil; + } +} + + +// Moves BookmarkNodes into a parent folder, then selects them. +- (void)moveNodes:(std::vector<const BookmarkNode*>)nodes + toFolder:(const BookmarkNode*)dstParent + atIndex:(int)dstIndex { + for (std::vector<const BookmarkNode*>::iterator it = nodes.begin(); + it != nodes.end(); ++it) { + // Use an autorelease pool to clean up after the various observers that + // get called after each individual bookmark change. + NSAutoreleasePool* pool = [NSAutoreleasePool new]; + const BookmarkNode* srcNode = *it; + const BookmarkNode* srcParent = srcNode->GetParent(); + int srcIndex = srcParent->IndexOfChild(srcNode); + [manager_ bookmarkModel]->Move(srcNode, dstParent, dstIndex); + if (srcParent != dstParent || srcIndex >= dstIndex) { + dstIndex++; + } + [pool drain]; + } + + [self selectNodesInFolder:dstParent + atIndexes:NSMakeRange(dstIndex - nodes.size(), nodes.size())]; +} + +// Inserts bookmarks in BookmarkDictionaryListPboardType into a folder node. +- (void)insertPropertyList:(NSArray*)plist + inFolder:(const BookmarkNode*)dstParent + atIndex:(NSInteger)dstIndex { + BookmarkModel* model = [manager_ bookmarkModel]; + NSInteger i = 0; + for (NSDictionary* plistItem in plist) { + // Use an autorelease pool to clean up after the various observers that + // get called after each individual bookmark change. + NSAutoreleasePool* pool = [NSAutoreleasePool new]; + if ([[plistItem objectForKey:kTypeKey] isEqual:kLeafType]) { + NSString* title = [[plistItem objectForKey:kURIDictionaryKey] + objectForKey:kURIDictTitleKey]; + NSString* urlStr = [plistItem objectForKey:kURLStringKey]; + if (title && urlStr) { + model->AddURL(dstParent, + dstIndex + i, + base::SysNSStringToWide(title), + GURL(base::SysNSStringToUTF8(urlStr))); + ++i; + } + } else { + NSString* title = [plistItem objectForKey:kTitleKey]; + NSArray* children = [plistItem objectForKey:kChildrenKey]; + if (title && children) { + const BookmarkNode* newFolder; + newFolder = model->AddGroup(dstParent, + dstIndex + i, + base::SysNSStringToWide(title)); + ++i; + [self insertPropertyList:children + inFolder:newFolder + atIndex:0]; + } + } + [pool drain]; + } + [self selectNodesInFolder:dstParent + atIndexes:NSMakeRange(dstIndex, [plist count])]; +} + + +// Validates whether or not the proposed drop is valid. +- (NSDragOperation)outlineView:(NSOutlineView*)outlineView + validateDrop:(id <NSDraggingInfo>)info + proposedItem:(id)item + proposedChildIndex:(NSInteger)childIndex { + NSPasteboard* pb = [info draggingPasteboard]; + + // Check to see what we are proposed to be dropping on + const BookmarkNode*targetNode = [self nodeFromItem:item]; + if (!targetNode->is_folder()) { + // The target node is not a container, but a leaf. + // Refuse the drop (we may get called again with a between) + if (childIndex == NSOutlineViewDropOnItemIndex) { + return NSDragOperationNone; + } + } + + // Dragging within the outline? + if ([info draggingSource] == outlineView && + [[pb types] containsObject:kCustomPboardType]) { + // If we are allowing the drop, we see if we are dragging from ourselves + // and dropping into a descendent, which wouldn't be allowed... + // See if the appropriate drag information is available on the pasteboard. + //TODO(snej): Re-implement this + /* + if (targetNode != group_ && + [[[info draggingPasteboard] types] containsObject:kCustomPboardType]) { + for (NSDictionary* draggedNode in draggedNodes_) { + if ([self treeNode:targetNode isDescendantOfNode:draggedNode]) { + // Yup, it is, refuse it. + return NSDragOperationNone; + break; + } + } + */ + return NSDragOperationMove; + } + + // Drag from elsewhere is a copy. + return NSDragOperationCopy; +} + +// Actually handles the drop. +- (BOOL)outlineView:(NSOutlineView*)outlineView + acceptDrop:(id <NSDraggingInfo>)info + item:(id)item + childIndex:(NSInteger)childIndex +{ + NSPasteboard* pb = [info draggingPasteboard]; + + const BookmarkNode* targetNode = [self nodeFromItem:item]; + + // Determine the parent to insert into and the child index to insert at. + if (!targetNode->is_folder()) { + // If our target is a leaf, and we are dropping on it. + if (childIndex == NSOutlineViewDropOnItemIndex) { + return NO; + } else { + // We will be dropping on the item's parent at the target index + // of this child, plus one. + const BookmarkNode* oldTargetNode = targetNode; + targetNode = targetNode->GetParent(); + childIndex = targetNode->IndexOfChild(oldTargetNode) + 1; + } + } else { + if (childIndex == NSOutlineViewDropOnItemIndex) { + // Insert it at the end, if we were dropping on it + childIndex = targetNode->GetChildCount(); + } + } + + if ([info draggingSource] == outlineView && + [[pb types] containsObject:kCustomPboardType]) { + // If the source was ourselves, move the selected nodes. + [self moveNodes:draggedNodes_ + toFolder:targetNode + atIndex:childIndex]; + } else { + NSArray* plist = [self readPropertyListFromPasteboard:pb]; + if (!plist) { + return NO; + } + [self insertPropertyList:plist + inFolder:targetNode + atIndex:childIndex]; + } + return YES; +} + + +// The Paste command. +- (IBAction)paste:(id)sender { + if (![self pasteFromPasteboard:[NSPasteboard generalPasteboard]]) + NSBeep(); +} + +- (BOOL)pasteFromPasteboard:(NSPasteboard*)pb { + NSArray* plist = [self readPropertyListFromPasteboard: pb]; + if (!plist) + return NO; + + const BookmarkNode* targetNode; + NSInteger childIndex; + int selRow = [outline_ selectedRow]; + if (selRow >= 0) { + // Insert after selected row. + const BookmarkNode* selNode = [self nodeFromItem: + [outline_ itemAtRow:selRow]]; + targetNode = selNode->GetParent(); + childIndex = targetNode->IndexOfChild(selNode) + 1; + } else { + // ...or at very end if there's no selection: + targetNode = [self nodeFromItem:group_]; + childIndex = targetNode->GetChildCount(); + } + + [self insertPropertyList:plist + inFolder:targetNode + atIndex:childIndex]; + return YES; +} + + +// Selectively enables/disables menu commands. +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem { + SEL action = [menuItem action]; + if (action == @selector(cut:) || action == @selector(copy:) || + action == @selector(delete:)) { + return [[outline_ selectedRowIndexes] count] > 0; + } else if (action == @selector(paste:)) { + return [[NSPasteboard generalPasteboard] + availableTypeFromArray:[outline_ registeredDraggedTypes]] + != nil; + } else { + return YES; + } +} + + +@end diff --git a/chrome/browser/cocoa/bookmark_tree_controller_unittest.mm b/chrome/browser/cocoa/bookmark_tree_controller_unittest.mm new file mode 100644 index 0000000..dc22f19 --- /dev/null +++ b/chrome/browser/cocoa/bookmark_tree_controller_unittest.mm @@ -0,0 +1,186 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/bookmark_groups_controller.h" +#import "chrome/browser/cocoa/bookmark_manager_controller.h" +#import "chrome/browser/cocoa/bookmark_tree_controller.h" +#include "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +// Mac WebKit uses this type, declared in WebKit/mac/History/WebURLsWithTitles.h +static NSString* const WebURLsWithTitlesPboardType = + @"WebURLsWithTitlesPboardType"; + +namespace { + +class BookmarkTreeControllerTest : public CocoaTest { + public: + void SetUp() { + CocoaTest::SetUp(); + pasteboard_ = [NSPasteboard pasteboardWithUniqueName]; + manager_ = [BookmarkManagerController showBookmarkManager: + browser_test_helper_.profile()]; + ASSERT_TRUE(manager_); + treeController_ = [manager_ treeController]; + ASSERT_TRUE(treeController_); + } + + void TearDown() { + [manager_ close]; + [pasteboard_ releaseGlobally]; + CocoaTest::TearDown(); + } + + id SelectBar() { + BookmarkModel* model = [manager_ bookmarkModel]; + id barItem = [manager_ itemFromNode:model->GetBookmarkBarNode()]; + [[manager_ groupsController] setSelectedGroup:barItem]; + return barItem; + } + + id AddToBar(const std::wstring& title, const std::string& urlStr) { + BookmarkModel* model = [manager_ bookmarkModel]; + const BookmarkNode* bar = model->GetBookmarkBarNode(); + const BookmarkNode* node; + node = model->AddURL(bar, bar->GetChildCount(), title, GURL(urlStr)); + return [manager_ itemFromNode:node]; + } + + BrowserTestHelper browser_test_helper_; + BookmarkManagerController* manager_; + BookmarkTreeController* treeController_; + NSPasteboard* pasteboard_; +}; + +TEST_F(BookmarkTreeControllerTest, Model) { + // Select nothing in the group list and check tree is empty: + BookmarkGroupsController* groupsController = [manager_ groupsController]; + [groupsController setSelectedGroup:nil]; + ASSERT_EQ(nil, [treeController_ group]); + + // Select the bookmarks bar and check that it's shown in the tree: + id barItem = SelectBar(); + ASSERT_EQ(barItem, [treeController_ group]); +} + +TEST_F(BookmarkTreeControllerTest, Selection) { + SelectBar(); + id test1 = AddToBar(L"Test 1", "http://example.com/test1"); + id test2 = AddToBar(L"Test 2", "http://example.com/test2"); + id test3 = AddToBar(L"Test 3", "http://example.com/test3"); + EXPECT_EQ(0U, [[treeController_ selectedItems] count]); + + NSArray* sel = [NSArray arrayWithObject:test2]; + [treeController_ setSelectedItems:sel]; + EXPECT_TRUE([sel isEqual:[treeController_ selectedItems]]); + sel = [NSArray arrayWithObjects:test1, test3, nil]; + [treeController_ setSelectedItems:sel]; + EXPECT_TRUE([sel isEqual:[treeController_ selectedItems]]); + sel = [NSArray arrayWithObjects:test1, test2, test3, nil]; + [treeController_ setSelectedItems:sel]; + EXPECT_TRUE([sel isEqual:[treeController_ selectedItems]]); + sel = [NSArray array]; + [treeController_ setSelectedItems:sel]; + EXPECT_TRUE([sel isEqual:[treeController_ selectedItems]]); +} + +TEST_F(BookmarkTreeControllerTest, CopyURLs) { + SelectBar(); + AddToBar(L"Test 1", "http://example.com/test1"); + AddToBar(L"Test 2", "http://example.com/test2"); + AddToBar(L"Test 3", "http://example.com/test3"); + [[treeController_ outline] selectAll:treeController_]; + + ASSERT_TRUE([treeController_ copyToPasteboard:pasteboard_]); + + NSArray* contents = [pasteboard_ propertyListForType: + WebURLsWithTitlesPboardType]; + ASSERT_TRUE([contents isKindOfClass:[NSArray class]]); + NSArray* urlStrings = [contents objectAtIndex:0]; + EXPECT_TRUE([urlStrings isKindOfClass:[NSArray class]]); + NSArray* expectedURLStrings = [NSArray arrayWithObjects: + @"http://example.com/test1", + @"http://example.com/test2", + @"http://example.com/test3", nil]; + EXPECT_TRUE([urlStrings isEqual:expectedURLStrings]); + NSArray* titles = [contents objectAtIndex:1]; + EXPECT_TRUE([titles isKindOfClass:[NSArray class]]); + NSArray* expectedTitles = [NSArray arrayWithObjects: + @"Test 1", + @"Test 2", + @"Test 3", nil]; + EXPECT_TRUE([titles isEqual:expectedTitles]); + + NSString* str = [pasteboard_ stringForType:NSStringPboardType]; + EXPECT_TRUE([str isEqual: + @"http://example.com/test1\n" + "http://example.com/test2\n" + "http://example.com/test3"]); + + EXPECT_FALSE([pasteboard_ dataForType:NSURLPboardType]); +} + +TEST_F(BookmarkTreeControllerTest, PasteSingleURL) { + [pasteboard_ declareTypes:[NSArray arrayWithObjects: + NSURLPboardType, @"public.url-name", nil] + owner:nil]; + [[NSURL URLWithString:@"http://google.com"] writeToPasteboard:pasteboard_]; + [pasteboard_ setString:@"Gooooogle" forType:@"public.url-name"]; + + SelectBar(); + AddToBar(L"Test 1", "http://example.com/test1"); + AddToBar(L"Test 2", "http://example.com/test2"); + AddToBar(L"Test 3", "http://example.com/test3"); + + ASSERT_TRUE([treeController_ pasteFromPasteboard:pasteboard_]); + EXPECT_EQ(4, [[treeController_ outline] numberOfRows]); + EXPECT_EQ(3, [[treeController_ outline] selectedRow]); + NSArray* sel = [treeController_ selectedItems]; + ASSERT_EQ(1U, [sel count]); + const BookmarkNode* node = [manager_ nodeFromItem:[sel objectAtIndex:0]]; + ASSERT_TRUE(node); + EXPECT_EQ(GURL("http://google.com"), node->GetURL()); + EXPECT_EQ(L"Gooooogle", node->GetTitle()); +} + +TEST_F(BookmarkTreeControllerTest, PasteMultipleURLs) { + [pasteboard_ declareTypes:[NSArray arrayWithObjects: + WebURLsWithTitlesPboardType, + NSURLPboardType, nil] + owner:nil]; + NSMutableArray* urls = [NSArray arrayWithObjects: + @"http://google.com", @"http://chromium.org", nil]; + NSMutableArray* titles = [NSArray arrayWithObjects: + @"Gooooogle", @"Chrooooomium", nil]; + [pasteboard_ setPropertyList:[NSArray arrayWithObjects:urls, titles, nil] + forType:WebURLsWithTitlesPboardType]; + [[NSURL URLWithString:@"http://example.com"] writeToPasteboard:pasteboard_]; + + SelectBar(); + AddToBar(L"Test 1", "http://example.com/test1"); + id test2 = AddToBar(L"Test 2", "http://example.com/test2"); + AddToBar(L"Test 3", "http://example.com/test3"); + [treeController_ setSelectedItems:[NSArray arrayWithObject:test2]]; + + ASSERT_TRUE([treeController_ pasteFromPasteboard:pasteboard_]); + EXPECT_EQ(5, [[treeController_ outline] numberOfRows]); + EXPECT_TRUE([[[treeController_ outline] selectedRowIndexes] + isEqual:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)]]); + NSArray* sel = [treeController_ selectedItems]; + ASSERT_EQ(2U, [sel count]); + + const BookmarkNode* node = [manager_ nodeFromItem:[sel objectAtIndex:0]]; + ASSERT_TRUE(node); + EXPECT_EQ(GURL("http://google.com"), node->GetURL()); + EXPECT_EQ(L"Gooooogle", node->GetTitle()); + node = [manager_ nodeFromItem:[sel objectAtIndex:1]]; + ASSERT_TRUE(node); + EXPECT_EQ(GURL("http://chromium.org"), node->GetURL()); + EXPECT_EQ(L"Chrooooomium", node->GetTitle()); +} + +} // namespace diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index a7e5bf1..c25a32e 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -10,6 +10,7 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/browser_list.h" +#import "chrome/browser/cocoa/bookmark_manager_controller.h" #include "chrome/browser/cocoa/browser_window_cocoa.h" #import "chrome/browser/cocoa/browser_window_controller.h" #import "chrome/browser/cocoa/bug_report_window_controller.h" @@ -253,7 +254,7 @@ void BrowserWindowCocoa::ShowTaskManager() { } void BrowserWindowCocoa::ShowBookmarkManager() { - NOTIMPLEMENTED(); + [BookmarkManagerController showBookmarkManager:browser_->profile()]; } void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url, diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 65ca6b9..9ee667f 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -349,6 +349,10 @@ 'browser/cocoa/bookmark_editor_base_controller.mm', 'browser/cocoa/bookmark_editor_controller.h', 'browser/cocoa/bookmark_editor_controller.mm', + 'browser/cocoa/bookmark_groups_controller.mm', + 'browser/cocoa/bookmark_groups_controller.h', + 'browser/cocoa/bookmark_manager_controller.h', + 'browser/cocoa/bookmark_manager_controller.mm', 'browser/cocoa/bookmark_menu.h', 'browser/cocoa/bookmark_menu.mm', 'browser/cocoa/bookmark_menu_bridge.h', @@ -357,6 +361,9 @@ 'browser/cocoa/bookmark_menu_cocoa_controller.mm', 'browser/cocoa/bookmark_name_folder_controller.h', 'browser/cocoa/bookmark_name_folder_controller.mm', + 'browser/cocoa/bookmark_tree_controller.h', + 'browser/cocoa/bookmark_tree_controller.mm', + 'browser/cocoa/bookmark_tree_controller_pasteboard.mm', 'browser/cocoa/bookmark_tree_browser_cell.h', 'browser/cocoa/bookmark_tree_browser_cell.mm', 'browser/cocoa/browser_command_executor.h', @@ -2010,6 +2017,7 @@ 'app/nibs/BookmarkBar.xib', 'app/nibs/BookmarkBubble.xib', 'app/nibs/BookmarkEditor.xib', + 'app/nibs/BookmarkManager.xib', 'app/nibs/BookmarkNameFolder.xib', 'app/nibs/ClearBrowsingData.xib', 'app/nibs/DownloadItem.xib', diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi index b3d4d38f..29edb9e 100644 --- a/chrome/chrome_dll.gypi +++ b/chrome/chrome_dll.gypi @@ -183,6 +183,7 @@ 'app/nibs/BookmarkBar.xib', 'app/nibs/BookmarkBubble.xib', 'app/nibs/BookmarkEditor.xib', + 'app/nibs/BookmarkManager.xib', 'app/nibs/BookmarkNameFolder.xib', 'app/nibs/BrowserWindow.xib', 'app/nibs/ClearBrowsingData.xib', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 6e4673c..829be9e 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -575,11 +575,14 @@ 'browser/cocoa/bookmark_button_cell_unittest.mm', 'browser/cocoa/bookmark_editor_base_controller_unittest.mm', 'browser/cocoa/bookmark_editor_controller_unittest.mm', + 'browser/cocoa/bookmark_groups_controller_unittest.mm', + 'browser/cocoa/bookmark_manager_controller_unittest.mm', 'browser/cocoa/bookmark_menu_unittest.mm', 'browser/cocoa/bookmark_menu_bridge_unittest.mm', 'browser/cocoa/bookmark_menu_cocoa_controller_unittest.mm', 'browser/cocoa/bookmark_name_folder_controller_unittest.mm', 'browser/cocoa/bookmark_tree_browser_cell_unittest.mm', + 'browser/cocoa/bookmark_tree_controller_unittest.mm', 'browser/cocoa/browser_frame_view_unittest.mm', 'browser/cocoa/browser_window_cocoa_unittest.mm', 'browser/cocoa/browser_window_controller_unittest.mm', |