summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/nibs/BookmarkAllTabs.xib802
-rw-r--r--chrome/app/nibs/BookmarkEditor.xib87
-rw-r--r--chrome/browser/cocoa/bookmark_all_tabs_controller.h44
-rw-r--r--chrome/browser/cocoa/bookmark_all_tabs_controller.mm90
-rw-r--r--chrome/browser/cocoa/bookmark_all_tabs_controller_unittest.mm81
-rw-r--r--chrome/browser/cocoa/bookmark_editor_base_controller.h97
-rw-r--r--chrome/browser/cocoa/bookmark_editor_base_controller.mm398
-rw-r--r--chrome/browser/cocoa/bookmark_editor_base_controller_unittest.mm149
-rw-r--r--chrome/browser/cocoa/bookmark_editor_controller.h45
-rw-r--r--chrome/browser/cocoa/bookmark_editor_controller.mm430
-rw-r--r--chrome/browser/cocoa/bookmark_editor_controller_unittest.mm5
-rwxr-xr-xchrome/chrome.gyp8
12 files changed, 1784 insertions, 452 deletions
diff --git a/chrome/app/nibs/BookmarkAllTabs.xib b/chrome/app/nibs/BookmarkAllTabs.xib
new file mode 100644
index 0000000..09e68a6
--- /dev/null
+++ b/chrome/app/nibs/BookmarkAllTabs.xib
@@ -0,0 +1,802 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">9L30</string>
+ <string key="IBDocument.InterfaceBuilderVersion">670</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="2"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="1001">
+ <string key="NSClassName">BookmarkAllTabsController</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="1005">
+ <int key="NSWindowStyleMask">15</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{196, 257}, {480, 253}}</string>
+ <int key="NSWTFlags">536870912</int>
+ <string key="NSWindowTitle">Bookmark All Tabs</string>
+ <string key="NSWindowClass">NSWindow</string>
+ <nil key="NSViewClass"/>
+ <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ <string key="NSWindowContentMinSize">{480, 244}</string>
+ <object class="NSView" key="NSWindowView" id="1006">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSBrowser" id="723395462">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrame">{{20, 60}, {440, 143}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSBrowserCell" key="NSCellPrototype">
+ <int key="NSCellFlags">67239488</int>
+ <int key="NSCellFlags2">2048</int>
+ <string key="NSContents"> </string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.200000e+01</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ </object>
+ <string key="NSPathSeparator">/</string>
+ <int key="NSMinColumnWidth">100</int>
+ <int key="NSNumberOfVisibleColumns">3</int>
+ <int key="NSColumnResizingType">1</int>
+ <double key="NSPreferedColumnWidth">1.000000e+02</double>
+ <bool key="NSAllowsTypeSelect">YES</bool>
+ <int key="NSBrFlags">1544765440</int>
+ </object>
+ <object class="NSCustomView" id="138844528">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">289</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSButton" id="983581711">
+ <reference key="NSNextResponder" ref="138844528"/>
+ <int key="NSvFlags">289</int>
+ <string key="NSFrame">{{101, 12}, {96, 32}}</string>
+ <reference key="NSSuperview" ref="138844528"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="137649770">
+ <int key="NSCellFlags">604110336</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">^IDS_APP_OK</string>
+ <object class="NSFont" key="NSSupport" id="899171858">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.300000e+01</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <reference key="NSControlView" ref="983581711"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ <object class="NSButton" id="110527617">
+ <reference key="NSNextResponder" ref="138844528"/>
+ <int key="NSvFlags">289</int>
+ <string key="NSFrame">{{5, 12}, {96, 32}}</string>
+ <reference key="NSSuperview" ref="138844528"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="820689210">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">^IDS_APP_CANCEL</string>
+ <reference key="NSSupport" ref="899171858"/>
+ <reference key="NSControlView" ref="110527617"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">268435585</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent">.</string>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrame">{{269, 0}, {211, 52}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <string key="NSClassName">GTMWidthBasedTweaker</string>
+ </object>
+ <object class="NSCustomView" id="563188797">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">268</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSTextField" id="1036501322">
+ <reference key="NSNextResponder" ref="563188797"/>
+ <int key="NSvFlags">265</int>
+ <string key="NSFrame">{{17, 6}, {50, 17}}</string>
+ <reference key="NSSuperview" ref="563188797"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="52444064">
+ <int key="NSCellFlags">68288064</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents">^IDS_BOOMARK_EDITOR_NAME_LABEL</string>
+ <reference key="NSSupport" ref="899171858"/>
+ <reference key="NSControlView" ref="1036501322"/>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlTextColor</string>
+ <object class="NSColor" key="NSColor" id="528526553">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrame">{{0, 207}, {71, 32}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <string key="NSClassName">GTMWidthBasedTweaker</string>
+ </object>
+ <object class="NSCustomView" id="649769717">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">292</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSButton" id="631907363">
+ <reference key="NSNextResponder" ref="649769717"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{14, 12}, {111, 32}}</string>
+ <reference key="NSSuperview" ref="649769717"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="732374144">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">^IDS_BOOMARK_EDITOR_NEW_FOLDER_BUTTON</string>
+ <reference key="NSSupport" ref="899171858"/>
+ <reference key="NSControlView" ref="631907363"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{139, 52}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <string key="NSClassName">GTMWidthBasedTweaker</string>
+ </object>
+ <object class="NSTextField" id="921757931">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">266</int>
+ <string key="NSFrame">{{74, 211}, {386, 22}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="1025899850">
+ <int key="NSCellFlags">-1804468671</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents"/>
+ <reference key="NSSupport" ref="899171858"/>
+ <reference key="NSControlView" ref="921757931"/>
+ <bool key="NSDrawsBackground">YES</bool>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textBackgroundColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textColor</string>
+ <reference key="NSColor" ref="528526553"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{480, 253}</string>
+ <reference key="NSSuperview"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+ <string key="NSMinSize">{480, 266}</string>
+ <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ </object>
+ <object class="NSCustomObject" id="764065517">
+ <string key="NSClassName">ChromeUILocalizer</string>
+ </object>
+ <object class="NSCustomObject" id="12470901">
+ <string key="NSClassName">GTMUILocalizerAndLayoutTweaker</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">newFolder:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="631907363"/>
+ </object>
+ <int key="connectionID">21</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">cancel:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="110527617"/>
+ </object>
+ <int key="connectionID">22</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">ok:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="983581711"/>
+ </object>
+ <int key="connectionID">23</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">28</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1005"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">29</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">newFolderButton_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="631907363"/>
+ </object>
+ <int key="connectionID">30</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">okButton_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="983581711"/>
+ </object>
+ <int key="connectionID">31</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">uiObject_</string>
+ <reference key="source" ref="12470901"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">38</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">localizer_</string>
+ <reference key="source" ref="12470901"/>
+ <reference key="destination" ref="764065517"/>
+ </object>
+ <int key="connectionID">39</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">viewToResize_</string>
+ <reference key="source" ref="563188797"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">41</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">folderBrowser_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="723395462"/>
+ </object>
+ <int key="connectionID">59</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="723395462"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">60</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">target</string>
+ <reference key="source" ref="723395462"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">61</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">value: displayName</string>
+ <reference key="source" ref="921757931"/>
+ <reference key="destination" ref="1001"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="921757931"/>
+ <reference key="NSDestination" ref="1001"/>
+ <string key="NSLabel">value: displayName</string>
+ <string key="NSBinding">value</string>
+ <string key="NSKeyPath">displayName</string>
+ <object class="NSDictionary" key="NSOptions">
+ <string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+ <integer value="1" key="NS.object.0" id="5"/>
+ </object>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">65</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">enabled: okEnabled</string>
+ <reference key="source" ref="983581711"/>
+ <reference key="destination" ref="1001"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="983581711"/>
+ <reference key="NSDestination" ref="1001"/>
+ <string key="NSLabel">enabled: okEnabled</string>
+ <string key="NSBinding">enabled</string>
+ <string key="NSKeyPath">okEnabled</string>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">66</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="1002">
+ <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="1002"/>
+ <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="1002"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1004"/>
+ <reference key="parent" ref="1002"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="1005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1006"/>
+ </object>
+ <reference key="parent" ref="1002"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="1006"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="723395462"/>
+ <reference ref="138844528"/>
+ <reference ref="563188797"/>
+ <reference ref="649769717"/>
+ <reference ref="921757931"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">26</int>
+ <reference key="object" ref="723395462"/>
+ <reference key="parent" ref="1006"/>
+ <string key="objectName">Folder Tree Browser</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">34</int>
+ <reference key="object" ref="764065517"/>
+ <reference key="parent" ref="1002"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">36</int>
+ <reference key="object" ref="138844528"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="983581711"/>
+ <reference ref="110527617"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5</int>
+ <reference key="object" ref="983581711"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="137649770"/>
+ </object>
+ <reference key="parent" ref="138844528"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">6</int>
+ <reference key="object" ref="137649770"/>
+ <reference key="parent" ref="983581711"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">7</int>
+ <reference key="object" ref="110527617"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="820689210"/>
+ </object>
+ <reference key="parent" ref="138844528"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">8</int>
+ <reference key="object" ref="820689210"/>
+ <reference key="parent" ref="110527617"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">37</int>
+ <reference key="object" ref="12470901"/>
+ <reference key="parent" ref="1002"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">40</int>
+ <reference key="object" ref="563188797"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1036501322"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="1036501322"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="52444064"/>
+ </object>
+ <reference key="parent" ref="563188797"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">10</int>
+ <reference key="object" ref="52444064"/>
+ <reference key="parent" ref="1036501322"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">44</int>
+ <reference key="object" ref="649769717"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="631907363"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="631907363"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="732374144"/>
+ </object>
+ <reference key="parent" ref="649769717"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="732374144"/>
+ <reference key="parent" ref="631907363"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">13</int>
+ <reference key="object" ref="921757931"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1025899850"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">14</int>
+ <reference key="object" ref="1025899850"/>
+ <reference key="parent" ref="921757931"/>
+ </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.IBViewEditorWindowController.showingLayoutRectangles</string>
+ <string>1.IBWindowTemplateEditedContentRect</string>
+ <string>1.NSWindowTemplate.visibleAtLaunch</string>
+ <string>1.WindowOrigin</string>
+ <string>1.editorWindowContentRectSynchronizationRect</string>
+ <string>1.windowTemplate.hasMaxSize</string>
+ <string>1.windowTemplate.hasMinSize</string>
+ <string>1.windowTemplate.maxSize</string>
+ <string>1.windowTemplate.minSize</string>
+ <string>10.IBPluginDependency</string>
+ <string>13.IBPluginDependency</string>
+ <string>14.IBPluginDependency</string>
+ <string>2.IBPluginDependency</string>
+ <string>2.IBUserGuides</string>
+ <string>26.IBPluginDependency</string>
+ <string>3.IBPluginDependency</string>
+ <string>34.IBPluginDependency</string>
+ <string>37.IBPluginDependency</string>
+ <string>4.IBPluginDependency</string>
+ <string>5.IBPluginDependency</string>
+ <string>6.IBPluginDependency</string>
+ <string>7.IBPluginDependency</string>
+ <string>8.IBPluginDependency</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>{{141, 575}, {480, 253}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="0" id="6"/>
+ <string>{{141, 575}, {480, 253}}</string>
+ <reference ref="6"/>
+ <string>{196, 240}</string>
+ <string>{{357, 418}, {480, 270}}</string>
+ <reference ref="6"/>
+ <reference ref="5"/>
+ <string>{331, 270}</string>
+ <string>{480, 244}</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>
+ <object class="NSMutableArray">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <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>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>
+ </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">66</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">BookmarkAllTabsController</string>
+ <string key="superclassName">BookmarkEditorBaseController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/bookmark_all_tabs_controller.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">BookmarkEditorBaseController</string>
+ <string key="superclassName">NSWindowController</string>
+ <object class="NSMutableDictionary" key="actions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>cancel:</string>
+ <string>newFolder:</string>
+ <string>ok:</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="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>folderBrowser_</string>
+ <string>newFolderButton_</string>
+ <string>okButton_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSBrowser</string>
+ <string>NSButton</string>
+ <string>NSButton</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/bookmark_editor_base_controller.h</string>
+ </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">GTMUILocalizerAndLayoutTweaker</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>localizerOwner_</string>
+ <string>localizer_</string>
+ <string>uiObject_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>GTMUILocalizer</string>
+ <string>id</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="262327023">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMWidthBasedTweaker</string>
+ <string key="superclassName">NSView</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>viewToResize_</string>
+ <string>viewToSlideAndResize_</string>
+ <string>viewToSlide_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>NSView</string>
+ <string>NSView</string>
+ </object>
+ </object>
+ <reference key="sourceIdentifier" ref="262327023"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSBrowser</string>
+ <string key="superclassName">NSControl</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">target</string>
+ <string key="NS.object.0">id</string>
+ </object>
+ <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/BookmarkEditor.xib b/chrome/app/nibs/BookmarkEditor.xib
index aabecda..312cafd 100644
--- a/chrome/app/nibs/BookmarkEditor.xib
+++ b/chrome/app/nibs/BookmarkEditor.xib
@@ -1,28 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
-<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02">
<data>
<int key="IBDocument.SystemTarget">1050</int>
- <string key="IBDocument.SystemVersion">9L31a</string>
- <string key="IBDocument.InterfaceBuilderVersion">677</string>
+ <string key="IBDocument.SystemVersion">9L30</string>
+ <string key="IBDocument.InterfaceBuilderVersion">670</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="2"/>
+ <integer value="36"/>
</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">
@@ -346,14 +337,6 @@
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
- <string key="label">nameField_</string>
- <reference key="source" ref="1001"/>
- <reference key="destination" ref="921757931"/>
- </object>
- <int key="connectionID">24</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
<string key="label">urlField_</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="812603726"/>
@@ -448,6 +431,62 @@
</object>
<int key="connectionID">61</int>
</object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">value: displayURL</string>
+ <reference key="source" ref="812603726"/>
+ <reference key="destination" ref="1001"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="812603726"/>
+ <reference key="NSDestination" ref="1001"/>
+ <string key="NSLabel">value: displayURL</string>
+ <string key="NSBinding">value</string>
+ <string key="NSKeyPath">displayURL</string>
+ <object class="NSDictionary" key="NSOptions">
+ <string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+ <integer value="1" key="NS.object.0" id="5"/>
+ </object>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">64</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">value: displayName</string>
+ <reference key="source" ref="921757931"/>
+ <reference key="destination" ref="1001"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="921757931"/>
+ <reference key="NSDestination" ref="1001"/>
+ <string key="NSLabel">value: displayName</string>
+ <string key="NSBinding">value</string>
+ <string key="NSKeyPath">displayName</string>
+ <object class="NSDictionary" key="NSOptions">
+ <string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+ <reference key="NS.object.0" ref="5"/>
+ </object>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">65</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">enabled: okEnabled</string>
+ <reference key="source" ref="983581711"/>
+ <reference key="destination" ref="1001"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="983581711"/>
+ <reference key="NSDestination" ref="1001"/>
+ <string key="NSLabel">enabled: okEnabled</string>
+ <string key="NSBinding">enabled</string>
+ <string key="NSKeyPath">okEnabled</string>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">66</int>
+ </object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -698,10 +737,10 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{626, 873}, {480, 270}}</string>
+ <string>{{141, 558}, {480, 270}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="0" id="6"/>
- <string>{{626, 873}, {480, 270}}</string>
+ <string>{{141, 558}, {480, 270}}</string>
<reference ref="6"/>
<string>{196, 240}</string>
<string>{{357, 418}, {480, 270}}</string>
@@ -752,7 +791,7 @@
</object>
</object>
<nil key="sourceID"/>
- <int key="maxID">61</int>
+ <int key="maxID">66</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
diff --git a/chrome/browser/cocoa/bookmark_all_tabs_controller.h b/chrome/browser/cocoa/bookmark_all_tabs_controller.h
new file mode 100644
index 0000000..e861c50
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_all_tabs_controller.h
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef CHROME_BROWSER_COCOA_BOOKMARK_ALL_TABS_CONTROLLER_H_
+#define CHROME_BROWSER_COCOA_BOOKMARK_ALL_TABS_CONTROLLER_H_
+
+#include <utility>
+#include <vector>
+
+#import "chrome/browser/cocoa/bookmark_editor_base_controller.h"
+
+// A list of pairs containing the name and URL associated with each
+// currently active tab in the active browser window.
+typedef std::pair<std::wstring, GURL> ActiveTabNameURLPair;
+typedef std::vector<ActiveTabNameURLPair> ActiveTabsNameURLPairVector;
+
+// A controller for the bookmark editor, opened with Edit... from the
+// context menu of a bookmark button.
+@interface BookmarkAllTabsController : BookmarkEditorBaseController {
+ @private
+ ActiveTabsNameURLPairVector activeTabPairsVector_;
+}
+
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+ profile:(Profile*)profile
+ parent:(const BookmarkNode*)parent
+ configuration:(BookmarkEditor::Configuration)configuration
+ handler:(BookmarkEditor::Handler*)handler;
+
+@end
+
+@interface BookmarkAllTabsController(TestingAPI)
+
+// Initializes the list of all tab names and URLs. Overridden by unit test
+// to provide canned test data.
+- (void)UpdateActiveTabPairs;
+
+// Provides testing access to tab pairs list.
+- (ActiveTabsNameURLPairVector*)activeTabPairsVector;
+
+@end
+
+#endif /* CHROME_BROWSER_COCOA_BOOKMARK_ALL_TABS_CONTROLLER_H_ */
diff --git a/chrome/browser/cocoa/bookmark_all_tabs_controller.mm b/chrome/browser/cocoa/bookmark_all_tabs_controller.mm
new file mode 100644
index 0000000..93b4026
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_all_tabs_controller.mm
@@ -0,0 +1,90 @@
+// 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_all_tabs_controller.h"
+#include "app/l10n_util_mac.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "grit/generated_resources.h"
+
+@implementation BookmarkAllTabsController
+
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+ profile:(Profile*)profile
+ parent:(const BookmarkNode*)parent
+ configuration:(BookmarkEditor::Configuration)configuration
+ handler:(BookmarkEditor::Handler*)handler {
+ NSString* nibName = @"BookmarkAllTabs";
+ if ((self = [super initWithParentWindow:parentWindow
+ nibName:nibName
+ profile:profile
+ parent:parent
+ configuration:configuration
+ handler:handler])) {
+ }
+ return self;
+}
+
+- (void)awakeFromNib {
+ [self
+ setInitialName:
+ l10n_util::GetNSStringWithFixup(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME)];
+ [super awakeFromNib];
+}
+
+#pragma mark Bookmark Editing
+
+- (void)UpdateActiveTabPairs {
+ activeTabPairsVector_.clear();
+ Browser* browser = BrowserList::GetLastActive();
+ TabStripModel* tabstrip_model = browser->tabstrip_model();
+ const int tabCount = tabstrip_model->count();
+ for (int i = 0; i < tabCount; ++i) {
+ TabContents* tc = tabstrip_model->GetTabContentsAt(i);
+ const std::wstring tabTitle = UTF16ToWideHack(tc->GetTitle());
+ const GURL& tabURL(tc->GetURL());
+ ActiveTabNameURLPair tabPair(tabTitle, tabURL);
+ activeTabPairsVector_.push_back(tabPair);
+ }
+}
+
+// The the name for the folder into which the tabs will be recorded as
+// bookmarks is assumed to be non-empty. The folder is then created
+// and a bookmark for each open tab added therein.
+- (IBAction)ok:(id)sender {
+ NSString* name = [[self displayName] stringByTrimmingCharactersInSet:
+ [NSCharacterSet newlineCharacterSet]];
+ std::wstring newTitle = base::SysNSStringToWide(name);
+ const BookmarkNode* newParentNode = [self selectedNode];
+ int newIndex = newParentNode->GetChildCount();
+ // Create the new folder which will contain all of the tab URLs.
+ NSString* newFolderName = [self displayName];
+ std::wstring newFolderString = base::SysNSStringToWide(newFolderName);
+ BookmarkModel* model = [self bookmarkModel];
+ const BookmarkNode* newFolder = model->AddGroup(newParentNode, newIndex,
+ newFolderString);
+ [self NotifyHandlerCreatedNode:newFolder];
+ // Get a list of all open tabs, create nodes for them, and add
+ // to the new folder node.
+ [self UpdateActiveTabPairs];
+ int i = 0;
+ for (ActiveTabsNameURLPairVector::const_iterator it =
+ activeTabPairsVector_.begin();
+ it != activeTabPairsVector_.end(); ++it, ++i) {
+ const BookmarkNode* node = model->AddURL(newFolder, i,
+ it->first, it->second);
+ [self NotifyHandlerCreatedNode:node];
+ }
+ [super ok:sender];
+}
+
+- (ActiveTabsNameURLPairVector*)activeTabPairsVector {
+ return &activeTabPairsVector_;
+}
+
+@end // BookmarkAllTabsController
+
diff --git a/chrome/browser/cocoa/bookmark_all_tabs_controller_unittest.mm b/chrome/browser/cocoa/bookmark_all_tabs_controller_unittest.mm
new file mode 100644
index 0000000..db452b1
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_all_tabs_controller_unittest.mm
@@ -0,0 +1,81 @@
+// 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"
+#include "base/sys_string_conversions.h"
+#import "chrome/browser/cocoa/bookmark_all_tabs_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"
+
+@interface BookmarkAllTabsControllerOverride : BookmarkAllTabsController
+@end
+
+@implementation BookmarkAllTabsControllerOverride
+
+- (void)UpdateActiveTabPairs {
+ ActiveTabsNameURLPairVector* activeTabPairsVector =
+ [self activeTabPairsVector];
+ activeTabPairsVector->clear();
+ activeTabPairsVector->push_back(
+ ActiveTabNameURLPair(L"at-0", GURL("http://at-0.com")));
+ activeTabPairsVector->push_back(
+ ActiveTabNameURLPair(L"at-1", GURL("http://at-1.com")));
+ activeTabPairsVector->push_back(
+ ActiveTabNameURLPair(L"at-2", GURL("http://at-2.com")));
+}
+
+@end
+
+class BookmarkAllTabsControllerTest : public CocoaTest {
+ public:
+ CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc...
+ BrowserTestHelper helper_;
+ const BookmarkNode* parent_node_;
+ BookmarkAllTabsControllerOverride* controller_;
+ const BookmarkNode* group_a_;
+
+ BookmarkAllTabsControllerTest() {
+ BookmarkModel& model(*(helper_.profile()->GetBookmarkModel()));
+ const BookmarkNode* root = model.GetBookmarkBarNode();
+ group_a_ = model.AddGroup(root, 0, L"a");
+ model.AddURL(group_a_, 0, L"a-0", GURL("http://a-0.com"));
+ model.AddURL(group_a_, 1, L"a-1", GURL("http://a-1.com"));
+ model.AddURL(group_a_, 2, L"a-2", GURL("http://a-2.com"));
+ }
+
+ virtual BookmarkAllTabsControllerOverride* CreateController() {
+ return [[BookmarkAllTabsControllerOverride alloc]
+ initWithParentWindow:cocoa_helper_.window()
+ profile:helper_.profile()
+ parent:group_a_
+ configuration:BookmarkEditor::SHOW_TREE
+ handler:nil];
+ }
+
+ virtual void SetUp() {
+ CocoaTest::SetUp();
+ controller_ = CreateController();
+ EXPECT_TRUE([controller_ window]);
+ }
+
+ virtual void TearDown() {
+ [controller_ close];
+ CocoaTest::TearDown();
+ }
+};
+
+TEST_F(BookmarkAllTabsControllerTest, BookmarkAllTabs) {
+ // OK button should always be enabled.
+ EXPECT_TRUE([controller_ okButtonEnabled]);
+ [controller_ setDisplayName:@"ALL MY TABS"];
+ [controller_ ok:nil];
+ EXPECT_EQ(4, group_a_->GetChildCount());
+ const BookmarkNode* folderChild = group_a_->GetChild(3);
+ EXPECT_EQ(folderChild->GetTitle(), L"ALL MY TABS");
+ EXPECT_EQ(3, folderChild->GetChildCount());
+}
diff --git a/chrome/browser/cocoa/bookmark_editor_base_controller.h b/chrome/browser/cocoa/bookmark_editor_base_controller.h
new file mode 100644
index 0000000..cb0725d
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_editor_base_controller.h
@@ -0,0 +1,97 @@
+// 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.
+
+#ifndef CHROME_BROWSER_COCOA_BOOKMARK_EDITOR_BASE_CONTROLLER_H_
+#define CHROME_BROWSER_COCOA_BOOKMARK_EDITOR_BASE_CONTROLLER_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/cocoa_protocols_mac.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/bookmarks/bookmark_editor.h"
+
+@class BookmarkTreeBrowserCell;
+class BookmarkModel;
+
+// A base controller class for bookmark creation and editing dialogs which
+// present the current bookmark folder structure in a tree view. Do not
+// instantiate this controller directly -- use one of its derived classes.
+// NOTE: If your derived classes is intended to be dispatched via the
+// BookmarkEditor::Show static function found in the accompanying
+// implementation will need to update that function.
+@interface BookmarkEditorBaseController :
+ NSWindowController<NSMatrixDelegate, NSTextFieldDelegate> {
+ @private
+ IBOutlet NSBrowser* folderBrowser_;
+ IBOutlet NSButton* newFolderButton_;
+ IBOutlet NSButton* okButton_; // Used for unit testing only.
+
+ NSWindow* parentWindow_;
+ Profile* profile_; // weak
+ const BookmarkNode* parentNode_; // weak; owned by the model
+ BookmarkEditor::Configuration configuration_;
+ scoped_ptr<BookmarkEditor::Handler> handler_; // we take ownership
+ NSString* initialName_;
+ NSString* displayName_; // Bound to a text field in the dialog.
+ BOOL okEnabled_; // Bound to the OK button.
+}
+
+@property (copy) NSString* initialName;
+@property (copy) NSString* displayName;
+@property (assign) BOOL okEnabled;
+
+// Designated initializer. Derived classes should call through to this init.
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+ nibName:(NSString*)nibName
+ profile:(Profile*)profile
+ parent:(const BookmarkNode*)parent
+ configuration:(BookmarkEditor::Configuration)configuration
+ handler:(BookmarkEditor::Handler*)handler;
+
+// Run the bookmark editor as a modal sheet. Does not block.
+- (void)runAsModalSheet;
+
+// Create a new folder at the end of the selected parent folder, give it
+// an untitled name, and put it into editing mode.
+- (IBAction)newFolder:(id)sender;
+
+// Actions for the buttons at the bottom of the window.
+- (IBAction)cancel:(id)sender;
+
+// The OK action will record the edited bookmark. The default dismisses
+// the dialog and should be called by the derived class if overridden.
+- (IBAction)ok:(id)sender;
+
+// Methods for use by derived classes only.
+
+// Determine and returns the rightmost selected/highlighted element (node)
+// in the bookmark tree view if the tree view is showing, otherwise returns
+// the original |parentNode_|. If the tree view is showing but nothing is
+// selected then return the root node. This assumes that leaf nodes (pure
+// bookmarks) are not being presented.
+- (const BookmarkNode*)selectedNode;
+
+// Select/highlight the given node within the browser tree view. If the
+// node is nil then select the bookmark bar node. Exposed for unit test.
+- (void)selectNodeInBrowser:(const BookmarkNode*)node;
+
+// Notify the handler, if any, of a node creation.
+- (void)NotifyHandlerCreatedNode:(const BookmarkNode*)node;
+
+// Accessors
+- (BookmarkModel*)bookmarkModel;
+- (const BookmarkNode*)parentNode;
+
+@end
+
+@interface BookmarkEditorBaseController(TestingAPI)
+@property (readonly) BOOL okButtonEnabled;
+- (void)selectTestNodeInBrowser:(const BookmarkNode*)node;
++ (const BookmarkNode*)folderChildForParent:(const BookmarkNode*)parent
+ withFolderIndex:(NSInteger)index;
++ (int)indexOfFolderChild:(const BookmarkNode*)child;
+@end
+
+#endif /* CHROME_BROWSER_COCOA_BOOKMARK_EDITOR_BASE_CONTROLLER_H_ */
diff --git a/chrome/browser/cocoa/bookmark_editor_base_controller.mm b/chrome/browser/cocoa/bookmark_editor_base_controller.mm
new file mode 100644
index 0000000..d97874a
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_editor_base_controller.mm
@@ -0,0 +1,398 @@
+// 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_editor_base_controller.h"
+#include "app/l10n_util.h"
+#include "base/logging.h"
+#include "base/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#import "chrome/browser/cocoa/bookmark_all_tabs_controller.h"
+#import "chrome/browser/cocoa/bookmark_editor_controller.h"
+#import "chrome/browser/cocoa/bookmark_tree_browser_cell.h"
+#include "chrome/browser/profile.h"
+#include "grit/generated_resources.h"
+
+@interface BookmarkEditorBaseController (Private)
+
+// Given a cell in the folder browser, make that cell editable so that the
+// bookmark folder name can be modified by the user.
+- (void)editFolderNameInCell:(BookmarkTreeBrowserCell*)cell;
+
+// The action called by the bookmark folder name cell being edited by
+// the user when editing has been completed (such as by pressing <return>).
+- (void)cellEditingCompleted:(id)sender;
+
+// Update the folder name from the current edit in the given cell
+// and return the focus to the folder tree browser.
+- (void)saveFolderNameForCell:(BookmarkTreeBrowserCell*)cell;
+
+// A custom action handler called by the bookmark folder browser when the
+// user has double-clicked on a folder name.
+- (void)browserDoubleClicked:(id)sender;
+
+@end
+
+// static; implemented for each platform.
+void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd,
+ Profile* profile,
+ const BookmarkNode* parent,
+ const EditDetails& details,
+ Configuration configuration,
+ Handler* handler) {
+ BookmarkEditorBaseController* controller = nil;
+ if (details.type == EditDetails::NEW_FOLDER) {
+ controller = [[BookmarkAllTabsController alloc]
+ initWithParentWindow:parent_hwnd
+ profile:profile
+ parent:parent
+ configuration:configuration
+ handler:handler];
+ } else {
+ controller = [[BookmarkEditorController alloc]
+ initWithParentWindow:parent_hwnd
+ profile:profile
+ parent:parent
+ node:details.existing_node
+ configuration:configuration
+ handler:handler];
+ }
+ [controller runAsModalSheet];
+}
+
+#pragma mark Bookmark TreeNode Helpers
+
+namespace {
+
+// Find the index'th folder child of a parent, ignoring bookmarks (leafs).
+const BookmarkNode* GetFolderChildForParent(const BookmarkNode* parent_node,
+ NSInteger folder_index) {
+ const BookmarkNode* child_node = nil;
+ int i = 0;
+ int child_count = parent_node->GetChildCount();
+ do {
+ child_node = parent_node->GetChild(i);
+ if (child_node->type() != BookmarkNode::URL)
+ --folder_index;
+ ++i;
+ } while (folder_index >= 0 && i < child_count);
+ return child_node;
+}
+
+// Determine the index of a child within its parent ignoring
+// bookmarks (leafs).
+int IndexOfFolderChild(const BookmarkNode* child_node) {
+ const BookmarkNode* node_parent = child_node->GetParent();
+ int child_index = node_parent->IndexOfChild(child_node);
+ for (int i = child_index - 1; i >= 0; --i) {
+ const BookmarkNode* sibling = node_parent->GetChild(i);
+ if (sibling->type() == BookmarkNode::URL)
+ --child_index;
+ }
+ return child_index;
+}
+
+} // namespace
+
+@implementation BookmarkEditorBaseController
+
+@synthesize initialName = initialName_;
+@synthesize displayName = displayName_;
+@synthesize okEnabled = okEnabled_;
+
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+ nibName:(NSString*)nibName
+ profile:(Profile*)profile
+ parent:(const BookmarkNode*)parent
+ configuration:(BookmarkEditor::Configuration)configuration
+ handler:(BookmarkEditor::Handler*)handler {
+ NSString* nibpath = [mac_util::MainAppBundle()
+ pathForResource:nibName
+ ofType:@"nib"];
+ if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+ parentWindow_ = parentWindow;
+ profile_ = profile;
+ parentNode_ = parent;
+ configuration_ = configuration;
+ handler_.reset(handler);
+ initialName_ = [@"" retain];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [initialName_ release];
+ [displayName_ release];
+ [super dealloc];
+}
+
+- (void)awakeFromNib {
+ [self setDisplayName:[self initialName]];
+
+ if (configuration_ != BookmarkEditor::SHOW_TREE) {
+ // Remember the NSBrowser's height; we will shrink our frame by that
+ // much.
+ NSRect frame = [[self window] frame];
+ CGFloat browserHeight = [folderBrowser_ frame].size.height;
+ frame.size.height -= browserHeight;
+ frame.origin.y += browserHeight;
+ // Remove the NSBrowser and "new folder" button.
+ [folderBrowser_ removeFromSuperview];
+ [newFolderButton_ removeFromSuperview];
+ // Finally, commit the size change.
+ [[self window] setFrame:frame display:YES];
+ }
+
+ [folderBrowser_ setCellClass:[BookmarkTreeBrowserCell class]];
+ [folderBrowser_ setDoubleAction:@selector(browserDoubleClicked:)];
+}
+
+- (void)windowDidLoad {
+ if (configuration_ == BookmarkEditor::SHOW_TREE) {
+ [self selectNodeInBrowser:parentNode_];
+ }
+}
+
+- (void)windowWillClose:(NSNotification *)notification {
+ // If a folder name cell is being edited then force it to end editing
+ // so that any changes are recorded.
+ [[self window] makeFirstResponder:nil];
+ [self autorelease];
+}
+
+/* TODO(jrg):
+// Implementing this informal protocol allows us to open the sheet
+// somewhere other than at the top of the window. NOTE: this means
+// that I, the controller, am also the window's delegate.
+- (NSRect)window:(NSWindow*)window willPositionSheet:(NSWindow*)sheet
+ usingRect:(NSRect)rect {
+ // adjust rect.origin.y to be the bottom of the toolbar
+ return rect;
+}
+*/
+
+// TODO(jrg): consider NSModalSession.
+- (void)runAsModalSheet {
+ [NSApp beginSheet:[self window]
+ modalForWindow:parentWindow_
+ modalDelegate:self
+ didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
+ contextInfo:nil];
+}
+
+- (void)selectNodeInBrowser:(const BookmarkNode*)node {
+ DCHECK(configuration_ == BookmarkEditor::SHOW_TREE);
+ std::deque<NSInteger> rowsToSelect;
+ const BookmarkNode* nodeParent = nil;
+ if (node) {
+ nodeParent = node->GetParent();
+ // There should always be a parent node.
+ DCHECK(nodeParent);
+ while (nodeParent) {
+ int nodeRow = IndexOfFolderChild(node);
+ rowsToSelect.push_front(nodeRow);
+ node = nodeParent;
+ nodeParent = nodeParent->GetParent();
+ }
+ } else {
+ BookmarkModel* model = profile_->GetBookmarkModel();
+ nodeParent = model->GetBookmarkBarNode();
+ rowsToSelect.push_front(0);
+ }
+ for (std::deque<NSInteger>::size_type column = 0;
+ column < rowsToSelect.size();
+ ++column) {
+ [folderBrowser_ selectRow:rowsToSelect[column] inColumn:column];
+ }
+
+ // Force the OK button state to be re-evaluated.
+ [self willChangeValueForKey:@"okEnabled"];
+ [self didChangeValueForKey:@"okEnabled"];
+}
+
+- (const BookmarkNode*)selectedNode {
+ BookmarkModel* model = profile_->GetBookmarkModel();
+ const BookmarkNode* selectedNode = NULL;
+ // Determine a new parent node only if the browser is showing.
+ if (configuration_ == BookmarkEditor::SHOW_TREE) {
+ selectedNode = model->root_node();
+ NSInteger column = 0;
+ NSInteger selectedRow = [folderBrowser_ selectedRowInColumn:column];
+ while (selectedRow >= 0) {
+ selectedNode = GetFolderChildForParent(selectedNode,
+ selectedRow);
+ ++column;
+ selectedRow = [folderBrowser_ selectedRowInColumn:column];
+ }
+ } else {
+ // If the tree is not showing then we use the original parent.
+ selectedNode = parentNode_;
+ }
+ return selectedNode;
+}
+
+- (void)NotifyHandlerCreatedNode:(const BookmarkNode*)node {
+ if (handler_.get())
+ handler_->NodeCreated(node);
+}
+
+#pragma mark New Folder Handler & Folder Cell Editing
+
+- (void)editFolderNameInCell:(BookmarkTreeBrowserCell*)cell {
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
+ [cell setEditable:YES];
+ [cell setTarget:self];
+ [cell setAction:@selector(cellEditingCompleted:)];
+ [cell setSendsActionOnEndEditing:YES];
+ NSMatrix* matrix = [cell matrix];
+ // Set the delegate so that we get called when editing completes.
+ [matrix setDelegate:self];
+ [matrix selectText:self];
+}
+
+- (void)cellEditingCompleted:(id)sender {
+ DCHECK([sender isKindOfClass:[NSMatrix class]]);
+ BookmarkTreeBrowserCell* cell = [sender selectedCell];
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
+ [self saveFolderNameForCell:cell];
+}
+
+- (void)saveFolderNameForCell:(BookmarkTreeBrowserCell*)cell {
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
+ // It's possible that the cell can get reused so clean things up
+ // to prevent inadvertant notifications.
+ [cell setTarget:nil];
+ [cell setAction:nil];
+ [cell setEditable:NO];
+ [cell setSendsActionOnEndEditing:NO];
+ // Force a responder change here to force the editing of the cell's text
+ // to complete otherwise the call to -[cell title] could return stale text.
+ // The focus does not automatically get reset to the browser when the
+ // cell gives up focus.
+ [[folderBrowser_ window] makeFirstResponder:folderBrowser_];
+ const BookmarkNode* bookmarkNode = [cell bookmarkNode];
+ BookmarkModel* model = profile_->GetBookmarkModel();
+ NSString* newTitle = [cell title];
+ model->SetTitle(bookmarkNode, base::SysNSStringToWide(newTitle));
+}
+
+- (void)browserDoubleClicked:(id)sender {
+ BookmarkTreeBrowserCell* cell = [folderBrowser_ selectedCell];
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
+ [self editFolderNameInCell:cell];
+}
+
+- (IBAction)newFolder:(id)sender {
+ BookmarkModel* model = profile_->GetBookmarkModel();
+ const BookmarkNode* newParentNode = [self selectedNode];
+ int newIndex = newParentNode->GetChildCount();
+ std::wstring newFolderString =
+ l10n_util::GetString(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME);
+ const BookmarkNode* newFolder = model->AddGroup(newParentNode, newIndex,
+ newFolderString);
+ [self selectNodeInBrowser:newFolder];
+ BookmarkTreeBrowserCell* cell = [folderBrowser_ selectedCell];
+ [self editFolderNameInCell:cell];
+}
+
+- (BOOL)okEnabled {
+ return YES;
+}
+
+- (IBAction)ok:(id)sender {
+ [NSApp endSheet:[self window]];
+}
+
+- (IBAction)cancel:(id)sender {
+ [NSApp endSheet:[self window]];
+}
+
+- (void)didEndSheet:(NSWindow*)sheet
+ returnCode:(int)returnCode
+ contextInfo:(void*)contextInfo {
+ [sheet close];
+}
+
+- (BookmarkModel*)bookmarkModel {
+ return profile_->GetBookmarkModel();
+}
+
+- (const BookmarkNode*)parentNode {
+ return parentNode_;
+}
+
+#pragma mark For Unit Test Use Only
+
+- (BOOL)okButtonEnabled {
+ return [okButton_ isEnabled];
+}
+
+- (void)selectTestNodeInBrowser:(const BookmarkNode*)node {
+ [self selectNodeInBrowser:node];
+}
+
++ (const BookmarkNode*)folderChildForParent:(const BookmarkNode*)parent
+ withFolderIndex:(NSInteger)index {
+ return GetFolderChildForParent(parent, index);
+}
+
++ (int)indexOfFolderChild:(const BookmarkNode*)child {
+ return IndexOfFolderChild(child);
+}
+
+
+#pragma mark NSBrowser delegate methods
+
+// Given a column number, determine the parent bookmark folder node for the
+// bookmarks being shown in that column. This is done by scanning forward
+// from column zero and following the selected row for each column up
+// to the parent of the desired column.
+- (const BookmarkNode*)parentNodeForColumn:(NSInteger)column {
+ DCHECK(column >= 0);
+ BookmarkModel* model = profile_->GetBookmarkModel();
+ const BookmarkNode* node = model->root_node();
+ for (NSInteger i = 0; i < column; ++i) {
+ NSInteger selectedRowInColumn = [folderBrowser_ selectedRowInColumn:i];
+ node = GetFolderChildForParent(node, selectedRowInColumn);
+ }
+ return node;
+}
+
+// This implementation returns the number of folders contained in the parent
+// folder node for this column.
+// TOTO(mrossetti): Decide if bookmark (i.e. non-folder) nodes should be
+// shown, perhaps in gray.
+- (NSInteger)browser:(NSBrowser*)sender numberOfRowsInColumn:(NSInteger)col {
+ NSInteger rowCount = 0;
+ const BookmarkNode* parentNode = [self parentNodeForColumn:col];
+ if (parentNode) {
+ int childCount = parentNode->GetChildCount();
+ for (int i = 0; i < childCount; ++i) {
+ const BookmarkNode* childNode = parentNode->GetChild(i);
+ if (childNode->type() != BookmarkNode::URL)
+ ++rowCount;
+ }
+ }
+ return rowCount;
+}
+
+- (void)browser:(NSBrowser*)sender
+ willDisplayCell:(NSBrowserCell*)cell
+ atRow:(NSInteger)row
+ column:(NSInteger)column {
+ DCHECK(row >= 0); // Trust AppKit, but verify.
+ DCHECK(column >= 0);
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
+ const BookmarkNode* parentNode = [self parentNodeForColumn:column];
+ const BookmarkNode* childNode = GetFolderChildForParent(parentNode, row);
+ DCHECK(childNode);
+ BookmarkTreeBrowserCell* browserCell =
+ static_cast<BookmarkTreeBrowserCell*>(cell);
+ [browserCell setTitle:base::SysWideToNSString(childNode->GetTitle())];
+ [browserCell setBookmarkNode:childNode];
+ [browserCell setMatrix:[folderBrowser_ matrixInColumn:column]];
+}
+
+@end // BookmarkEditorBaseController
+
diff --git a/chrome/browser/cocoa/bookmark_editor_base_controller_unittest.mm b/chrome/browser/cocoa/bookmark_editor_base_controller_unittest.mm
new file mode 100644
index 0000000..908fe25
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_editor_base_controller_unittest.mm
@@ -0,0 +1,149 @@
+// 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"
+#include "base/sys_string_conversions.h"
+#import "chrome/browser/cocoa/bookmark_editor_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"
+
+class BookmarkEditorBaseControllerTest : public CocoaTest {
+ public:
+ CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc...
+ BrowserTestHelper helper_;
+ BookmarkEditorBaseController* controller_;
+ const BookmarkNode* group_a_;
+ const BookmarkNode* group_b_;
+ const BookmarkNode* group_b_0_;
+ const BookmarkNode* group_b_3_;
+ const BookmarkNode* group_c_;
+
+ BookmarkEditorBaseControllerTest() {
+ // Set up a small bookmark hierarchy, which will look as follows:
+ // a b c d
+ // a-0 b-0 c-0
+ // a-1 b-00 c-1
+ // a-2 b-1 c-2
+ // b-2 c-3
+ // b-3
+ // b-30
+ // b-31
+ // b-4
+ BookmarkModel& model(*(helper_.profile()->GetBookmarkModel()));
+ const BookmarkNode* root = model.GetBookmarkBarNode();
+ group_a_ = model.AddGroup(root, 0, L"a");
+ model.AddURL(group_a_, 0, L"a-0", GURL("http://a-0.com"));
+ model.AddURL(group_a_, 1, L"a-1", GURL("http://a-1.com"));
+ model.AddURL(group_a_, 2, L"a-2", GURL("http://a-2.com"));
+
+ group_b_ = model.AddGroup(root, 1, L"b");
+ group_b_0_ = model.AddGroup(group_b_, 0, L"b-0");
+ model.AddURL(group_b_0_, 0, L"bb-0", GURL("http://bb-0.com"));
+ model.AddURL(group_b_, 1, L"b-1", GURL("http://b-1.com"));
+ model.AddURL(group_b_, 2, L"b-2", GURL("http://b-2.com"));
+ group_b_3_ = model.AddGroup(group_b_, 3, L"b-3");
+ model.AddURL(group_b_3_, 0, L"b-30", GURL("http://b-30.com"));
+ model.AddURL(group_b_3_, 1, L"b-31", GURL("http://b-31.com"));
+ model.AddURL(group_b_, 4, L"b-4", GURL("http://b-4.com"));
+
+ group_c_ = model.AddGroup(root, 2, L"c");
+ model.AddURL(group_c_, 0, L"c-0", GURL("http://c-0.com"));
+ model.AddURL(group_c_, 1, L"c-1", GURL("http://c-1.com"));
+ model.AddURL(group_c_, 2, L"c-2", GURL("http://c-2.com"));
+ model.AddURL(group_c_, 3, L"c-3", GURL("http://c-3.com"));
+
+ model.AddURL(root, 3, L"d", GURL("http://d-0.com"));
+ }
+
+ virtual BookmarkEditorBaseController* CreateController() {
+ return [[BookmarkEditorBaseController alloc]
+ initWithParentWindow:test_window()
+ nibName:@"BookmarkAllTabs"
+ profile:helper_.profile()
+ parent:group_b_0_
+ configuration:BookmarkEditor::SHOW_TREE
+ handler:nil];
+ }
+
+ virtual void SetUp() {
+ CocoaTest::SetUp();
+ controller_ = CreateController();
+ EXPECT_TRUE([controller_ window]);
+ }
+
+ virtual void TearDown() {
+ [controller_ close];
+ CocoaTest::TearDown();
+ }
+};
+
+TEST_F(BookmarkEditorBaseControllerTest, VerifyBookmarkTestModel) {
+ BookmarkModel& model(*(helper_.profile()->GetBookmarkModel()));
+ const BookmarkNode& root(*model.GetBookmarkBarNode());
+ EXPECT_EQ(4, root.GetChildCount());
+ // a
+ const BookmarkNode* child = root.GetChild(0);
+ EXPECT_EQ(3, child->GetChildCount());
+ const BookmarkNode* subchild = child->GetChild(0);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ subchild = child->GetChild(1);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ subchild = child->GetChild(2);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ // b
+ child = root.GetChild(1);
+ EXPECT_EQ(5, child->GetChildCount());
+ subchild = child->GetChild(0);
+ EXPECT_EQ(1, subchild->GetChildCount());
+ const BookmarkNode* subsubchild = subchild->GetChild(0);
+ EXPECT_EQ(0, subsubchild->GetChildCount());
+ subchild = child->GetChild(1);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ subchild = child->GetChild(2);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ subchild = child->GetChild(3);
+ EXPECT_EQ(2, subchild->GetChildCount());
+ subsubchild = subchild->GetChild(0);
+ EXPECT_EQ(0, subsubchild->GetChildCount());
+ subsubchild = subchild->GetChild(1);
+ EXPECT_EQ(0, subsubchild->GetChildCount());
+ subchild = child->GetChild(4);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ // c
+ child = root.GetChild(2);
+ EXPECT_EQ(4, child->GetChildCount());
+ subchild = child->GetChild(0);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ subchild = child->GetChild(1);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ subchild = child->GetChild(2);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ subchild = child->GetChild(3);
+ EXPECT_EQ(0, subchild->GetChildCount());
+ // d
+ child = root.GetChild(3);
+ EXPECT_EQ(0, child->GetChildCount());
+}
+
+TEST_F(BookmarkEditorBaseControllerTest, FolderChildForParent) {
+ const BookmarkNode* child =
+ [BookmarkEditorBaseController folderChildForParent:group_b_
+ withFolderIndex:1];
+ EXPECT_EQ(child, group_b_3_);
+}
+
+TEST_F(BookmarkEditorBaseControllerTest, IndexOfFolderChild) {
+ int index = [BookmarkEditorBaseController indexOfFolderChild:group_b_3_];
+ EXPECT_EQ(index, 1);
+}
+
+TEST_F(BookmarkEditorBaseControllerTest, NodeSelection) {
+ [controller_ selectNodeInBrowser:group_b_3_];
+ const BookmarkNode* node = [controller_ selectedNode];
+ EXPECT_EQ(node, group_b_3_);
+}
diff --git a/chrome/browser/cocoa/bookmark_editor_controller.h b/chrome/browser/cocoa/bookmark_editor_controller.h
index 055b7fd..ff779b8 100644
--- a/chrome/browser/cocoa/bookmark_editor_controller.h
+++ b/chrome/browser/cocoa/bookmark_editor_controller.h
@@ -5,37 +5,19 @@
#ifndef CHROME_BROWSER_COCOA_BOOKMARK_EDITOR_CONTROLLER_H_
#define CHROME_BROWSER_COCOA_BOOKMARK_EDITOR_CONTROLLER_H_
-#import <Cocoa/Cocoa.h>
-
-#import "base/cocoa_protocols_mac.h"
-#include "base/scoped_ptr.h"
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
-
-@class BookmarkTreeBrowserCell;
+#import "chrome/browser/cocoa/bookmark_editor_base_controller.h"
// A controller for the bookmark editor, opened with Edit... from the
// context menu of a bookmark button.
-@interface BookmarkEditorController : NSWindowController<NSMatrixDelegate,
- NSTextFieldDelegate> {
+@interface BookmarkEditorController : BookmarkEditorBaseController {
@private
- IBOutlet NSTextField* nameField_;
- IBOutlet NSTextField* urlField_;
- IBOutlet NSBrowser* folderBrowser_;
- IBOutlet NSButton* okButton_;
- IBOutlet NSButton* newFolderButton_;
-
- NSWindow* parentWindow_;
- Profile* profile_; // weak
- const BookmarkNode* parentNode_; // weak; owned by the model
const BookmarkNode* node_; // weak; owned by the model
- BookmarkEditor::Configuration configuration_;
- scoped_ptr<BookmarkEditor::Handler> handler_; // we take ownership
-
- scoped_nsobject<NSString> initialName_;
scoped_nsobject<NSString> initialUrl_;
+ NSString* displayURL_; // Bound to a text field in the dialog.
}
+@property (copy) NSString* displayURL;
+
- (id)initWithParentWindow:(NSWindow*)parentWindow
profile:(Profile*)profile
parent:(const BookmarkNode*)parent
@@ -43,23 +25,6 @@
configuration:(BookmarkEditor::Configuration)configuration
handler:(BookmarkEditor::Handler*)handler;
-// Run the bookmark editor as a modal sheet. Does not block.
-- (void)runAsModalSheet;
-
-// Create a new folder at the end of the selected parent folder, give it
-// an untitled name, and put it into editing mode.
-- (IBAction)newFolder:(id)sender;
-
-// Actions for the buttons at the bottom of the window.
-- (IBAction)cancel:(id)sender;
-- (IBAction)ok:(id)sender;
-@end
-
-@interface BookmarkEditorController(TestingAPI)
-@property (assign) NSString* displayName;
-@property (assign) NSString* displayURL;
-@property (readonly) BOOL okButtonEnabled;
-- (void)selectTestNodeInBrowser:(const BookmarkNode*)node;
@end
#endif /* CHROME_BROWSER_COCOA_BOOKMARK_EDITOR_CONTROLLER_H_ */
diff --git a/chrome/browser/cocoa/bookmark_editor_controller.mm b/chrome/browser/cocoa/bookmark_editor_controller.mm
index 2915094..8164d4b 100644
--- a/chrome/browser/cocoa/bookmark_editor_controller.mm
+++ b/chrome/browser/cocoa/bookmark_editor_controller.mm
@@ -2,319 +2,69 @@
// 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_editor_controller.h"
#include "app/l10n_util.h"
-#include "base/logging.h"
-#include "base/mac_util.h"
#include "base/sys_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/profile.h"
-#import "chrome/browser/cocoa/bookmark_tree_browser_cell.h"
-#import "chrome/browser/cocoa/bookmark_editor_controller.h"
-#include "grit/generated_resources.h"
@interface BookmarkEditorController (Private)
// Grab the url from the text field and convert.
- (GURL)GURLFromUrlField;
-// Given a cell in the folder browser, make that cell editable so that the
-// bookmark folder name can be modified by the user.
-- (void)editFolderNameInCell:(BookmarkTreeBrowserCell*)cell;
-
-// The action called by the bookmark folder name cell being edited by
-// the user when editing has been completed (such as by pressing <return>).
-- (void)cellEditingCompleted:(id)sender;
-
-// Update the folder name from the current edit in the given cell
-// and return the focus to the folder tree browser.
-- (void)saveFolderNameForCell:(BookmarkTreeBrowserCell*)cell;
-
-// A custom action handler called by the bookmark folder browser when the
-// user has double-clicked on a folder name.
-- (void)browserDoubleClicked:(id)sender;
-
-// Determine and returns the rightmost selected/highlighted element (node)
-// in the bookmark tree view if the tree view is showing, otherwise returns
-// the original parentNode_. If the tree view is showing but nothing is
-// selected then return the root node. This assumes that leaf nodes (pure
-// bookmarks) are not being presented.
-- (const BookmarkNode*)selectedNode;
-
-// Select/highlight the given node within the browser tree view. If the
-// node is nil then select the bookmark bar.
-- (void)selectNodeInBrowser:(const BookmarkNode*)node;
-
@end
-// static; implemented for each platform.
-void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd,
- Profile* profile,
- const BookmarkNode* parent,
- const EditDetails& details,
- Configuration configuration,
- Handler* handler) {
- if (details.type == EditDetails::NEW_FOLDER) {
- // TODO(sky): implement this.
- NOTIMPLEMENTED();
- return;
- }
- BookmarkEditorController* controller = [[BookmarkEditorController alloc]
- initWithParentWindow:parent_hwnd
- profile:profile
- parent:parent
- node:details.existing_node
- configuration:configuration
- handler:handler];
- [controller runAsModalSheet];
-}
-
-#pragma mark Bookmark TreeNode Helpers
-
-namespace {
+@implementation BookmarkEditorController
-// Find the index'th folder child of a parent, ignoring bookmarks (leafs).
-const BookmarkNode* GetFolderChildForParent(const BookmarkNode* parent_node,
- NSInteger folder_index) {
- const BookmarkNode* child_node = nil;
- int i = 0;
- int child_count = parent_node->GetChildCount();
- do {
- child_node = parent_node->GetChild(i);
- if (child_node->type() != BookmarkNode::URL)
- --folder_index;
- ++i;
- } while (folder_index >= 0 && i < child_count);
- return child_node;
-}
+@synthesize displayURL = displayURL_;
-// Determine the index of a child within its parent ignoring
-// bookmarks (leafs).
-int IndexOfFolderChild(const BookmarkNode* child_node) {
- const BookmarkNode* node_parent = child_node->GetParent();
- int child_index = node_parent->IndexOfChild(child_node);
- for (int i = child_index - 1; i >= 0; --i) {
- const BookmarkNode* sibling = node_parent->GetChild(i);
- if (sibling->type() == BookmarkNode::URL)
- --child_index;
- }
- return child_index;
++ (NSSet*)keyPathsForValuesAffectingOkEnabled {
+ return [NSSet setWithObject:@"displayURL"];
}
-} // namespace
-
-@implementation BookmarkEditorController
-
- (id)initWithParentWindow:(NSWindow*)parentWindow
profile:(Profile*)profile
parent:(const BookmarkNode*)parent
node:(const BookmarkNode*)node
configuration:(BookmarkEditor::Configuration)configuration
handler:(BookmarkEditor::Handler*)handler {
- NSString* nibpath = [mac_util::MainAppBundle()
- pathForResource:@"BookmarkEditor"
- ofType:@"nib"];
- if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
- parentWindow_ = parentWindow;
- profile_ = profile;
- parentNode_ = parent;
+ if ((self = [super initWithParentWindow:parentWindow
+ nibName:@"BookmarkEditor"
+ profile:profile
+ parent:parent
+ configuration:configuration
+ handler:handler])) {
// "Add Page..." has no "node" so this may be NULL.
node_ = node;
- configuration_ = configuration;
- handler_.reset(handler);
}
return self;
}
+- (void)dealloc {
+ [displayURL_ release];
+ [super dealloc];
+}
+
- (void)awakeFromNib {
// Set text fields to match our bookmark. If the node is NULL we
// arrived here from an "Add Page..." item in a context menu.
if (node_) {
- initialName_.reset([base::SysWideToNSString(node_->GetTitle()) retain]);
+ [self setInitialName:base::SysWideToNSString(node_->GetTitle())];
std::string url_string = node_->GetURL().possibly_invalid_spec();
initialUrl_.reset([[NSString stringWithUTF8String:url_string.c_str()]
retain]);
} else {
- initialName_.reset([@"" retain]);
initialUrl_.reset([@"" retain]);
}
- [nameField_ setStringValue:initialName_];
- [urlField_ setStringValue:initialUrl_];
-
- // Get a ping when the URL or name text fields change;
- // trigger an initial ping to set things up.
- [nameField_ setDelegate:self];
- [urlField_ setDelegate:self];
- [self controlTextDidChange:nil];
-
- if (configuration_ != BookmarkEditor::SHOW_TREE) {
- // Remember the NSBrowser's height; we will shrink our frame by that
- // much.
- NSRect frame = [[self window] frame];
- CGFloat browserHeight = [folderBrowser_ frame].size.height;
- frame.size.height -= browserHeight;
- frame.origin.y += browserHeight;
- // Remove the NSBrowser and "new folder" button.
- [folderBrowser_ removeFromSuperview];
- [newFolderButton_ removeFromSuperview];
- // Finally, commit the size change.
- [[self window] setFrame:frame display:YES];
- }
-
- [folderBrowser_ setCellClass:[BookmarkTreeBrowserCell class]];
- [folderBrowser_ setDoubleAction:@selector(browserDoubleClicked:)];
-}
-
-- (void)windowDidLoad {
- if (configuration_ == BookmarkEditor::SHOW_TREE) {
- // Find and select the |parent| bookmark node in the folder tree browser.
- [self selectNodeInBrowser:parentNode_];
- }
-}
-
-- (void)windowWillClose:(NSNotification *)notification {
- // If a folder name cell is being edited then force it to end editing
- // so that any changes are recorded.
- [[self window] makeFirstResponder:nil];
-
- // This is probably unnecessary but it feels cleaner since the
- // delegate of a text field can be automatically registered for
- // notifications.
- [nameField_ setDelegate:nil];
- [urlField_ setDelegate:nil];
- [self autorelease];
-}
-
-/* TODO(jrg):
-// Implementing this informal protocol allows us to open the sheet
-// somewhere other than at the top of the window. NOTE: this means
-// that I, the controller, am also the window's delegate.
-- (NSRect)window:(NSWindow*)window willPositionSheet:(NSWindow*)sheet
- usingRect:(NSRect)rect {
- // adjust rect.origin.y to be the bottom of the toolbar
- return rect;
-}
-*/
-
-// TODO(jrg): consider NSModalSession.
-- (void)runAsModalSheet {
- [NSApp beginSheet:[self window]
- modalForWindow:parentWindow_
- modalDelegate:self
- didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
- contextInfo:nil];
-}
-
-- (void)selectNodeInBrowser:(const BookmarkNode*)node {
- DCHECK(configuration_ == BookmarkEditor::SHOW_TREE);
- std::deque<NSInteger> rowsToSelect;
- const BookmarkNode* nodeParent = nil;
- if (node) {
- nodeParent = node->GetParent();
- // There should always be a parent node.
- DCHECK(nodeParent);
- while (nodeParent) {
- int nodeRow = IndexOfFolderChild(node);
- rowsToSelect.push_front(nodeRow);
- node = nodeParent;
- nodeParent = nodeParent->GetParent();
- }
- } else {
- BookmarkModel* model = profile_->GetBookmarkModel();
- nodeParent = model->GetBookmarkBarNode();
- rowsToSelect.push_front(0);
- }
- for (std::deque<NSInteger>::size_type column = 0;
- column < rowsToSelect.size();
- ++column) {
- [folderBrowser_ selectRow:rowsToSelect[column] inColumn:column];
- }
- [self controlTextDidChange:nil];
-}
-
-- (const BookmarkNode*)selectedNode {
- BookmarkModel* model = profile_->GetBookmarkModel();
- const BookmarkNode* selectedNode = NULL;
- // Determine a new parent node only if the browser is showing.
- if (configuration_ == BookmarkEditor::SHOW_TREE) {
- selectedNode = model->root_node();
- NSInteger column = 0;
- NSInteger selectedRow = [folderBrowser_ selectedRowInColumn:column];
- while (selectedRow >= 0) {
- selectedNode = GetFolderChildForParent(selectedNode,
- selectedRow);
- ++column;
- selectedRow = [folderBrowser_ selectedRowInColumn:column];
- }
- } else {
- // If the tree is not showing then we use the original parent.
- selectedNode = parentNode_;
- }
- return selectedNode;
-}
-
-#pragma mark New Folder Handler & Folder Cell Editing
-
-- (void)editFolderNameInCell:(BookmarkTreeBrowserCell*)cell {
- DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
- [cell setEditable:YES];
- [cell setTarget:self];
- [cell setAction:@selector(cellEditingCompleted:)];
- [cell setSendsActionOnEndEditing:YES];
- NSMatrix* matrix = [cell matrix];
- // Set the delegate so that we get called when editing wants to complete.
- [matrix setDelegate:self];
- [matrix selectText:self];
-}
-
-- (void)cellEditingCompleted:(id)sender {
- DCHECK([sender isKindOfClass:[NSMatrix class]]);
- BookmarkTreeBrowserCell* cell = [sender selectedCell];
- DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
- [self saveFolderNameForCell:cell];
-}
-
-- (void)saveFolderNameForCell:(BookmarkTreeBrowserCell*)cell {
- DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
- // It's possible that the cell can get reused so clean things up
- // to prevent inadvertant notifications.
- [cell setTarget:nil];
- [cell setAction:nil];
- [cell setEditable:NO];
- [cell setSendsActionOnEndEditing:NO];
- // Force a responder change here to force the editing of the cell's text
- // to complete otherwise the call to -[cell title] could return stale text.
- [[folderBrowser_ window] makeFirstResponder:folderBrowser_];
- const BookmarkNode* bookmarkNode = [cell bookmarkNode];
- BookmarkModel* model = profile_->GetBookmarkModel();
- NSString* newTitle = [cell title];
- model->SetTitle(bookmarkNode, base::SysNSStringToWide(newTitle));
-}
-
-- (void)browserDoubleClicked:(id)sender {
- BookmarkTreeBrowserCell* cell = [folderBrowser_ selectedCell];
- DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
- [self editFolderNameInCell:cell];
-}
-
-- (IBAction)newFolder:(id)sender {
- BookmarkModel* model = profile_->GetBookmarkModel();
- const BookmarkNode* newParentNode = [self selectedNode];
- int newIndex = newParentNode->GetChildCount();
- std::wstring newFolderString =
- l10n_util::GetString(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME);
- const BookmarkNode* newFolder = model->AddGroup(newParentNode, newIndex,
- newFolderString);
- [self selectNodeInBrowser:newFolder];
- BookmarkTreeBrowserCell* cell = [folderBrowser_ selectedCell];
- [self editFolderNameInCell:cell];
+ [self setDisplayURL:initialUrl_];
+ [super awakeFromNib];
}
#pragma mark Bookmark Editing
// If possible, return a valid GURL from the URL text field.
- (GURL)GURLFromUrlField {
- NSString* url = [urlField_ stringValue];
+ NSString* url = [self displayURL];
GURL newURL = GURL([url UTF8String]);
if (!newURL.is_valid()) {
// Mimic observed friendliness from Windows
@@ -323,25 +73,28 @@ int IndexOfFolderChild(const BookmarkNode* child_node) {
return newURL;
}
-// Enable the OK button if there is a bookmark name and there is a valid URL.
-// We set ourselves as the delegate of urlField_ so this gets called.
-// (Yes, setting ourself as a delegate automatically registers us for
-// the notification.)
-- (void)controlTextDidChange:(NSNotification*)aNotification {
- GURL newURL = [self GURLFromUrlField];
- [okButton_ setEnabled:(newURL.is_valid()) ? YES : NO];
+// Enable the OK button if there is a valid URL.
+- (BOOL)okEnabled {
+ BOOL okEnabled = NO;
+ if ([[self displayURL] length]) {
+ GURL newURL = [self GURLFromUrlField];
+ okEnabled = (newURL.is_valid()) ? YES : NO;
+ }
+ return okEnabled;
}
-// The ok: action is connected to the OK button in the Edit Bookmark window
-// of the BookmarkEditor.xib. The the bookmark's name and URL are assumed
-// to be valid (otherwise the OK button should not be enabled). If the
-// bookmark previously existed then it is removed from its old folder.
-// The bookmark is then added to its new folder. If the folder has not
-// changed then the bookmark stays in its original position (index) otherwise
-// it is added to the end of the new folder.
+// The the bookmark's URL is assumed to be valid (otherwise the OK button
+// should not be enabled). If the bookmark previously existed then it is
+// removed from its old folder. The bookmark is then added to its new
+// folder. If the folder has not changed then the bookmark stays in its
+// original position (index) otherwise it is added to the end of the new folder.
- (IBAction)ok:(id)sender {
- NSString* name = [nameField_ stringValue];
+ NSString* name = [[self displayName] stringByTrimmingCharactersInSet:
+ [NSCharacterSet newlineCharacterSet]];
std::wstring newTitle = base::SysNSStringToWide(name);
+ const BookmarkNode* newParentNode = [self selectedNode];
+ BookmarkModel* model = [self bookmarkModel];
+ int newIndex = newParentNode->GetChildCount();
GURL newURL = [self GURLFromUrlField];
if (!newURL.is_valid()) {
// Shouldn't be reached -- OK button disabled if not valid!
@@ -350,114 +103,21 @@ int IndexOfFolderChild(const BookmarkNode* child_node) {
}
// Determine where the new/replacement bookmark is to go.
- const BookmarkNode* newParentNode = [self selectedNode];
- BookmarkModel* model = profile_->GetBookmarkModel();
- int newIndex = newParentNode->GetChildCount();
- if (node_ && parentNode_) {
+ const BookmarkNode* parentNode = [self parentNode];
+ if (node_ && parentNode) {
// Replace the old bookmark with the updated bookmark.
- int oldIndex = parentNode_->IndexOfChild(node_);
+ int oldIndex = parentNode->IndexOfChild(node_);
if (oldIndex >= 0)
- model->Remove(parentNode_, oldIndex);
- if (parentNode_ == newParentNode)
+ model->Remove(parentNode, oldIndex);
+ if (parentNode == newParentNode)
newIndex = oldIndex;
}
// Add bookmark as new node at the end of the newly selected folder.
const BookmarkNode* node = model->AddURL(newParentNode, newIndex,
newTitle, newURL);
// Honor handler semantics: callback on node creation.
- if (handler_.get())
- handler_->NodeCreated(node);
- [NSApp endSheet:[self window]];
-}
-
-- (IBAction)cancel:(id)sender {
- [NSApp endSheet:[self window]];
-}
-
-- (void)didEndSheet:(NSWindow*)sheet
- returnCode:(int)returnCode
- contextInfo:(void*)contextInfo {
- [sheet close];
-}
-
-#pragma mark For Unit Test Use Only
-
-- (NSString*)displayName {
- return [nameField_ stringValue];
-}
-
-- (NSString*)displayURL {
- return [urlField_ stringValue];
-}
-
-- (void)setDisplayName:(NSString*)name {
- [nameField_ setStringValue:name];
- [self controlTextDidChange:nil];
-}
-
-- (void)setDisplayURL:(NSString*)name {
- [urlField_ setStringValue:name];
- [self controlTextDidChange:nil];
-}
-
-- (BOOL)okButtonEnabled {
- return [okButton_ isEnabled];
-}
-
-- (void)selectTestNodeInBrowser:(const BookmarkNode*)node {
- [self selectNodeInBrowser:node];
-}
-
-#pragma mark NSBrowser delegate methods
-
-// Given a column number, determine the parent bookmark folder node for the
-// bookmarks being shown in that column. This is done by scanning forward
-// from column zero and following the selected row for each column up
-// to the parent of the desired column.
-- (const BookmarkNode*)parentNodeForColumn:(NSInteger)column {
- DCHECK(column >= 0);
- BookmarkModel* model = profile_->GetBookmarkModel();
- const BookmarkNode* node = model->root_node();
- for (NSInteger i = 0; i < column; ++i) {
- NSInteger selectedRowInColumn = [folderBrowser_ selectedRowInColumn:i];
- node = GetFolderChildForParent(node, selectedRowInColumn);
- }
- return node;
-}
-
-// This implementation returns the number of folders contained in the parent
-// folder node for this column.
-// TOTO(mrossetti): Decide if bookmark (i.e. non-folder) nodes should be
-// shown, perhaps in gray.
-- (NSInteger)browser:(NSBrowser*)sender numberOfRowsInColumn:(NSInteger)col {
- NSInteger rowCount = 0;
- const BookmarkNode* parentNode = [self parentNodeForColumn:col];
- if (parentNode) {
- int childCount = parentNode->GetChildCount();
- for (int i = 0; i < childCount; ++i) {
- const BookmarkNode* childNode = parentNode->GetChild(i);
- if (childNode->type() != BookmarkNode::URL)
- ++rowCount;
- }
- }
- return rowCount;
-}
-
-- (void)browser:(NSBrowser*)sender
- willDisplayCell:(NSBrowserCell*)cell
- atRow:(NSInteger)row
- column:(NSInteger)column {
- DCHECK(row >= 0); // Trust AppKit, but verify.
- DCHECK(column >= 0);
- DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]);
- const BookmarkNode* parentNode = [self parentNodeForColumn:column];
- const BookmarkNode* childNode = GetFolderChildForParent(parentNode, row);
- DCHECK(childNode);
- BookmarkTreeBrowserCell* browserCell =
- static_cast<BookmarkTreeBrowserCell*>(cell);
- [browserCell setTitle:base::SysWideToNSString(childNode->GetTitle())];
- [browserCell setBookmarkNode:childNode];
- [browserCell setMatrix:[folderBrowser_ matrixInColumn:column]];
+ [self NotifyHandlerCreatedNode:node];
+ [super ok:sender];
}
@end // BookmarkEditorController
diff --git a/chrome/browser/cocoa/bookmark_editor_controller_unittest.mm b/chrome/browser/cocoa/bookmark_editor_controller_unittest.mm
index e8d06d5..db340b1 100644
--- a/chrome/browser/cocoa/bookmark_editor_controller_unittest.mm
+++ b/chrome/browser/cocoa/bookmark_editor_controller_unittest.mm
@@ -183,9 +183,9 @@ class BookmarkEditorControllerTreeTest : public CocoaTest {
model.AddURL(group_bb_, 1, L"bb-1", GURL("http://bb-1.com"));
model.AddURL(group_bb_, 2, L"bb-2", GURL("http://bb-2.com"));
bookmark_bb_3_ =
- model.AddURL(group_bb_, 3, L"bb-3", GURL("http://bb-3.com"));
+ model.AddURL(group_bb_, 3, L"bb-3", GURL("http://bb-3.com"));
model.AddURL(group_bb_, 4, L"bb-4", GURL("http://bb-4.com"));
- model.AddURL(group_b_, 2, L"b-2", GURL("http://b-2.com"));
+ model.AddURL(group_b_, 2, L"b-1", GURL("http://b-2.com"));
model.AddURL(group_b_, 3, L"b-2", GURL("http://b-3.com"));
group_c_ = model.AddGroup(root, 2, L"c");
@@ -365,4 +365,3 @@ TEST_F(BookmarkEditorControllerTreeNoParentTest, AddFolderWithNoGroupSelected) {
const BookmarkNode* folderChild = bookmarkBar->GetChild(4);
EXPECT_EQ(folderChild->GetTitle(), L"New folder");
}
-
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 1ac1ef9..b45260d 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1054,6 +1054,8 @@
'browser/cocoa/browser_window_factory.mm',
'browser/cocoa/blocked_popup_container_controller.h',
'browser/cocoa/blocked_popup_container_controller.mm',
+ 'browser/cocoa/bookmark_all_tabs_controller.h',
+ 'browser/cocoa/bookmark_all_tabs_controller.mm',
'browser/cocoa/bookmark_bar_bridge.h',
'browser/cocoa/bookmark_bar_bridge.mm',
'browser/cocoa/bookmark_bar_constants.h',
@@ -1071,6 +1073,8 @@
'browser/cocoa/bookmark_bubble_window.mm',
'browser/cocoa/bookmark_button_cell.h',
'browser/cocoa/bookmark_button_cell.mm',
+ 'browser/cocoa/bookmark_editor_base_controller.h',
+ 'browser/cocoa/bookmark_editor_base_controller.mm',
'browser/cocoa/bookmark_editor_controller.h',
'browser/cocoa/bookmark_editor_controller.mm',
'browser/cocoa/bookmark_menu_bridge.h',
@@ -2642,6 +2646,7 @@
'xib_files_to_scan': [
# The xibs that need localization
'app/nibs/About.xib',
+ 'app/nibs/BookmarkAllTabs.xib',
'app/nibs/BookmarkBar.xib',
'app/nibs/BookmarkBubble.xib',
'app/nibs/BookmarkEditor.xib',
@@ -4514,6 +4519,7 @@
'browser/cocoa/background_gradient_view_unittest.mm',
'browser/cocoa/background_tile_view_unittest.mm',
'browser/cocoa/blocked_popup_container_controller_unittest.mm',
+ 'browser/cocoa/bookmark_all_tabs_controller_unittest.mm',
'browser/cocoa/bookmark_bar_bridge_unittest.mm',
'browser/cocoa/bookmark_bar_controller_unittest.mm',
'browser/cocoa/bookmark_bar_toolbar_view_unittest.mm',
@@ -4522,6 +4528,7 @@
'browser/cocoa/bookmark_bubble_view_unittest.mm',
'browser/cocoa/bookmark_bubble_window_unittest.mm',
'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_menu_bridge_unittest.mm',
'browser/cocoa/bookmark_menu_cocoa_controller_unittest.mm',
@@ -5709,6 +5716,7 @@
'app/framework-Info.plist',
'app/nibs/About.xib',
'app/nibs/AboutIPC.xib',
+ 'app/nibs/BookmarkAllTabs.xib',
'app/nibs/BookmarkBar.xib',
'app/nibs/BookmarkBubble.xib',
'app/nibs/BookmarkEditor.xib',