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.
5 #import "chrome/browser/ui/cocoa/view_id_util.h"
7 #import <Cocoa/Cocoa.h>
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"
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;
24 static base::LazyInstance<ViewIDMap> g_view_id_map = LAZY_INSTANCE_INITIALIZER;
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)
32 for (NSView* subview in [view subviews]) {
33 NSView* result = FindViewWithID(subview, viewID);
40 } // anonymous namespace
42 namespace view_id_util {
44 void SetID(NSView* view, ViewID viewID) {
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;
52 void UnsetID(NSView* view) {
54 g_view_id_map.Get().erase(view);
57 NSView* GetView(NSWindow* window, ViewID viewID) {
58 DCHECK(viewID != VIEW_ID_NONE);
61 // As tabs can be created, destroyed or rearranged dynamically, we handle them
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];
72 (viewID == VIEW_ID_TAB_LAST ? count - 1 : viewID - VIEW_ID_TAB_0);
73 return index < count ? [tabStripController viewAtIndex:index] : nil;
76 return FindViewWithID([[window contentView] superview], viewID);
79 } // namespace view_id_util
81 @implementation NSView (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;
89 - (NSView*)ancestorWithViewID:(ViewID)viewID {
90 NSView* ancestor = self;
91 while (ancestor && [ancestor viewID] != viewID)
92 ancestor = [ancestor superview];