summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/nibs/BookmarkBubble.xib730
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller.mm4
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_controller.h98
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_controller.mm215
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_controller_unittest.mm213
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_view.h11
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_view.mm58
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_view_unittest.mm36
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_window.h11
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_window.mm33
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_window_unittest.mm27
-rw-r--r--chrome/browser/cocoa/bookmark_editor_controller.h3
-rw-r--r--chrome/browser/cocoa/bookmark_editor_controller.mm9
-rw-r--r--chrome/browser/cocoa/bookmark_name_folder_controller.h2
-rw-r--r--chrome/browser/cocoa/bookmark_name_folder_controller.mm2
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm3
-rw-r--r--chrome/browser/cocoa/browser_window_controller.h10
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm49
-rw-r--r--chrome/browser/cocoa/browser_window_controller_unittest.mm11
-rw-r--r--chrome/browser/cocoa/toolbar_controller.h4
-rw-r--r--chrome/browser/cocoa/toolbar_controller.mm6
-rw-r--r--chrome/browser/cocoa/toolbar_controller_unittest.mm9
-rw-r--r--chrome/chrome.gyp11
23 files changed, 1543 insertions, 12 deletions
diff --git a/chrome/app/nibs/BookmarkBubble.xib b/chrome/app/nibs/BookmarkBubble.xib
new file mode 100644
index 0000000..58d3215
--- /dev/null
+++ b/chrome/app/nibs/BookmarkBubble.xib
@@ -0,0 +1,730 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">9J61</string>
+ <string key="IBDocument.InterfaceBuilderVersion">677</string>
+ <string key="IBDocument.AppKitVersion">949.46</string>
+ <string key="IBDocument.HIToolboxVersion">353.00</string>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="1"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="1001">
+ <string key="NSClassName">BookmarkBubbleController</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="NSCustomView" id="1005">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">268</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSTextField" id="559397096">
+ <reference key="NSNextResponder" ref="1005"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{17, 113}, {244, 19}}</string>
+ <reference key="NSSuperview" ref="1005"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="368795405">
+ <int key="NSCellFlags">68288064</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents">^IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK</string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.600000e+01</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <reference key="NSControlView" ref="559397096"/>
+ <object class="NSColor" key="NSBackgroundColor" id="152587692">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlColor</string>
+ <object class="NSColor" key="NSColor" id="748407352">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor" id="1000275559">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlTextColor</string>
+ <object class="NSColor" key="NSColor" id="947148753">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSTextField" id="303910295">
+ <reference key="NSNextResponder" ref="1005"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{17, 87}, {65, 17}}</string>
+ <reference key="NSSuperview" ref="1005"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="628112279">
+ <int key="NSCellFlags">68288064</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents">^IDS_BOOMARK_BUBBLE_TITLE_TEXT</string>
+ <object class="NSFont" key="NSSupport" id="714614853">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.300000e+01</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <reference key="NSControlView" ref="303910295"/>
+ <reference key="NSBackgroundColor" ref="152587692"/>
+ <reference key="NSTextColor" ref="1000275559"/>
+ </object>
+ </object>
+ <object class="NSTextField" id="228609717">
+ <reference key="NSNextResponder" ref="1005"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{17, 62}, {65, 17}}</string>
+ <reference key="NSSuperview" ref="1005"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="295393049">
+ <int key="NSCellFlags">68288064</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents">^IDS_BOOMARK_BUBBLE_FOLDER_TEXT</string>
+ <reference key="NSSupport" ref="714614853"/>
+ <reference key="NSControlView" ref="228609717"/>
+ <reference key="NSBackgroundColor" ref="152587692"/>
+ <reference key="NSTextColor" ref="1000275559"/>
+ </object>
+ </object>
+ <object class="NSTextField" id="39428350">
+ <reference key="NSNextResponder" ref="1005"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{87, 85}, {267, 22}}</string>
+ <reference key="NSSuperview" ref="1005"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="905670292">
+ <int key="NSCellFlags">-1804468671</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents"/>
+ <reference key="NSSupport" ref="714614853"/>
+ <reference key="NSControlView" ref="39428350"/>
+ <bool key="NSDrawsBackground">YES</bool>
+ <object class="NSColor" key="NSBackgroundColor" id="1033293763">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textBackgroundColor</string>
+ <object class="NSColor" key="NSColor" id="660986653">
+ <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="947148753"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSComboBox" id="977232728">
+ <reference key="NSNextResponder" ref="1005"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{87, 56}, {270, 26}}</string>
+ <reference key="NSSuperview" ref="1005"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSComboBoxCell" key="NSCell" id="1003570867">
+ <int key="NSCellFlags">74579521</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents"/>
+ <reference key="NSSupport" ref="714614853"/>
+ <reference key="NSControlView" ref="977232728"/>
+ <bool key="NSDrawsBackground">YES</bool>
+ <reference key="NSBackgroundColor" ref="1033293763"/>
+ <reference key="NSTextColor" ref="1000275559"/>
+ <int key="NSVisibleItemCount">5</int>
+ <bool key="NSHasVerticalScroller">YES</bool>
+ <reference key="NSDelegate" ref="977232728"/>
+ <object class="NSComboTableView" key="NSTableView" id="1071628594">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrameSize">{15, 0}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSMutableArray" key="NSTableColumns">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSTableColumn">
+ <integer value="0" key="NSIdentifier"/>
+ <double key="NSWidth">1.200000e+01</double>
+ <double key="NSMinWidth">1.000000e+01</double>
+ <double key="NSMaxWidth">1.000000e+03</double>
+ <object class="NSTableHeaderCell" key="NSHeaderCell">
+ <int key="NSCellFlags">75628032</int>
+ <int key="NSCellFlags2">0</int>
+ <string key="NSContents"/>
+ <object class="NSFont" key="NSSupport" id="930683210">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.200000e+01</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+ </object>
+ <reference key="NSTextColor" ref="660986653"/>
+ </object>
+ <object class="NSTextFieldCell" key="NSDataCell">
+ <int key="NSCellFlags">338820672</int>
+ <int key="NSCellFlags2">1024</int>
+ <reference key="NSSupport" ref="714614853"/>
+ <reference key="NSControlView" ref="1071628594"/>
+ <bool key="NSDrawsBackground">YES</bool>
+ <object class="NSColor" key="NSBackgroundColor" id="744868739">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlBackgroundColor</string>
+ <reference key="NSColor" ref="748407352"/>
+ </object>
+ <reference key="NSTextColor" ref="1000275559"/>
+ </object>
+ <int key="NSResizingMask">3</int>
+ <bool key="NSIsResizeable">YES</bool>
+ <reference key="NSTableView" ref="1071628594"/>
+ </object>
+ </object>
+ <double key="NSIntercellSpacingWidth">3.000000e+00</double>
+ <double key="NSIntercellSpacingHeight">2.000000e+00</double>
+ <reference key="NSBackgroundColor" ref="744868739"/>
+ <object class="NSColor" key="NSGridColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">gridColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC41AA</bytes>
+ </object>
+ </object>
+ <double key="NSRowHeight">1.900000e+01</double>
+ <string key="NSAction">tableViewAction:</string>
+ <int key="NSTvFlags">-767524864</int>
+ <reference key="NSDelegate" ref="1003570867"/>
+ <reference key="NSDataSource" ref="1003570867"/>
+ <reference key="NSTarget" ref="1003570867"/>
+ <int key="NSColumnAutoresizingStyle">1</int>
+ <int key="NSDraggingSourceMaskForLocal">15</int>
+ <int key="NSDraggingSourceMaskForNonLocal">0</int>
+ <bool key="NSAllowsTypeSelect">YES</bool>
+ </object>
+ </object>
+ </object>
+ <object class="NSButton" id="430629007">
+ <reference key="NSNextResponder" ref="1005"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{168, 12}, {96, 32}}</string>
+ <reference key="NSSuperview" ref="1005"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="562929863">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">^IDS_BOOMARK_BUBBLE_OPTIONS</string>
+ <reference key="NSSupport" ref="714614853"/>
+ <reference key="NSControlView" ref="430629007"/>
+ <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 class="NSButton" id="82356437">
+ <reference key="NSNextResponder" ref="1005"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{264, 12}, {96, 32}}</string>
+ <reference key="NSSuperview" ref="1005"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="307931553">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">^IDS_CLOSE</string>
+ <reference key="NSSupport" ref="714614853"/>
+ <reference key="NSControlView" ref="82356437"/>
+ <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="177936093">
+ <reference key="NSNextResponder" ref="1005"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{270, 113}, {84, 19}}</string>
+ <reference key="NSSuperview" ref="1005"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="1066753170">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">^IDS_BOOMARK_BUBBLE_REMOVE_BOOKMARK</string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.200000e+01</double>
+ <int key="NSfFlags">4883</int>
+ </object>
+ <reference key="NSControlView" ref="177936093"/>
+ <int key="NSButtonFlags">-2038021889</int>
+ <int key="NSButtonFlags2">164</int>
+ <reference key="NSAlternateImage" ref="930683210"/>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">400</int>
+ <int key="NSPeriodicInterval">75</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{374, 152}</string>
+ <reference key="NSSuperview"/>
+ <string key="NSClassName">BookmarkBubbleView</string>
+ </object>
+ <object class="NSCustomObject" id="704223344">
+ <string key="NSClassName">ChromeUILocalizer</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="977232728"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">23</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">remove:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="177936093"/>
+ </object>
+ <int key="connectionID">24</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">edit:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="430629007"/>
+ </object>
+ <int key="connectionID">25</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">close:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="82356437"/>
+ </object>
+ <int key="connectionID">26</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">bigTitle_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="559397096"/>
+ </object>
+ <int key="connectionID">28</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">nameTextField_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="39428350"/>
+ </object>
+ <int key="connectionID">29</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">30</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">owner_</string>
+ <reference key="source" ref="704223344"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">32</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">folderComboBox_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="977232728"/>
+ </object>
+ <int key="connectionID">33</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="228609717"/>
+ <reference ref="39428350"/>
+ <reference ref="977232728"/>
+ <reference ref="82356437"/>
+ <reference ref="303910295"/>
+ <reference ref="559397096"/>
+ <reference ref="430629007"/>
+ <reference ref="177936093"/>
+ </object>
+ <reference key="parent" ref="1002"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="559397096"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="368795405"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="368795405"/>
+ <reference key="parent" ref="559397096"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">8</int>
+ <reference key="object" ref="303910295"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="628112279"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="628112279"/>
+ <reference key="parent" ref="303910295"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">10</int>
+ <reference key="object" ref="228609717"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="295393049"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">11</int>
+ <reference key="object" ref="295393049"/>
+ <reference key="parent" ref="228609717"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">12</int>
+ <reference key="object" ref="39428350"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="905670292"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">13</int>
+ <reference key="object" ref="905670292"/>
+ <reference key="parent" ref="39428350"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">14</int>
+ <reference key="object" ref="977232728"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1003570867"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">15</int>
+ <reference key="object" ref="1003570867"/>
+ <reference key="parent" ref="977232728"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">16</int>
+ <reference key="object" ref="430629007"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="562929863"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">17</int>
+ <reference key="object" ref="562929863"/>
+ <reference key="parent" ref="430629007"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">18</int>
+ <reference key="object" ref="82356437"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="307931553"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">19</int>
+ <reference key="object" ref="307931553"/>
+ <reference key="parent" ref="82356437"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">20</int>
+ <reference key="object" ref="177936093"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1066753170"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">21</int>
+ <reference key="object" ref="1066753170"/>
+ <reference key="parent" ref="177936093"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">31</int>
+ <reference key="object" ref="704223344"/>
+ <reference key="parent" ref="1002"/>
+ </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.WindowOrigin</string>
+ <string>1.editorWindowContentRectSynchronizationRect</string>
+ <string>10.IBPluginDependency</string>
+ <string>11.IBPluginDependency</string>
+ <string>12.IBPluginDependency</string>
+ <string>13.IBPluginDependency</string>
+ <string>14.IBPluginDependency</string>
+ <string>15.IBPluginDependency</string>
+ <string>16.IBPluginDependency</string>
+ <string>17.IBPluginDependency</string>
+ <string>18.IBPluginDependency</string>
+ <string>19.IBPluginDependency</string>
+ <string>2.IBPluginDependency</string>
+ <string>20.IBPluginDependency</string>
+ <string>21.IBPluginDependency</string>
+ <string>3.IBPluginDependency</string>
+ <string>31.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>{{553, 1288}, {374, 152}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{628, 654}</string>
+ <string>{{357, 416}, {480, 272}}</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>
+ <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">33</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">BookmarkBubbleController</string>
+ <string key="superclassName">NSViewController</string>
+ <object class="NSMutableDictionary" key="actions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>close:</string>
+ <string>edit:</string>
+ <string>remove:</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>bigTitle_</string>
+ <string>delegate_</string>
+ <string>folderComboBox_</string>
+ <string>nameTextField_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSTextField</string>
+ <string>id</string>
+ <string>NSComboBox</string>
+ <string>NSTextField</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/bookmark_bubble_controller.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">BookmarkBubbleView</string>
+ <string key="superclassName">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/bookmark_bubble_view.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">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>
+ </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/browser/cocoa/bookmark_bar_controller.mm b/chrome/browser/cocoa/bookmark_bar_controller.mm
index 1f64cf4..75e3441 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller.mm
+++ b/chrome/browser/cocoa/bookmark_bar_controller.mm
@@ -411,9 +411,9 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
initWithParentWindow:[[self view] window]
profile:profile_
node:node];
- [controller runModal];
+ [controller runAsModalSheet];
- // runModal will run the window as a sheet. The
+ // runAsModalSheet will run the window as a sheet. The
// BookmarkNameFolderController will release itself when the sheet
// ends.
}
diff --git a/chrome/browser/cocoa/bookmark_bubble_controller.h b/chrome/browser/cocoa/bookmark_bubble_controller.h
new file mode 100644
index 0000000..0760fa0
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_controller.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+#include "base/scoped_nsobject.h"
+
+class BookmarkModel;
+class BookmarkNode;
+@class BookmarkBubbleController;
+
+// Protocol for a BookmarkBubbleController's (BBC's) delegate.
+@protocol BookmarkBubbleControllerDelegate
+
+// The bubble asks the delegate to perform an edit when needed.
+- (void)editBookmarkNode:(const BookmarkNode*)node;
+
+// The bubble tells its delegate when it's done and can be deallocated.
+- (void)doneWithBubbleController:(BookmarkBubbleController*)controller;
+
+@end
+
+// Controller for the bookmark bubble. The bookmark bubble is a
+// bubble that pops up when clicking on the STAR next to the URL to
+// add or remove it as a bookmark. This bubble allows for editing of
+// the bookmark in various ways (name, folder, etc.)
+//
+// The bubble is stored in a nib as a view, not as a window, so we can
+// make it an actual bubble. There is no nib-rific way to encode a
+// NSBorderlessWindowMask NSWindow, and the style of an NSWindow can't
+// be set other than init time. To deal, we create the NSWindow
+// programatically, but encode the view in a nib. Thus,
+// BookmarkBubbleController is an NSViewController, not an
+// NSWindowController.
+@interface BookmarkBubbleController : NSViewController {
+ @private
+ // Unexpected for this controller, perhaps, but our window does NOT
+ // come from a nib.
+ scoped_nsobject<NSWindow> window_;
+
+ id<BookmarkBubbleControllerDelegate> delegate_; // weak like other delegates
+ NSWindow* parentWindow_; // weak
+ NSPoint topLeftForBubble_;
+
+ // Both weak; owned by the current browser's profile
+ BookmarkModel* model_;
+ const BookmarkNode* node_;
+
+ // A mapping from titles to nodes so we only have to walk this once.
+ scoped_nsobject<NSMutableArray> titleMapping_;
+
+ BOOL alreadyBookmarked_;
+ scoped_nsobject<NSString> chooseAnotherFolder_;
+
+ IBOutlet NSTextField* bigTitle_; // "Bookmark" or "Bookmark Added!"
+ IBOutlet NSTextField* nameTextField_;
+ IBOutlet NSComboBox* folderComboBox_;
+}
+
+// |node| is the bookmark node we edit in this bubble.
+// |alreadyBookmarked| tells us if the node was bookmarked before the
+// user clicked on the star. (if NO, this is a brand new bookmark).
+// The owner of this object is responsible for showing the bubble if
+// it desires it to be visible on the screen. It is not shown by the
+// init routine. Closing of the window happens implicitly on dealloc.
+- (id)initWithDelegate:(id<BookmarkBubbleControllerDelegate>)delegate
+ parentWindow:(NSWindow*)parentWindow
+ topLeftForBubble:(NSPoint)topLeftForBubble
+ model:(BookmarkModel*)model
+ node:(const BookmarkNode*)node
+ alreadyBookmarked:(BOOL)alreadyBookmarked;
+
+- (void)showWindow;
+
+// Actions for buttons in the dialog.
+- (IBAction)edit:(id)sender;
+- (IBAction)close:(id)sender;
+- (IBAction)remove:(id)sender;
+
+@end
+
+
+// Exposed only for unit testing.
+@interface BookmarkBubbleController(ExposedForUnitTesting)
+- (NSWindow*)createBubbleWindow;
+- (void)fillInFolderList;
+- (BOOL)windowHasBeenClosed;
+- (void)addFolderNodes:(const BookmarkNode*)parent toComboBox:(NSComboBox*)box;
+- (void)updateBookmarkNode;
+- (void)setTitle:(NSString *)title parentFolder:(NSString*)folder;
+- (NSString*)chooseAnotherFolderString;
+@end
+
+// Also private but I need to declare them specially for @synthesize to work.
+@interface BookmarkBubbleController ()
+@property (readonly) id delegate;
+@property (readonly) NSComboBox* folderComboBox;
+@end
diff --git a/chrome/browser/cocoa/bookmark_bubble_controller.mm b/chrome/browser/cocoa/bookmark_bubble_controller.mm
new file mode 100644
index 0000000..7e9b1e2
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_controller.mm
@@ -0,0 +1,215 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "app/l10n_util_mac.h"
+#include "base/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#import "chrome/browser/cocoa/bookmark_bubble_controller.h"
+#import "chrome/browser/cocoa/bookmark_bubble_window.h"
+#include "grit/generated_resources.h"
+
+
+@interface BookmarkBubbleController(PrivateAPI)
+- (void)closeWindow;
+@end
+
+@implementation BookmarkBubbleController
+
+@synthesize delegate = delegate_;
+@synthesize folderComboBox = folderComboBox_;
+
+- (id)initWithDelegate:(id<BookmarkBubbleControllerDelegate>)delegate
+ parentWindow:(NSWindow*)parentWindow
+ topLeftForBubble:(NSPoint)topLeftForBubble
+ model:(BookmarkModel*)model
+ node:(const BookmarkNode*)node
+ alreadyBookmarked:(BOOL)alreadyBookmarked {
+ if ((self = [super initWithNibName:@"BookmarkBubble"
+ bundle:mac_util::MainAppBundle()])) {
+ // all these are weak...
+ delegate_ = delegate;
+ parentWindow_ = parentWindow;
+ topLeftForBubble_ = topLeftForBubble;
+ model_ = model;
+ node_ = node;
+ alreadyBookmarked_ = alreadyBookmarked;
+ // But this is strong.
+ titleMapping_.reset([[NSMutableDictionary alloc] init]);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self closeWindow];
+ [super dealloc];
+}
+
+- (void)showWindow {
+ [self view]; // force nib load and window_ allocation
+ [window_ makeKeyAndOrderFront:self];
+}
+
+// Actually close the window. Do nothing else.
+- (void)closeWindow {
+ [parentWindow_ removeChildWindow:window_];
+ [window_ close];
+}
+
+- (void)awakeFromNib {
+ window_.reset([self createBubbleWindow]);
+ [parentWindow_ addChildWindow:window_ ordered:NSWindowAbove];
+
+ // Fill in inital values for text, controls, ...
+
+ // Default is IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK; "Bookmark".
+ // If adding for the 1st time the string becomes "Bookmark Added!"
+ if (!alreadyBookmarked_) {
+ NSString* title =
+ l10n_util::GetNSString(IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED);
+ [bigTitle_ setStringValue:title];
+ }
+
+ [self fillInFolderList];
+}
+
+- (IBAction)edit:(id)sender {
+ [self updateBookmarkNode];
+ [self closeWindow];
+ [delegate_ editBookmarkNode:node_];
+ [delegate_ doneWithBubbleController:self];
+}
+
+- (IBAction)close:(id)sender {
+ if (node_) {
+ // no node_ if the bookmark was just removed
+ [self updateBookmarkNode];
+ }
+ [self closeWindow];
+ [delegate_ doneWithBubbleController:self];
+}
+
+// By implementing this, ESC causes the window to go away.
+- (IBAction)cancel:(id)sender {
+ [self close:sender];
+}
+
+- (IBAction)remove:(id)sender {
+ model_->SetURLStarred(node_->GetURL(), node_->GetTitle(), false);
+ node_ = NULL; // no longer valid
+ [self close:self];
+}
+
+// We are the delegate of the combo box so we can tell when "choose
+// another folder" was picked.
+- (void)comboBoxSelectionDidChange:(NSNotification*)notification {
+ NSString* selected = [folderComboBox_ objectValueOfSelectedItem];
+ if ([selected isEqual:chooseAnotherFolder_.get()]) {
+ [self edit:self];
+ }
+}
+
+// We are the delegate of our own window so we know when we lose key.
+// When we lose key status we close, mirroring Windows behaivor.
+- (void)windowDidResignKey:(NSNotification*)notification {
+ if ([window_ isVisible])
+ [self close:self];
+}
+
+@end // BookmarkBubbleController
+
+
+@implementation BookmarkBubbleController(ExposedForUnitTesting)
+
+// Create and return a retained NSWindow for this bubble.
+- (NSWindow*)createBubbleWindow {
+ NSRect contentRect = [[self view] frame];
+ NSPoint origin = topLeftForBubble_;
+ origin.y -= contentRect.size.height; // since it'll be our bottom-left
+ contentRect.origin = origin;
+ // Now convert to global coordinates since it'll be used for a window.
+ contentRect.origin = [parentWindow_ convertBaseToScreen:contentRect.origin];
+ NSWindow* window = [[BookmarkBubbleWindow alloc]
+ initWithContentRect:contentRect];
+ [window setDelegate:self];
+ [window setContentView:[self view]];
+ return window;
+}
+
+// Fill in all information related to the folder combo box.
+//
+// TODO(jrg): make sure nested folders that have the same name are
+// handled properly.
+// http://crbug.com/19408
+- (void)fillInFolderList {
+ [nameTextField_ setStringValue:base::SysWideToNSString(node_->GetTitle())];
+ [self addFolderNodes:model_->root_node() toComboBox:folderComboBox_];
+
+ // Add "Choose another folder...". Remember it for later to compare against.
+ chooseAnotherFolder_.reset(
+ [l10n_util::GetNSString(IDS_BOOMARK_BUBBLE_CHOOSER_ANOTHER_FOLDER)
+ retain]);
+ [folderComboBox_ addItemWithObjectValue:chooseAnotherFolder_.get()];
+
+ // Finally, select the current parent.
+ NSString* parentTitle = base::SysWideToNSString(
+ node_->GetParent()->GetTitle());
+ [folderComboBox_ selectItemWithObjectValue:parentTitle];
+}
+
+- (BOOL)windowHasBeenClosed {
+ return ![window_ isVisible];
+}
+
+// For the given folder node, walk the tree and add folder names to
+// the given combo box.
+//
+// TODO(jrg): no distinction is made among folders with the same name.
+- (void)addFolderNodes:(const BookmarkNode*)parent toComboBox:(NSComboBox*)box {
+ NSString* title = base::SysWideToNSString(parent->GetTitle());
+ if ([title length]) { // no title if root
+ [box addItemWithObjectValue:title];
+ [titleMapping_ setValue:[NSValue valueWithPointer:parent] forKey:title];
+ }
+ for (int i = 0; i < parent->GetChildCount(); i++) {
+ const BookmarkNode* child = parent->GetChild(i);
+ if (child->is_folder())
+ [self addFolderNodes:child toComboBox:box];
+ }
+}
+
+// Look at the dialog; if the user has changed anything, update the
+// bookmark node to reflect this.
+- (void)updateBookmarkNode {
+ // First the title...
+ NSString* oldTitle = base::SysWideToNSString(node_->GetTitle());
+ NSString* newTitle = [nameTextField_ stringValue];
+ if (![oldTitle isEqual:newTitle]) {
+ model_->SetTitle(node_, base::SysNSStringToWide(newTitle));
+ }
+ // Then the parent folder.
+ NSString* oldParentTitle = base::SysWideToNSString(
+ node_->GetParent()->GetTitle());
+ NSString* newParentTitle = [folderComboBox_ objectValueOfSelectedItem];
+ if (![oldParentTitle isEqual:newParentTitle]) {
+ const BookmarkNode* newParent = static_cast<const BookmarkNode*>(
+ [[titleMapping_ objectForKey:newParentTitle] pointerValue]);
+ if (newParent) {
+ // newParent should only ever possibly be NULL in a unit test.
+ int index = newParent->GetChildCount();
+ model_->Move(node_, newParent, index);
+ }
+ }
+}
+
+- (void)setTitle:(NSString*)title parentFolder:(NSString*)folder {
+ [nameTextField_ setStringValue:title];
+ [folderComboBox_ selectItemWithObjectValue:folder];
+}
+
+- (NSString*)chooseAnotherFolderString {
+ return chooseAnotherFolder_.get();
+}
+
+@end // implementation BookmarkBubbleController(ExposedForUnitTesting)
diff --git a/chrome/browser/cocoa/bookmark_bubble_controller_unittest.mm b/chrome/browser/cocoa/bookmark_bubble_controller_unittest.mm
new file mode 100644
index 0000000..2e741c0
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_controller_unittest.mm
@@ -0,0 +1,213 @@
+// 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/basictypes.h"
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/cocoa/bookmark_bubble_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 BBDelegate : NSObject<BookmarkBubbleControllerDelegate> {
+ NSWindow* window_; // weak
+ int edits_;
+ int dones_;
+}
+@property (readonly) int edits;
+@property (readonly) int dones;
+@property (readonly) NSWindow* window;
+@end
+
+@implementation BBDelegate
+
+@synthesize edits = edits_;
+@synthesize window = window_;
+@synthesize dones = dones_;
+
+- (NSPoint)topLeftForBubble {
+ return NSMakePoint(10, 300);
+}
+
+- (void)editBookmarkNode:(const BookmarkNode*)node {
+ edits_++;
+}
+
+- (void)doneWithBubbleController:(BookmarkBubbleController*)controller {
+ dones_++;
+}
+
+- (void)clear {
+ edits_ = 0;
+ dones_ = 0;
+}
+
+@end
+
+namespace {
+
+class BookmarkBubbleControllerTest : public PlatformTest {
+ public:
+ CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc...
+ BrowserTestHelper helper_;
+ scoped_nsobject<BBDelegate> delegate_;
+ scoped_nsobject<BookmarkBubbleController> controller_;
+
+ BookmarkBubbleControllerTest() {
+ delegate_.reset([[BBDelegate alloc] init]);
+ }
+
+ // Returns a controller but ownership not transferred.
+ // Only one of these will be valid at a time.
+ BookmarkBubbleController* ControllerForNode(const BookmarkNode* node) {
+ controller_.reset([[BookmarkBubbleController alloc]
+ initWithDelegate:delegate_.get()
+ parentWindow:cocoa_helper_.window()
+ topLeftForBubble:[delegate_ topLeftForBubble]
+ model:helper_.profile()->GetBookmarkModel()
+ node:node
+ alreadyBookmarked:YES]);
+ [controller_ view]; // force nib load
+ return controller_.get();
+ }
+
+ BookmarkModel* GetBookmarkModel() {
+ return helper_.profile()->GetBookmarkModel();
+ }
+};
+
+// Confirm basics about the bubble window (e.g. that it is inside the
+// parent window)
+TEST_F(BookmarkBubbleControllerTest, TestBubbleWindow) {
+ BookmarkModel* model = GetBookmarkModel();
+ const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(),
+ 0,
+ L"Bookie markie title",
+ GURL("http://www.google.com"));
+ BookmarkBubbleController* controller = ControllerForNode(node);
+ EXPECT_TRUE(controller);
+ NSWindow* window = [controller createBubbleWindow];
+ EXPECT_TRUE(window);
+ EXPECT_TRUE(NSContainsRect([cocoa_helper_.window() frame],
+ [window frame]));
+}
+
+// Confirm population of folder list
+TEST_F(BookmarkBubbleControllerTest, TestFillInFolder) {
+ // Create some folders, including a nested folder
+ BookmarkModel* model = GetBookmarkModel();
+ const BookmarkNode* node1 = model->AddGroup(model->GetBookmarkBarNode(),
+ 0, L"one");
+ const BookmarkNode* node2 = model->AddGroup(model->GetBookmarkBarNode(),
+ 1, L"two");
+ const BookmarkNode* node3 = model->AddGroup(model->GetBookmarkBarNode(),
+ 2, L"three");
+ const BookmarkNode* node4 = model->AddGroup(node2,
+ 0, L"sub");
+ model->AddURL(node1, 0, L"title1", GURL("http://www.google.com"));
+ model->AddURL(node3, 0, L"title2", GURL("http://www.google.com"));
+ model->AddURL(node4, 0, L"title3", GURL("http://www.google.com/reader"));
+
+ BookmarkBubbleController* controller = ControllerForNode(node4);
+ EXPECT_TRUE(controller);
+
+ NSArray* items = [[controller folderComboBox] objectValues];
+ EXPECT_TRUE([items containsObject:@"one"]);
+ EXPECT_TRUE([items containsObject:@"two"]);
+ EXPECT_TRUE([items containsObject:@"three"]);
+ EXPECT_TRUE([items containsObject:@"sub"]);
+ EXPECT_FALSE([items containsObject:@"title1"]);
+ EXPECT_FALSE([items containsObject:@"title2"]);
+}
+
+// Click on edit; bubble gets closed.
+TEST_F(BookmarkBubbleControllerTest, TestSimpleActions) {
+ BookmarkModel* model = GetBookmarkModel();
+ const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(),
+ 0,
+ L"Bookie markie title",
+ GURL("http://www.google.com"));
+ BookmarkBubbleController* controller = ControllerForNode(node);
+ EXPECT_TRUE(controller);
+
+ EXPECT_EQ([delegate_ edits], 0);
+ EXPECT_EQ([delegate_ dones], 0);
+ EXPECT_FALSE([controller windowHasBeenClosed]);
+ [controller edit:controller];
+ EXPECT_EQ([delegate_ edits], 1);
+ EXPECT_EQ([delegate_ dones], 1);
+ EXPECT_TRUE([controller windowHasBeenClosed]);
+
+ [delegate_ clear];
+ EXPECT_EQ([delegate_ edits], 0);
+ EXPECT_EQ([delegate_ dones], 0);
+
+ controller = ControllerForNode(node);
+ EXPECT_TRUE(controller);
+ EXPECT_FALSE([controller windowHasBeenClosed]);
+ [controller close:controller];
+ EXPECT_EQ([delegate_ edits], 0);
+ EXPECT_EQ([delegate_ dones], 1);
+ EXPECT_TRUE([controller windowHasBeenClosed]);
+}
+
+// User changes title and parent folder in the UI
+TEST_F(BookmarkBubbleControllerTest, TestUserEdit) {
+ BookmarkModel* model = GetBookmarkModel();
+ const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(),
+ 0,
+ L"short-title",
+ GURL("http://www.google.com"));
+ model->AddGroup(model->GetBookmarkBarNode(), 0, L"grandma");
+ model->AddGroup(model->GetBookmarkBarNode(), 0, L"grandpa");
+ BookmarkBubbleController* controller = ControllerForNode(node);
+ EXPECT_TRUE(controller);
+
+ // simulate a user edit
+ [controller setTitle:@"oops" parentFolder:@"grandma"];
+ [controller edit:controller];
+
+ // Make sure bookmark has changed
+ EXPECT_EQ(node->GetTitle(), L"oops");
+ EXPECT_EQ(node->GetParent()->GetTitle(), L"grandma");
+}
+
+// Click the "remove" button
+TEST_F(BookmarkBubbleControllerTest, TestRemove) {
+ BookmarkModel* model = GetBookmarkModel();
+ GURL gurl("http://www.google.com");
+ const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(),
+ 0,
+ L"Bookie markie title",
+ gurl);
+ BookmarkBubbleController* controller = ControllerForNode(node);
+ EXPECT_TRUE(controller);
+ EXPECT_TRUE(model->IsBookmarked(gurl));
+
+ [controller remove:controller];
+ EXPECT_FALSE(model->IsBookmarked(gurl));
+ EXPECT_TRUE([controller windowHasBeenClosed]);
+ EXPECT_EQ([delegate_ dones], 1);
+}
+
+// Confirm picking "choose another folder" caused edit: to be called.
+TEST_F(BookmarkBubbleControllerTest, ComboSelectionChanged) {
+ BookmarkModel* model = GetBookmarkModel();
+ GURL gurl("http://www.google.com");
+ const BookmarkNode* node = model->AddURL(model->GetBookmarkBarNode(),
+ 0, L"super-title",
+ gurl);
+ BookmarkBubbleController* controller = ControllerForNode(node);
+ EXPECT_TRUE(controller);
+
+ NSString* chooseAnotherFolder = [controller chooseAnotherFolderString];
+ EXPECT_EQ([delegate_ edits], 0);
+ [controller setTitle:@"DOH!" parentFolder:chooseAnotherFolder];
+ EXPECT_EQ([delegate_ edits], 1);
+}
+
+
+} // namespace
diff --git a/chrome/browser/cocoa/bookmark_bubble_view.h b/chrome/browser/cocoa/bookmark_bubble_view.h
new file mode 100644
index 0000000..1e811a8
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_view.h
@@ -0,0 +1,11 @@
+// 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>
+
+// Content view for a Bookmark Bubble opened by clicking on the star
+// toolbar button. This is where nonrectangular drawing happens.
+@interface BookmarkBubbleView : NSView
+@end
+
diff --git a/chrome/browser/cocoa/bookmark_bubble_view.mm b/chrome/browser/cocoa/bookmark_bubble_view.mm
new file mode 100644
index 0000000..b4c5c7e56
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_view.mm
@@ -0,0 +1,58 @@
+// 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_bubble_view.h"
+#import "third_party/GTM/AppKit/GTMTheme.h"
+
+namespace {
+// TODO(jrg): confirm constants with UI dudes
+const CGFloat kBubbleCornerRadius = 8.0;
+const CGFloat kBubbleArrowXOffset = 10.0;
+const CGFloat kBubbleArrowWidth = 15.0;
+const CGFloat kBubbleArrowHeight = 8.0;
+const CGFloat kBubbleBorderLineWidth = 1.0;
+}
+
+@implementation BookmarkBubbleView
+
+- (void)drawRect:(NSRect)rect {
+ // Make room for the border to be seen.
+ NSRect bounds = [self bounds];
+ bounds.size.height -= kBubbleArrowHeight;
+ bounds = NSInsetRect(bounds,
+ kBubbleBorderLineWidth/2.0,
+ kBubbleBorderLineWidth/2.0);
+
+ NSBezierPath* bezier = [NSBezierPath bezierPath];
+ rect.size.height -= kBubbleArrowHeight;
+
+ // Start with a rounded rectangle.
+ [bezier appendBezierPathWithRoundedRect:bounds
+ xRadius:kBubbleCornerRadius
+ yRadius:kBubbleCornerRadius];
+
+ // Add the bubble arrow (pointed at the star).
+ NSPoint arrowStart = NSMakePoint(NSMinX(bounds), NSMaxY(bounds));
+ arrowStart.x += kBubbleArrowXOffset;
+ [bezier moveToPoint:NSMakePoint(arrowStart.x, arrowStart.y)];
+ [bezier lineToPoint:NSMakePoint(arrowStart.x + kBubbleArrowWidth/2.0,
+ arrowStart.y + kBubbleArrowHeight)];
+ [bezier lineToPoint:NSMakePoint(arrowStart.x + kBubbleArrowWidth,
+ arrowStart.y)];
+ [bezier closePath];
+
+ // Draw the outline...
+ [[NSColor blackColor] set];
+ [bezier setLineWidth:kBubbleBorderLineWidth];
+ [bezier stroke];
+
+ // Then fill the inside.
+ GTMTheme *theme = [GTMTheme defaultTheme];
+ NSGradient *gradient = [theme gradientForStyle:GTMThemeStyleToolBar
+ state:NO];
+ [gradient drawInBezierPath:bezier angle:0.0];
+}
+
+@end
+
diff --git a/chrome/browser/cocoa/bookmark_bubble_view_unittest.mm b/chrome/browser/cocoa/bookmark_bubble_view_unittest.mm
new file mode 100644
index 0000000..9744397
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_view_unittest.mm
@@ -0,0 +1,36 @@
+// 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"
+#import "chrome/browser/cocoa/bookmark_bubble_view.h"
+#import "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class BookmarkBubbleViewTest : public PlatformTest {
+ public:
+ BookmarkBubbleViewTest() {
+ NSRect frame = NSMakeRect(0, 0, 100, 30);
+ view_.reset([[BookmarkBubbleView alloc] initWithFrame:frame]);
+ [cocoa_helper_.contentView() addSubview:view_.get()];
+ }
+
+ CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc...
+ scoped_nsobject<BookmarkBubbleView> view_;
+};
+
+// Test drawing and an add/remove from the view hierarchy to ensure
+// nothing leaks or crashes.
+TEST_F(BookmarkBubbleViewTest, AddRemoveDisplay) {
+ [view_ display];
+ EXPECT_EQ(cocoa_helper_.contentView(), [view_ superview]);
+ [view_.get() removeFromSuperview];
+ EXPECT_FALSE([view_ superview]);
+}
+
+} // namespace
diff --git a/chrome/browser/cocoa/bookmark_bubble_window.h b/chrome/browser/cocoa/bookmark_bubble_window.h
new file mode 100644
index 0000000..45e2f3b
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_window.h
@@ -0,0 +1,11 @@
+// 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>
+
+// Window for the bookmark bubble that comes up when you click on "STAR".
+@interface BookmarkBubbleWindow : NSWindow
+- (id)initWithContentRect:(NSRect)contentRect;
+@end
+
diff --git a/chrome/browser/cocoa/bookmark_bubble_window.mm b/chrome/browser/cocoa/bookmark_bubble_window.mm
new file mode 100644
index 0000000..126b30e
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_window.mm
@@ -0,0 +1,33 @@
+// 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_bubble_window.h"
+
+@implementation BookmarkBubbleWindow
+
+- (id)initWithContentRect:(NSRect)contentRect {
+ if ((self = [super initWithContentRect:contentRect
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES])) {
+ [self setReleasedWhenClosed:NO];
+ [self setBackgroundColor:[NSColor clearColor]];
+ [self setExcludedFromWindowsMenu:YES];
+ [self setAlphaValue:1.0];
+ [self setOpaque:NO];
+ }
+ return self;
+}
+
+// According to
+// http://www.cocoabuilder.com/archive/message/cocoa/2006/6/19/165953,
+// NSBorderlessWindowMask windows cannot become key or main. In our
+// case, however, we don't want all of that behavior. (As an example,
+// our bubble has buttons!)
+
+- (BOOL)canBecomeKeyWindow {
+ return YES;
+}
+
+@end
diff --git a/chrome/browser/cocoa/bookmark_bubble_window_unittest.mm b/chrome/browser/cocoa/bookmark_bubble_window_unittest.mm
new file mode 100644
index 0000000..08baec4
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bubble_window_unittest.mm
@@ -0,0 +1,27 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/cocoa/bookmark_bubble_window.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class BookmarkBubbleWindowTest : public testing::Test {
+ public:
+ CocoaTestHelper cocoa_helper_;
+};
+
+TEST_F(BookmarkBubbleWindowTest, Basics) {
+ scoped_nsobject<BookmarkBubbleWindow> window_;
+ window_.reset([[BookmarkBubbleWindow alloc]
+ initWithContentRect:NSMakeRect(0,0,10,10)]);
+
+ EXPECT_TRUE([window_ canBecomeKeyWindow]);
+ EXPECT_FALSE([window_ canBecomeMainWindow]);
+
+ EXPECT_TRUE([window_ isExcludedFromWindowsMenu]);
+ EXPECT_FALSE([window_ isReleasedWhenClosed]);
+}
+
+
diff --git a/chrome/browser/cocoa/bookmark_editor_controller.h b/chrome/browser/cocoa/bookmark_editor_controller.h
index 742fbd1..4c80161 100644
--- a/chrome/browser/cocoa/bookmark_editor_controller.h
+++ b/chrome/browser/cocoa/bookmark_editor_controller.h
@@ -39,6 +39,9 @@
configuration:(BookmarkEditor::Configuration)configuration
handler:(BookmarkEditor::Handler*)handler;
+// Run the bookmark editor as a modal sheet. Does not block.
+- (void)runAsModalSheet;
+
// Actions for the buttons at the bottom of the window.
- (IBAction)newFolder:(id)sender;
- (IBAction)cancel:(id)sender;
diff --git a/chrome/browser/cocoa/bookmark_editor_controller.mm b/chrome/browser/cocoa/bookmark_editor_controller.mm
index 4ba0ab39..79cd1dc 100644
--- a/chrome/browser/cocoa/bookmark_editor_controller.mm
+++ b/chrome/browser/cocoa/bookmark_editor_controller.mm
@@ -10,11 +10,6 @@
#include "chrome/browser/profile.h"
#import "chrome/browser/cocoa/bookmark_editor_controller.h"
-@interface BookmarkEditorController(Private)
-// Run the bookmark editor as a modal sheet. Does not block.
-- (void)runModal;
-@end
-
// static; implemented for each platform.
void BookmarkEditor::Show(gfx::NativeView parent_hwnd,
Profile* profile,
@@ -30,7 +25,7 @@ void BookmarkEditor::Show(gfx::NativeView parent_hwnd,
node:node
configuration:configuration
handler:handler];
- [controller runModal];
+ [controller runAsModalSheet];
}
@@ -107,7 +102,7 @@ void BookmarkEditor::Show(gfx::NativeView parent_hwnd,
*/
// TODO(jrg): consider NSModalSession.
-- (void)runModal {
+- (void)runAsModalSheet {
[NSApp beginSheet:[self window]
modalForWindow:parentWindow_
modalDelegate:self
diff --git a/chrome/browser/cocoa/bookmark_name_folder_controller.h b/chrome/browser/cocoa/bookmark_name_folder_controller.h
index 64c3183..764a04a 100644
--- a/chrome/browser/cocoa/bookmark_name_folder_controller.h
+++ b/chrome/browser/cocoa/bookmark_name_folder_controller.h
@@ -26,7 +26,7 @@
- (id)initWithParentWindow:(NSWindow*)window
profile:(Profile*)profile
node:(const BookmarkNode*)node;
-- (void)runModal;
+- (void)runAsModalSheet;
- (IBAction)cancel:(id)sender;
- (IBAction)ok:(id)sender;
@end
diff --git a/chrome/browser/cocoa/bookmark_name_folder_controller.mm b/chrome/browser/cocoa/bookmark_name_folder_controller.mm
index fa24ac5..859e8e7 100644
--- a/chrome/browser/cocoa/bookmark_name_folder_controller.mm
+++ b/chrome/browser/cocoa/bookmark_name_folder_controller.mm
@@ -39,7 +39,7 @@
}
// TODO(jrg): consider NSModalSession.
-- (void)runModal {
+- (void)runAsModalSheet {
[NSApp beginSheet:[self window]
modalForWindow:parentWindow_
modalDelegate:self
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index 91c6a0f..ff1d813 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -202,7 +202,8 @@ void BrowserWindowCocoa::ShowBookmarkManager() {
void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
bool already_bookmarked) {
- NOTIMPLEMENTED();
+ [controller_ showBookmarkBubbleForURL:url
+ alreadyBookmarked:(already_bookmarked ? YES : NO)];
}
bool BrowserWindowCocoa::IsDownloadShelfVisible() const {
diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h
index 6713044..eb34d94 100644
--- a/chrome/browser/cocoa/browser_window_controller.h
+++ b/chrome/browser/cocoa/browser_window_controller.h
@@ -16,6 +16,7 @@
#include "base/scoped_ptr.h"
#import "chrome/browser/cocoa/tab_window_controller.h"
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
+#import "chrome/browser/cocoa/bookmark_bubble_controller.h"
#import "chrome/browser/cocoa/view_resizer.h"
#import "third_party/GTM/AppKit/GTMTheme.h"
@@ -40,6 +41,7 @@ class TabStripModelObserverBridge;
@interface BrowserWindowController :
TabWindowController<NSUserInterfaceValidations,
BookmarkURLOpener,
+ BookmarkBubbleControllerDelegate,
ViewResizer,
GTMThemeDelegate> {
@private
@@ -63,6 +65,7 @@ class TabStripModelObserverBridge;
scoped_nsobject<InfoBarContainerController> infoBarContainerController_;
scoped_ptr<StatusBubble> statusBubble_;
scoped_nsobject<DownloadShelfController> downloadShelfController_;
+ scoped_nsobject<BookmarkBubbleController> bookmarkBubbleController_;
scoped_nsobject<GTMTheme> theme_;
BOOL ownsBrowser_; // Only ever NO when testing
BOOL fullscreen_;
@@ -139,6 +142,10 @@ class TabStripModelObserverBridge;
// Delegate method for the status bubble to query about its vertical offset.
- (float)verticalOffsetForStatusBubble;
+// Show the bookmark bubble (e.g. user just clicked on the STAR)
+- (void)showBookmarkBubbleForURL:(const GURL&)url
+ alreadyBookmarked:(BOOL)alreadyBookmarked;
+
// Returns the (lazily created) window sheet controller of this window. Used
// for the per-tab sheets.
- (GTMWindowSheetController*)sheetController;
@@ -165,6 +172,9 @@ class TabStripModelObserverBridge;
// Return an autoreleased NSWindow suitable for fullscreen use.
- (NSWindow*)fullscreenWindow;
+// Return a point suitable for the topLeft for a bookmark bubble.
+- (NSPoint)topLeftForBubble;
+
@end // BrowserWindowController(TestingAPI)
#endif // CHROME_BROWSER_COCOA_BROWSER_WINDOW_CONTROLLER_H_
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm
index 5918cc4..01cd173 100644
--- a/chrome/browser/cocoa/browser_window_controller.mm
+++ b/chrome/browser/cocoa/browser_window_controller.mm
@@ -9,6 +9,7 @@
#import "base/scoped_nsobject.h"
#include "base/sys_string_conversions.h"
#include "chrome/app/chrome_dll_resource.h" // IDC_*
+#include "chrome/browser/bookmarks/bookmark_editor.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
@@ -20,6 +21,7 @@
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
+#import "chrome/browser/cocoa/bookmark_editor_controller.h"
#import "chrome/browser/cocoa/browser_window_cocoa.h"
#import "chrome/browser/cocoa/browser_window_controller.h"
#import "chrome/browser/cocoa/download_shelf_controller.h"
@@ -933,6 +935,53 @@ willPositionSheet:(NSWindow*)sheet
return theme_ ? theme_ : [GTMTheme defaultTheme];
}
+- (NSPoint)topLeftForBubble {
+ NSRect rect = [toolbarController_ starButtonInWindowCoordinates];
+ NSPoint p = NSMakePoint(NSMinX(rect), NSMinY(rect)); // bottom left
+ return p;
+}
+
+// Show the bookmark bubble (e.g. user just clicked on the STAR).
+- (void)showBookmarkBubbleForURL:(const GURL&)url
+ alreadyBookmarked:(BOOL)alreadyBookmarked {
+ BookmarkModel* model = browser_->profile()->GetBookmarkModel();
+ const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url);
+
+ // Bring up the bubble. But clicking on STAR while the bubble is
+ // open should make it go away.
+ if (bookmarkBubbleController_.get()) {
+ [self doneWithBubbleController:bookmarkBubbleController_.get()];
+ } else {
+ bookmarkBubbleController_.reset([[BookmarkBubbleController alloc]
+ initWithDelegate:self
+ parentWindow:[self window]
+ topLeftForBubble:[self topLeftForBubble]
+ model:model
+ node:node
+ alreadyBookmarked:alreadyBookmarked]);
+ [bookmarkBubbleController_ showWindow];
+ }
+}
+
+// Implement BookmarkBubbleControllerDelegate
+- (void)editBookmarkNode:(const BookmarkNode*)node {
+ // A BookmarkEditorController is a sheet that owns itself, and
+ // deallocates itself when closed.
+ [[[BookmarkEditorController alloc]
+ initWithParentWindow:[self window]
+ profile:browser_->profile()
+ parent:node->GetParent()
+ node:node
+ configuration:BookmarkEditor::SHOW_TREE
+ handler:NULL]
+ runAsModalSheet];
+}
+
+// Implement BookmarkBubbleControllerDelegate
+- (void)doneWithBubbleController:(BookmarkBubbleController*)controller {
+ bookmarkBubbleController_.reset(nil);
+}
+
@end
@implementation BrowserWindowController (Private)
diff --git a/chrome/browser/cocoa/browser_window_controller_unittest.mm b/chrome/browser/cocoa/browser_window_controller_unittest.mm
index 4b40a67..743c90c 100644
--- a/chrome/browser/cocoa/browser_window_controller_unittest.mm
+++ b/chrome/browser/cocoa/browser_window_controller_unittest.mm
@@ -257,4 +257,15 @@ TEST_F(BrowserWindowControllerTest, TestResizeViews) {
EXPECT_TRUE(NSEqualRects([toolbar frame], NSMakeRect(0, 561, 800, 39)));
}
+TEST_F(BrowserWindowControllerTest, TestTopLeftForBubble) {
+ NSPoint p = [controller_ topLeftForBubble];
+ NSRect all = [[controller_ window] frame];
+
+ // As a sanity check make sure the point is vaguely in the top left
+ // of the window.
+ EXPECT_GT(p.y, all.origin.y + (all.size.height/2));
+ EXPECT_LT(p.x, all.origin.x + (all.size.width/2));
+}
+
+
/* TODO(???): test other methods of BrowserWindowController */
diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h
index c5135d3..31aafc4 100644
--- a/chrome/browser/cocoa/toolbar_controller.h
+++ b/chrome/browser/cocoa/toolbar_controller.h
@@ -128,6 +128,10 @@ class ToolbarView;
- (IBAction)showPageMenu:(id)sender;
- (IBAction)showWrenchMenu:(id)sender;
+// The bookmark bubble (when you click the star) needs to know where to go.
+// Somewhere near the star button seems like a good start.
+- (NSRect)starButtonInWindowCoordinates;
+
@end
// A set of private methods used by tests, in the absence of "friends" in ObjC.
diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm
index 04c7e5e0..1bcf8a4 100644
--- a/chrome/browser/cocoa/toolbar_controller.mm
+++ b/chrome/browser/cocoa/toolbar_controller.mm
@@ -373,4 +373,10 @@ class PrefObserverBridge : public NotificationObserver {
forView:wrenchButton_];
}
+- (NSRect)starButtonInWindowCoordinates {
+ return [[[starButton_ window] contentView] convertRect:[starButton_ bounds]
+ fromView:starButton_];
+}
+
+
@end
diff --git a/chrome/browser/cocoa/toolbar_controller_unittest.mm b/chrome/browser/cocoa/toolbar_controller_unittest.mm
index aa0257193..091bddc 100644
--- a/chrome/browser/cocoa/toolbar_controller_unittest.mm
+++ b/chrome/browser/cocoa/toolbar_controller_unittest.mm
@@ -248,4 +248,13 @@ TEST_F(ToolbarControllerTest, BookmarkBarIsFullWidth) {
EXPECT_TRUE([bookmarkBarView isDescendantOf:[bar_ view]]);
}
+TEST_F(ToolbarControllerTest, StarButtonInWindowCoordinates) {
+ NSRect star = [bar_ starButtonInWindowCoordinates];
+ NSRect all = [[[bar_ view] window] frame];
+
+ // Make sure the star is completely inside the window rect
+ EXPECT_TRUE(NSContainsRect(all, star));
+}
+
+
} // namespace
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index e68faae..2432058 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -816,6 +816,12 @@
'browser/cocoa/bookmark_bar_controller.mm',
'browser/cocoa/bookmark_bar_view.h',
'browser/cocoa/bookmark_bar_view.mm',
+ 'browser/cocoa/bookmark_bubble_controller.h',
+ 'browser/cocoa/bookmark_bubble_controller.mm',
+ 'browser/cocoa/bookmark_bubble_view.h',
+ 'browser/cocoa/bookmark_bubble_view.mm',
+ 'browser/cocoa/bookmark_bubble_window.h',
+ 'browser/cocoa/bookmark_bubble_window.mm',
'browser/cocoa/bookmark_button_cell.h',
'browser/cocoa/bookmark_button_cell.mm',
'browser/cocoa/bookmark_editor_controller.h',
@@ -2173,6 +2179,7 @@
'xib_files_to_scan': [
# The xib that need localization
'app/nibs/BookmarkBar.xib',
+ 'app/nibs/BookmarkBubble.xib',
'app/nibs/BookmarkEditor.xib',
'app/nibs/BookmarkNameFolder.xib',
'app/nibs/MainMenu.xib',
@@ -2879,6 +2886,7 @@
# them.
'app/nibs/About.xib',
'app/nibs/BookmarkBar.xib',
+ 'app/nibs/BookmarkBubble.xib',
'app/nibs/BookmarkEditor.xib',
'app/nibs/BookmarkNameFolder.xib',
'app/nibs/BrowserWindow.xib',
@@ -3816,6 +3824,9 @@
'browser/cocoa/bookmark_bar_bridge_unittest.mm',
'browser/cocoa/bookmark_bar_controller_unittest.mm',
'browser/cocoa/bookmark_bar_view_unittest.mm',
+ 'browser/cocoa/bookmark_bubble_controller_unittest.mm',
+ '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_controller_unittest.mm',
'browser/cocoa/bookmark_menu_bridge_unittest.mm',