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#include "chrome/browser/ui/gtk/view_id_util.h"
6
7#include <stdint.h>
8#include <string>
9
10#include <gtk/gtk.h>
11
12#include "base/logging.h"
13
14namespace {
15
16const char kViewIDString[] = "__VIEW_ID__";
17const char kViewIDOverrideString[] = "__VIEW_ID_OVERRIDE__";
18
19struct ViewIDSearchStruct {
20  ViewID id;  // Input: the ID we are searching for.
21  GtkWidget* widget;  // Output: the found widget, or NULL.
22};
23
24// Recursively search for the given view ID among the children of |widget|.
25void SearchForWidgetWithViewID(GtkWidget* widget, gpointer data) {
26  ViewIDSearchStruct* search_struct =
27      reinterpret_cast<ViewIDSearchStruct*>(data);
28
29  // The widget has already been found; abort the search.
30  if (search_struct->widget)
31    return;
32
33  // Check if the widget defines its own ID function.
34  ViewIDUtil::Delegate* delegate = reinterpret_cast<ViewIDUtil::Delegate*>(
35      g_object_get_data(G_OBJECT(widget), kViewIDOverrideString));
36  if (delegate) {
37    search_struct->widget = delegate->GetWidgetForViewID(search_struct->id);
38    // If there was success, return.
39    if (search_struct->widget)
40      return;
41  }
42
43  // Otherwise check the g_object data.
44  int widget_id =
45      reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(widget),
46                                 kViewIDString));
47  if (search_struct->id == widget_id) {
48    // Success; set |widget| and return.
49    search_struct->widget = widget;
50    return;
51  }
52
53  // Recurse.
54  if (GTK_IS_CONTAINER(widget)) {
55    gtk_container_foreach(GTK_CONTAINER(widget),
56                          SearchForWidgetWithViewID, data);
57  }
58}
59
60const char* GetNameFromID(ViewID id) {
61  switch (id) {
62    case VIEW_ID_TAB_STRIP:
63      return "chrome-tab-strip";
64
65    case VIEW_ID_TOOLBAR:
66      return "chrome-toolbar";
67
68    case VIEW_ID_BACK_BUTTON:
69      return "chrome-toolbar-back-button";
70
71    case VIEW_ID_FORWARD_BUTTON:
72      return "chrome-toolbar-forward-button";
73
74    case VIEW_ID_RELOAD_BUTTON:
75      return "chrome-toolbar-reload-button";
76
77    case VIEW_ID_HOME_BUTTON:
78      return "chrome-toolbar-home-button";
79
80    case VIEW_ID_STAR_BUTTON:
81      return "chrome-toolbar-star-button";
82
83    case VIEW_ID_LOCATION_BAR:
84      return "chrome-location-bar";
85
86    case VIEW_ID_BROWSER_ACTION_TOOLBAR:
87      return "chrome-toolbar-browser-actions-container";
88
89    case VIEW_ID_APP_MENU:
90      return "chrome-app-menu";
91
92    case VIEW_ID_AUTOCOMPLETE:
93      return "chrome-autocomplete-edit";
94
95    case VIEW_ID_BOOKMARK_BAR:
96      return "chrome-bookmark-bar";
97
98    case VIEW_ID_OTHER_BOOKMARKS:
99      return "chrome-bookmark-bar-other-bookmarks";
100
101    case VIEW_ID_FIND_IN_PAGE_TEXT_FIELD:
102      return "chrome-find-in-page-entry";
103
104    case VIEW_ID_FIND_IN_PAGE:
105      return "chrome-find-in-page";
106
107    case VIEW_ID_DEV_TOOLS_DOCKED:
108      return "chrome-dev-tools-docked";
109
110    // These are never hit because the tab container uses the delegate to
111    // set its ID.
112    case VIEW_ID_TAB_CONTAINER:
113    case VIEW_ID_TAB_CONTAINER_FOCUS_VIEW:
114    default:
115      NOTREACHED() << "If you added a new VIEW_ID, please provide "
116                      "a name for the widget.";
117      return NULL;
118  }
119}
120
121}  // namespace
122
123void ViewIDUtil::SetID(GtkWidget* widget, ViewID id) {
124  const char* name = GetNameFromID(id);
125  if (name)
126    gtk_widget_set_name(widget, name);
127  g_object_set_data(G_OBJECT(widget), kViewIDString,
128                    reinterpret_cast<void*>(id));
129}
130
131GtkWidget* ViewIDUtil::GetWidget(GtkWidget* root, ViewID id) {
132  ViewIDSearchStruct search_struct = { id, NULL };
133  SearchForWidgetWithViewID(root, &search_struct);
134  return search_struct.widget;
135}
136
137void ViewIDUtil::SetDelegateForWidget(GtkWidget* widget, Delegate* delegate) {
138  g_object_set_data(G_OBJECT(widget), kViewIDOverrideString, delegate);
139}
140