• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_FOLDER_CONTROLLER_H_
6 #define CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_FOLDER_CONTROLLER_H_
7 #pragma once
8 
9 #import <Cocoa/Cocoa.h>
10 
11 #include "base/memory/scoped_nsobject.h"
12 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
13 #import "chrome/browser/ui/cocoa/tracking_area.h"
14 
15 @class BookmarkBarController;
16 @class BookmarkBarFolderView;
17 @class BookmarkFolderTarget;
18 @class BookmarkBarFolderHoverState;
19 @class BookmarkBarFolderWindow;
20 @class BookmarkBarFolderWindowContentView;
21 
22 // A controller for the pop-up windows from bookmark folder buttons
23 // which look sort of like menus.
24 @interface BookmarkBarFolderController :
25     NSWindowController<BookmarkButtonDelegate,
26                        BookmarkButtonControllerProtocol,
27                        NSUserInterfaceValidations> {
28  @private
29   // The button whose click opened us.
30   scoped_nsobject<BookmarkButton> parentButton_;
31 
32   // Bookmark bar folder controller chains are torn down in two ways:
33   // 1. Clicking "outside" the folder (see use of
34   // CrApplicationEventHookProtocol in the bookmark bar controller).
35   // 2. Engaging a different folder (via hover over or explicit click).
36   //
37   // In either case, the BookmarkButtonControllerProtocol method
38   // closeAllBookmarkFolders gets called.  For bookmark bar folder
39   // controllers, this is passed up the chain so we begin with a top
40   // level "close".
41   // When any bookmark folder window closes, it necessarily tells
42   // subcontroller windows to close (down the chain), and autoreleases
43   // the controller.  (Must autorelease since the controller can still
44   // get delegate events such as windowDidClose).
45   //
46   // Bookmark bar folder controllers own their buttons.  When doing
47   // drag and drop of a button from one sub-sub-folder to a different
48   // sub-sub-folder, we need to make sure the button's pointers stay
49   // valid until we've dropped (or cancelled).  Note that such a drag
50   // causes the source sub-sub-folder (previous parent window) to go
51   // away (windows close, controllers autoreleased) since you're
52   // hovering over a different folder chain for dropping.  To keep
53   // things valid (like the button's target, its delegate, the parent
54   // cotroller that we have a pointer to below [below], etc), we heep
55   // strong pointers to our owning controller, so the entire chain
56   // stays owned.
57 
58   // Our parent controller, if we are a nested folder, otherwise nil.
59   // Strong to insure the object lives as long as we need it.
60   scoped_nsobject<BookmarkBarFolderController> parentController_;
61 
62   // The main bar controller from whence we or a parent sprang.
63   BookmarkBarController* barController_;  // WEAK: It owns us.
64 
65   // Our buttons.  We do not have buttons for nested folders.
66   scoped_nsobject<NSMutableArray> buttons_;
67 
68   // The scroll view that contains our main button view (below).
69   IBOutlet NSScrollView* scrollView_;
70 
71   // The view defining the visible area in which we draw our content.
72   IBOutlet BookmarkBarFolderWindowContentView* visibleView_;
73 
74   // The main view of this window (where the buttons go) within the scroller.
75   IBOutlet BookmarkBarFolderView* folderView_;
76 
77   // A window used to show the shadow behind the main window when it is
78   // scrollable. (A 'shadow' window is needed because the main window, when
79   // scrollable in either or both directions, will reach completely to the
80   // top and/or bottom edge of the screen in order to support mouse tracking
81   // during scrolling operations. In that case, though, the 'visible'
82   // window must be inset a bit from the edge of the screen for aesthetics;
83   // it will also be inset much more from the bottom of the screen when the
84   // Dock is showing. When scrollable, the main window would show a shadow
85   // incorrectly positioned, hence the 'shadow' window.)
86   IBOutlet BookmarkBarFolderWindow* shadowWindow_;
87 
88   // The up and down scroll arrow views. These arrows are hidden and shown
89   // as necessary (when scrolling is possible) and are contained in the nib
90   // as siblings to the scroll view.
91   IBOutlet NSView* scrollDownArrowView_;  // Positioned at the top.
92   IBOutlet NSView* scrollUpArrowView_;  // Positioned at the bottom.
93 
94   // YES if subfolders should grow to the right (the default).
95   // Direction switches if we'd grow off the screen.
96   BOOL subFolderGrowthToRight_;
97 
98   // Weak; we keep track to work around a
99   // setShowsBorderOnlyWhileMouseInside bug.
100   BookmarkButton* buttonThatMouseIsIn_;
101 
102   // The context menu for a bookmark button which represents an URL.
103   IBOutlet NSMenu* buttonMenu_;
104 
105   // The context menu for a bookmark button which represents a folder.
106   IBOutlet NSMenu* folderMenu_;
107 
108   // We model hover state as a state machine with specific allowable
109   // transitions.  |hoverState_| is the state of this machine at any
110   // given time.
111   scoped_nsobject<BookmarkBarFolderHoverState> hoverState_;
112 
113   // Logic for dealing with a click on a bookmark folder button.
114   scoped_nsobject<BookmarkFolderTarget> folderTarget_;
115 
116   // A controller for a pop-up bookmark folder window (custom menu).
117   // We (self) are the parentController_ for our folderController_.
118   // This is not a scoped_nsobject because it owns itself (when its
119   // window closes the controller gets autoreleased).
120   BookmarkBarFolderController* folderController_;
121 
122   // Implement basic menu scrolling through this tracking area.
123   ScopedCrTrackingArea scrollTrackingArea_;
124 
125   // Timer to continue scrolling as needed.  We own the timer but
126   // don't release it when done (we invalidate it).
127   NSTimer* scrollTimer_;
128 
129   // Precalculated sum of left and right edge padding of buttons in a
130   // folder menu window. This is calculated from the widths of the main
131   // folder menu window and the scroll view within.
132   CGFloat padding_;
133 
134   // Amount to scroll by on each timer fire.  Can be + or -.
135   CGFloat verticalScrollDelta_;
136 
137   // We need to know the size of the vertical scrolling arrows so we
138   // can obscure/unobscure them.
139   CGFloat verticalScrollArrowHeight_;
140 
141   // Set to YES to prevent any node animations. Useful for unit testing so that
142   // incomplete animations do not cause valgrind complaints.
143   BOOL ignoreAnimations_;
144 
145   int selectedIndex_;
146   NSString* typedPrefix_;
147 }
148 
149 // Designated initializer.
150 - (id)initWithParentButton:(BookmarkButton*)button
151           parentController:(BookmarkBarFolderController*)parentController
152              barController:(BookmarkBarController*)barController;
153 
154 // Return the parent button that owns the bookmark folder we represent.
155 - (BookmarkButton*)parentButton;
156 
157 // Text typed by user, for type-select and arrow key support.
158 // Returns YES if the menu should be closed now.
159 - (BOOL)handleInputText:(NSString*)newText;
160 
161 // If you wanted to clear the type-select buffer. Currently only used
162 // internally.
163 - (void)clearInputText;
164 
165 // Gets notified when a fav icon asynchronously loads, so we can now use the
166 // real icon instead of a generic placeholder.
167 - (void)faviconLoadedForNode:(const BookmarkNode*)node;
168 
169 - (void)setSelectedButtonByIndex:(int)index;
170 
171 // Offset our folder menu window. This is usually needed in response to a
172 // parent folder menu window or the bookmark bar changing position due to
173 // the dragging of a bookmark node from the parent into this folder menu.
174 - (void)offsetFolderMenuWindow:(NSSize)offset;
175 
176 // Re-layout the window menu in case some buttons were added or removed,
177 // specifically as a result of the bookmark bar changing configuration
178 // and altering the contents of the off-the-side folder.
179 - (void)reconfigureMenu;
180 
181 // Actions from a context menu over a button or folder.
182 - (IBAction)cutBookmark:(id)sender;
183 - (IBAction)copyBookmark:(id)sender;
184 - (IBAction)pasteBookmark:(id)sender;
185 - (IBAction)deleteBookmark:(id)sender;
186 
187 // Passed up by a child view to tell us of a desire to scroll.
188 - (void)scrollWheel:(NSEvent *)theEvent;
189 
190 - (void)mouseDragged:(NSEvent*)theEvent;
191 
192 
193 // Forwarded to the associated BookmarkBarController.
194 - (IBAction)addFolder:(id)sender;
195 - (IBAction)addPage:(id)sender;
196 - (IBAction)editBookmark:(id)sender;
197 - (IBAction)openBookmark:(id)sender;
198 - (IBAction)openAllBookmarks:(id)sender;
199 - (IBAction)openAllBookmarksIncognitoWindow:(id)sender;
200 - (IBAction)openAllBookmarksNewWindow:(id)sender;
201 - (IBAction)openBookmarkInIncognitoWindow:(id)sender;
202 - (IBAction)openBookmarkInNewForegroundTab:(id)sender;
203 - (IBAction)openBookmarkInNewWindow:(id)sender;
204 
205 @property(assign, nonatomic) BOOL subFolderGrowthToRight;
206 
207 @end
208 
209 @interface BookmarkBarFolderController(TestingAPI)
210 - (NSPoint)windowTopLeftForWidth:(int)windowWidth
211                           height:(int)windowHeight;
212 - (NSArray*)buttons;
213 - (BookmarkBarFolderController*)folderController;
214 - (id)folderTarget;
215 - (void)configureWindowLevel;
216 - (void)performOneScroll:(CGFloat)delta;
217 - (BookmarkButton*)buttonThatMouseIsIn;
218 // Set to YES in order to prevent animations.
219 - (void)setIgnoreAnimations:(BOOL)ignore;
220 
221 // Return YES if the scroll-up or scroll-down arrows are showing.
222 - (BOOL)canScrollUp;
223 - (BOOL)canScrollDown;
224 - (CGFloat)verticalScrollArrowHeight;
225 - (NSView*)visibleView;
226 - (NSScrollView*)scrollView;
227 - (NSView*)folderView;
228 
229 - (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point;
230 @end
231 
232 #endif  // CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_FOLDER_CONTROLLER_H_
233