Home | History | Annotate | Download | only in bookmarks
      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