1 // Copyright (c) 2010 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 17 namespace { 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. 22 typedef std::map<NSView*, ViewID> ViewIDMap; 23 24 static base::LazyInstance<ViewIDMap> g_view_id_map(base::LINKER_INITIALIZED); 25 26 // Returns the view's nearest descendant (including itself) with a specific 27 // ViewID, or nil if no subview has that ViewID. 28 NSView* 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 42 namespace view_id_util { 43 44 void 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 52 void UnsetID(NSView* view) { 53 DCHECK(view); 54 g_view_id_map.Get().erase(view); 55 } 56 57 NSView* 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