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#import "chrome/browser/ui/cocoa/view_id_util.h" 6 7#import <Cocoa/Cocoa.h> 8 9#include <map> 10#include <utility> 11 12#include "base/lazy_instance.h" 13#include "base/logging.h" 14#import "chrome/browser/ui/cocoa/browser_window_controller.h" 15#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" 16 17namespace { 18 19// TODO(suzhe): After migrating to Mac OS X 10.6, we may use Objective-C's new 20// "Associative References" feature to attach the ViewID to the view directly 21// rather than using a separated map. 22typedef std::map<NSView*, ViewID> ViewIDMap; 23 24static base::LazyInstance<ViewIDMap> g_view_id_map = LAZY_INSTANCE_INITIALIZER; 25 26// Returns the view's nearest descendant (including itself) with a specific 27// ViewID, or nil if no subview has that ViewID. 28NSView* FindViewWithID(NSView* view, ViewID viewID) { 29 if ([view viewID] == viewID) 30 return view; 31 32 for (NSView* subview in [view subviews]) { 33 NSView* result = FindViewWithID(subview, viewID); 34 if (result != nil) 35 return result; 36 } 37 return nil; 38} 39 40} // anonymous namespace 41 42namespace view_id_util { 43 44void SetID(NSView* view, ViewID viewID) { 45 DCHECK(view); 46 DCHECK(viewID != VIEW_ID_NONE); 47 // We handle VIEW_ID_TAB_0 to VIEW_ID_TAB_LAST in GetView() function directly. 48 DCHECK(!((viewID >= VIEW_ID_TAB_0) && (viewID <= VIEW_ID_TAB_LAST))); 49 g_view_id_map.Get()[view] = viewID; 50} 51 52void UnsetID(NSView* view) { 53 DCHECK(view); 54 g_view_id_map.Get().erase(view); 55} 56 57NSView* GetView(NSWindow* window, ViewID viewID) { 58 DCHECK(viewID != VIEW_ID_NONE); 59 DCHECK(window); 60 61 // As tabs can be created, destroyed or rearranged dynamically, we handle them 62 // here specially. 63 if (viewID >= VIEW_ID_TAB_0 && viewID <= VIEW_ID_TAB_LAST) { 64 BrowserWindowController* windowController = [window windowController]; 65 DCHECK([windowController isKindOfClass:[BrowserWindowController class]]); 66 TabStripController* tabStripController = 67 [windowController tabStripController]; 68 DCHECK(tabStripController); 69 NSUInteger count = [tabStripController viewsCount]; 70 DCHECK(count); 71 NSUInteger index = 72 (viewID == VIEW_ID_TAB_LAST ? count - 1 : viewID - VIEW_ID_TAB_0); 73 return index < count ? [tabStripController viewAtIndex:index] : nil; 74 } 75 76 return FindViewWithID([[window contentView] superview], viewID); 77} 78 79} // namespace view_id_util 80 81@implementation NSView (ViewID) 82 83- (ViewID)viewID { 84 ViewIDMap* map = g_view_id_map.Pointer(); 85 ViewIDMap::const_iterator iter = map->find(self); 86 return iter != map->end() ? iter->second : VIEW_ID_NONE; 87} 88 89@end 90