OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/gtk/location_bar_view_gtk.h" | 5 #include "chrome/browser/ui/gtk/location_bar_view_gtk.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 #include "chrome/browser/ui/gtk/content_setting_bubble_gtk.h" | 53 #include "chrome/browser/ui/gtk/content_setting_bubble_gtk.h" |
54 #include "chrome/browser/ui/gtk/extensions/extension_popup_gtk.h" | 54 #include "chrome/browser/ui/gtk/extensions/extension_popup_gtk.h" |
55 #include "chrome/browser/ui/gtk/first_run_bubble.h" | 55 #include "chrome/browser/ui/gtk/first_run_bubble.h" |
56 #include "chrome/browser/ui/gtk/gtk_theme_service.h" | 56 #include "chrome/browser/ui/gtk/gtk_theme_service.h" |
57 #include "chrome/browser/ui/gtk/gtk_util.h" | 57 #include "chrome/browser/ui/gtk/gtk_util.h" |
58 #include "chrome/browser/ui/gtk/nine_box.h" | 58 #include "chrome/browser/ui/gtk/nine_box.h" |
59 #include "chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h" | 59 #include "chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h" |
60 #include "chrome/browser/ui/gtk/rounded_window.h" | 60 #include "chrome/browser/ui/gtk/rounded_window.h" |
61 #include "chrome/browser/ui/gtk/view_id_util.h" | 61 #include "chrome/browser/ui/gtk/view_id_util.h" |
62 #include "chrome/browser/ui/gtk/zoom_bubble_gtk.h" | 62 #include "chrome/browser/ui/gtk/zoom_bubble_gtk.h" |
63 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | |
63 #include "chrome/browser/ui/omnibox/location_bar_util.h" | 64 #include "chrome/browser/ui/omnibox/location_bar_util.h" |
64 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" | 65 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" |
65 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" | 66 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" |
66 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 67 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
67 #include "chrome/browser/ui/webui/extensions/extension_info_ui.h" | 68 #include "chrome/browser/ui/webui/extensions/extension_info_ui.h" |
68 #include "chrome/browser/ui/zoom/zoom_controller.h" | 69 #include "chrome/browser/ui/zoom/zoom_controller.h" |
69 #include "chrome/common/chrome_notification_types.h" | 70 #include "chrome/common/chrome_notification_types.h" |
70 #include "chrome/common/extensions/extension.h" | 71 #include "chrome/common/extensions/extension.h" |
71 #include "chrome/common/extensions/extension_action.h" | 72 #include "chrome/common/extensions/extension_action.h" |
72 #include "chrome/common/extensions/extension_manifest_constants.h" | 73 #include "chrome/common/extensions/extension_manifest_constants.h" |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 | 140 |
140 // Default page tool animation time (open and close). | 141 // Default page tool animation time (open and close). |
141 const int kPageToolAnimationTime = 150; | 142 const int kPageToolAnimationTime = 150; |
142 | 143 |
143 // The time, in ms, that the content setting label is fully displayed, for the | 144 // The time, in ms, that the content setting label is fully displayed, for the |
144 // cases where we animate it into and out of view. | 145 // cases where we animate it into and out of view. |
145 const int kContentSettingImageDisplayTime = 3200; | 146 const int kContentSettingImageDisplayTime = 3200; |
146 // The time, in ms, of the animation (open and close). | 147 // The time, in ms, of the animation (open and close). |
147 const int kContentSettingImageAnimationTime = 150; | 148 const int kContentSettingImageAnimationTime = 150; |
148 | 149 |
150 // Animation opening time for web intents button. | |
Evan Stade
2012/08/10 19:36:56
(in ms)
Greg Billock
2012/08/10 19:44:17
Done.
| |
151 const int kWebIntentsButtonAnimationTime = 2000; | |
Evan Stade
2012/08/10 19:36:56
I don't know what exactly this animation is, but u
Greg Billock
2012/08/10 19:44:17
I found it basically impossible to see at all at 2
Peter Kasting
2012/08/11 03:37:10
Whether we cap depends on the purpose of the anima
Greg Billock
2012/08/11 15:08:05
The rate is definitely slower than that. Obviously
Evan Stade
2012/08/14 00:32:32
I would copy the popup blocked duration. I don't t
Greg Billock
2012/08/15 06:34:32
Sounds good. It's easy enough to change if another
| |
152 | |
149 // Color of border of content setting area (icon/label). | 153 // Color of border of content setting area (icon/label). |
150 const GdkColor kContentSettingBorderColor = GDK_COLOR_RGB(0xe9, 0xb9, 0x66); | 154 const GdkColor kContentSettingBorderColor = GDK_COLOR_RGB(0xe9, 0xb9, 0x66); |
151 // Colors for the background gradient. | 155 // Colors for the background gradient. |
152 const GdkColor kContentSettingTopColor = GDK_COLOR_RGB(0xff, 0xf8, 0xd4); | 156 const GdkColor kContentSettingTopColor = GDK_COLOR_RGB(0xff, 0xf8, 0xd4); |
153 const GdkColor kContentSettingBottomColor = GDK_COLOR_RGB(0xff, 0xe6, 0xaf); | 157 const GdkColor kContentSettingBottomColor = GDK_COLOR_RGB(0xff, 0xe6, 0xaf); |
154 | 158 |
159 // Styling for gray button. | |
160 const GdkColor kGrayBorderColor = GDK_COLOR_RGB(0xa0, 0xa0, 0xa0); | |
161 const GdkColor kTopColorGray = GDK_COLOR_RGB(0xe5, 0xe5, 0xe5); | |
162 const GdkColor kBottomColorGray = GDK_COLOR_RGB(0xd0, 0xd0, 0xd0); | |
163 | |
155 // If widget is visible, increment the int pointed to by count. | 164 // If widget is visible, increment the int pointed to by count. |
156 // Suitible for use with gtk_container_foreach. | 165 // Suitible for use with gtk_container_foreach. |
157 void CountVisibleWidgets(GtkWidget* widget, gpointer count) { | 166 void CountVisibleWidgets(GtkWidget* widget, gpointer count) { |
158 if (gtk_widget_get_visible(widget)) | 167 if (gtk_widget_get_visible(widget)) |
159 *static_cast<int*>(count) += 1; | 168 *static_cast<int*>(count) += 1; |
160 } | 169 } |
161 | 170 |
162 class ContentSettingImageViewGtk : public LocationBarViewGtk::PageToolViewGtk, | 171 class ContentSettingImageViewGtk : public LocationBarViewGtk::PageToolViewGtk, |
163 public BubbleDelegateGtk { | 172 public BubbleDelegateGtk { |
164 public: | 173 public: |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
297 profile, tab_contents->web_contents()); | 306 profile, tab_contents->web_contents()); |
298 return; | 307 return; |
299 } | 308 } |
300 | 309 |
301 void ContentSettingImageViewGtk::BubbleClosing( | 310 void ContentSettingImageViewGtk::BubbleClosing( |
302 BubbleGtk* bubble, | 311 BubbleGtk* bubble, |
303 bool closed_by_escape) { | 312 bool closed_by_escape) { |
304 content_setting_bubble_ = NULL; | 313 content_setting_bubble_ = NULL; |
305 } | 314 } |
306 | 315 |
316 class WebIntentsButtonViewGtk : public LocationBarViewGtk::PageToolViewGtk { | |
317 public: | |
318 explicit WebIntentsButtonViewGtk(const LocationBarViewGtk* parent) | |
319 : LocationBarViewGtk::PageToolViewGtk(parent) { | |
320 animation_.SetSlideDuration(kWebIntentsButtonAnimationTime); | |
321 } | |
322 virtual ~WebIntentsButtonViewGtk() {} | |
307 | 323 |
324 // PageToolViewGtk | |
325 virtual void Update(TabContents* tab_contents) OVERRIDE; | |
326 | |
327 private: | |
328 // PageToolViewGtk | |
329 virtual GdkColor button_border_color() const OVERRIDE; | |
330 virtual GdkColor gradient_top_color() const OVERRIDE; | |
331 virtual GdkColor gradient_bottom_color() const OVERRIDE; | |
332 virtual void OnClick(GtkWidget* sender) OVERRIDE; | |
333 | |
334 DISALLOW_COPY_AND_ASSIGN(WebIntentsButtonViewGtk); | |
335 }; | |
336 | |
337 void WebIntentsButtonViewGtk::Update( | |
338 TabContents* tab_contents) { | |
339 if (!tab_contents || | |
340 !tab_contents->web_intent_picker_controller() || | |
341 !tab_contents->web_intent_picker_controller()-> | |
342 ShowLocationBarPickerTool()) { | |
343 gtk_widget_hide(widget()); | |
344 return; | |
345 } | |
346 | |
347 gtk_widget_set_tooltip_text(widget(), | |
348 l10n_util::GetStringUTF8(IDS_INTENT_PICKER_USE_ANOTHER_SERVICE).c_str()); | |
349 gtk_widget_show_all(widget()); | |
350 | |
351 gtk_label_set_text(GTK_LABEL(label_.get()), | |
352 l10n_util::GetStringUTF8(IDS_INTENT_PICKER_USE_ANOTHER_SERVICE).c_str()); | |
353 | |
354 StartAnimating(); | |
355 } | |
356 | |
357 void WebIntentsButtonViewGtk::OnClick(GtkWidget* sender) { | |
358 DLOG(INFO) << "Web Intents button click"; | |
Evan Stade
2012/08/10 19:36:56
TODO(gbillock): Implement. (?)
I don't think the
Greg Billock
2012/08/10 19:44:17
Done.
| |
359 } | |
360 | |
361 GdkColor WebIntentsButtonViewGtk::button_border_color() const { | |
362 return kGrayBorderColor; | |
363 } | |
364 | |
365 GdkColor WebIntentsButtonViewGtk::gradient_top_color() const { | |
366 return kTopColorGray; | |
367 } | |
368 | |
369 GdkColor WebIntentsButtonViewGtk::gradient_bottom_color() const { | |
370 return kBottomColorGray; | |
371 } | |
308 | 372 |
309 } // namespace | 373 } // namespace |
310 | 374 |
311 //////////////////////////////////////////////////////////////////////////////// | 375 //////////////////////////////////////////////////////////////////////////////// |
312 // LocationBarViewGtk | 376 // LocationBarViewGtk |
313 | 377 |
314 // static | 378 // static |
315 const GdkColor LocationBarViewGtk::kBackgroundColor = | 379 const GdkColor LocationBarViewGtk::kBackgroundColor = |
316 GDK_COLOR_RGB(255, 255, 255); | 380 GDK_COLOR_RGB(255, 255, 255); |
317 | 381 |
318 LocationBarViewGtk::LocationBarViewGtk(Browser* browser) | 382 LocationBarViewGtk::LocationBarViewGtk(Browser* browser) |
319 : zoom_image_(NULL), | 383 : zoom_image_(NULL), |
320 star_image_(NULL), | 384 star_image_(NULL), |
321 starred_(false), | 385 starred_(false), |
322 chrome_to_mobile_image_(NULL), | 386 chrome_to_mobile_image_(NULL), |
323 site_type_alignment_(NULL), | 387 site_type_alignment_(NULL), |
324 site_type_event_box_(NULL), | 388 site_type_event_box_(NULL), |
325 location_icon_image_(NULL), | 389 location_icon_image_(NULL), |
326 drag_icon_(NULL), | 390 drag_icon_(NULL), |
327 enable_location_drag_(false), | 391 enable_location_drag_(false), |
328 security_info_label_(NULL), | 392 security_info_label_(NULL), |
393 web_intents_button_view_(new WebIntentsButtonViewGtk(this)), | |
329 tab_to_search_alignment_(NULL), | 394 tab_to_search_alignment_(NULL), |
330 tab_to_search_box_(NULL), | 395 tab_to_search_box_(NULL), |
331 tab_to_search_full_label_(NULL), | 396 tab_to_search_full_label_(NULL), |
332 tab_to_search_partial_label_(NULL), | 397 tab_to_search_partial_label_(NULL), |
333 tab_to_search_hint_(NULL), | 398 tab_to_search_hint_(NULL), |
334 tab_to_search_hint_leading_label_(NULL), | 399 tab_to_search_hint_leading_label_(NULL), |
335 tab_to_search_hint_icon_(NULL), | 400 tab_to_search_hint_icon_(NULL), |
336 tab_to_search_hint_trailing_label_(NULL), | 401 tab_to_search_hint_trailing_label_(NULL), |
337 command_updater_(browser->command_controller()->command_updater()), | 402 command_updater_(browser->command_controller()->command_updater()), |
338 toolbar_model_(browser->toolbar_model()), | 403 toolbar_model_(browser->toolbar_model()), |
(...skipping 12 matching lines...) Expand all Loading... | |
351 } | 416 } |
352 | 417 |
353 LocationBarViewGtk::~LocationBarViewGtk() { | 418 LocationBarViewGtk::~LocationBarViewGtk() { |
354 // All of our widgets should be children of / owned by the alignment. | 419 // All of our widgets should be children of / owned by the alignment. |
355 zoom_.Destroy(); | 420 zoom_.Destroy(); |
356 star_.Destroy(); | 421 star_.Destroy(); |
357 chrome_to_mobile_view_.Destroy(); | 422 chrome_to_mobile_view_.Destroy(); |
358 hbox_.Destroy(); | 423 hbox_.Destroy(); |
359 content_setting_hbox_.Destroy(); | 424 content_setting_hbox_.Destroy(); |
360 page_action_hbox_.Destroy(); | 425 page_action_hbox_.Destroy(); |
426 web_intents_hbox_.Destroy(); | |
361 } | 427 } |
362 | 428 |
363 void LocationBarViewGtk::Init(bool popup_window_mode) { | 429 void LocationBarViewGtk::Init(bool popup_window_mode) { |
364 popup_window_mode_ = popup_window_mode; | 430 popup_window_mode_ = popup_window_mode; |
365 | 431 |
366 Profile* profile = browser_->profile(); | 432 Profile* profile = browser_->profile(); |
367 theme_service_ = GtkThemeService::GetFrom(profile); | 433 theme_service_ = GtkThemeService::GetFrom(profile); |
368 | 434 |
369 // Create the widget first, so we can pass it to the OmniboxViewGtk. | 435 // Create the widget first, so we can pass it to the OmniboxViewGtk. |
370 hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding)); | 436 hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding)); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
521 gtk_box_pack_end(GTK_BOX(content_setting_hbox_.get()), | 587 gtk_box_pack_end(GTK_BOX(content_setting_hbox_.get()), |
522 content_setting_view->widget(), FALSE, FALSE, 0); | 588 content_setting_view->widget(), FALSE, FALSE, 0); |
523 } | 589 } |
524 | 590 |
525 page_action_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding)); | 591 page_action_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding)); |
526 gtk_widget_set_name(page_action_hbox_.get(), | 592 gtk_widget_set_name(page_action_hbox_.get(), |
527 "chrome-page-action-hbox"); | 593 "chrome-page-action-hbox"); |
528 gtk_box_pack_end(GTK_BOX(hbox_.get()), page_action_hbox_.get(), | 594 gtk_box_pack_end(GTK_BOX(hbox_.get()), page_action_hbox_.get(), |
529 FALSE, FALSE, 0); | 595 FALSE, FALSE, 0); |
530 | 596 |
597 web_intents_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding)); | |
598 gtk_widget_set_name(web_intents_hbox_.get(), | |
599 "chrome-web-intents-hbox"); | |
600 gtk_box_pack_end(GTK_BOX(hbox_.get()), web_intents_hbox_.get(), | |
601 FALSE, FALSE, 0); | |
602 gtk_box_pack_end(GTK_BOX(web_intents_hbox_.get()), | |
603 web_intents_button_view_->widget(), FALSE, FALSE, 0); | |
604 | |
531 // Now that we've created the widget hierarchy, connect to the main |hbox_|'s | 605 // Now that we've created the widget hierarchy, connect to the main |hbox_|'s |
532 // size-allocate so we can do proper resizing and eliding on | 606 // size-allocate so we can do proper resizing and eliding on |
533 // |security_info_label_|. | 607 // |security_info_label_|. |
534 g_signal_connect(hbox_.get(), "size-allocate", | 608 g_signal_connect(hbox_.get(), "size-allocate", |
535 G_CALLBACK(&OnHboxSizeAllocateThunk), this); | 609 G_CALLBACK(&OnHboxSizeAllocateThunk), this); |
536 | 610 |
537 registrar_.Add(this, | 611 registrar_.Add(this, |
538 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | 612 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
539 content::Source<ThemeService>(theme_service_)); | 613 content::Source<ThemeService>(theme_service_)); |
540 registrar_.Add(this, | 614 registrar_.Add(this, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
652 return NULL; | 726 return NULL; |
653 } | 727 } |
654 | 728 |
655 void LocationBarViewGtk::Update(const WebContents* contents) { | 729 void LocationBarViewGtk::Update(const WebContents* contents) { |
656 UpdateZoomIcon(); | 730 UpdateZoomIcon(); |
657 UpdateStarIcon(); | 731 UpdateStarIcon(); |
658 UpdateChromeToMobileIcon(); | 732 UpdateChromeToMobileIcon(); |
659 UpdateSiteTypeArea(); | 733 UpdateSiteTypeArea(); |
660 UpdateContentSettingsIcons(); | 734 UpdateContentSettingsIcons(); |
661 UpdatePageActions(); | 735 UpdatePageActions(); |
736 UpdateWebIntentsButton(); | |
662 location_entry_->Update(contents); | 737 location_entry_->Update(contents); |
663 // The security level (background color) could have changed, etc. | 738 // The security level (background color) could have changed, etc. |
664 if (theme_service_->UsingNativeTheme()) { | 739 if (theme_service_->UsingNativeTheme()) { |
665 // In GTK mode, we need our parent to redraw, as it draws the text entry | 740 // In GTK mode, we need our parent to redraw, as it draws the text entry |
666 // border. | 741 // border. |
667 gtk_widget_queue_draw(gtk_widget_get_parent(widget())); | 742 gtk_widget_queue_draw(gtk_widget_get_parent(widget())); |
668 } else { | 743 } else { |
669 gtk_widget_queue_draw(widget()); | 744 gtk_widget_queue_draw(widget()); |
670 } | 745 } |
671 } | 746 } |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
934 size_t count_before = page_action_views_.size(); | 1009 size_t count_before = page_action_views_.size(); |
935 page_action_views_.clear(); | 1010 page_action_views_.clear(); |
936 if (page_action_views_.size() != count_before) { | 1011 if (page_action_views_.size() != count_before) { |
937 content::NotificationService::current()->Notify( | 1012 content::NotificationService::current()->Notify( |
938 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED, | 1013 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED, |
939 content::Source<LocationBar>(this), | 1014 content::Source<LocationBar>(this), |
940 content::NotificationService::NoDetails()); | 1015 content::NotificationService::NoDetails()); |
941 } | 1016 } |
942 } | 1017 } |
943 | 1018 |
1019 void LocationBarViewGtk::UpdateWebIntentsButton() { | |
1020 web_intents_button_view_->Update(GetTabContents()); | |
1021 gtk_widget_set_visible(web_intents_hbox_.get(), | |
1022 web_intents_button_view_->IsVisible()); | |
1023 } | |
1024 | |
944 void LocationBarViewGtk::SaveStateToContents(WebContents* contents) { | 1025 void LocationBarViewGtk::SaveStateToContents(WebContents* contents) { |
945 location_entry_->SaveStateToTab(contents); | 1026 location_entry_->SaveStateToTab(contents); |
946 } | 1027 } |
947 | 1028 |
948 void LocationBarViewGtk::Revert() { | 1029 void LocationBarViewGtk::Revert() { |
949 location_entry_->RevertAll(); | 1030 location_entry_->RevertAll(); |
950 } | 1031 } |
951 | 1032 |
952 const OmniboxView* LocationBarViewGtk::GetLocationEntry() const { | 1033 const OmniboxView* LocationBarViewGtk::GetLocationEntry() const { |
953 return location_entry_.get(); | 1034 return location_entry_.get(); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1076 1, 1, 0, 0); | 1157 1, 1, 0, 0); |
1077 gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_), | 1158 gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_), |
1078 1, 1, 0, 0); | 1159 1, 1, 0, 0); |
1079 } | 1160 } |
1080 | 1161 |
1081 UpdateZoomIcon(); | 1162 UpdateZoomIcon(); |
1082 UpdateStarIcon(); | 1163 UpdateStarIcon(); |
1083 UpdateChromeToMobileIcon(); | 1164 UpdateChromeToMobileIcon(); |
1084 UpdateSiteTypeArea(); | 1165 UpdateSiteTypeArea(); |
1085 UpdateContentSettingsIcons(); | 1166 UpdateContentSettingsIcons(); |
1167 UpdateWebIntentsButton(); | |
1086 break; | 1168 break; |
1087 } | 1169 } |
1088 | 1170 |
1089 default: | 1171 default: |
1090 NOTREACHED(); | 1172 NOTREACHED(); |
1091 } | 1173 } |
1092 } | 1174 } |
1093 | 1175 |
1094 gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget, | 1176 gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget, |
1095 GdkEventExpose* event) { | 1177 GdkEventExpose* event) { |
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2051 } | 2133 } |
2052 | 2134 |
2053 void LocationBarViewGtk::PageActionViewGtk::InspectPopup( | 2135 void LocationBarViewGtk::PageActionViewGtk::InspectPopup( |
2054 ExtensionAction* action) { | 2136 ExtensionAction* action) { |
2055 ExtensionPopupGtk::Show( | 2137 ExtensionPopupGtk::Show( |
2056 action->GetPopupUrl(current_tab_id_), | 2138 action->GetPopupUrl(current_tab_id_), |
2057 owner_->browser_, | 2139 owner_->browser_, |
2058 event_box_.get(), | 2140 event_box_.get(), |
2059 ExtensionPopupGtk::SHOW_AND_INSPECT); | 2141 ExtensionPopupGtk::SHOW_AND_INSPECT); |
2060 } | 2142 } |
OLD | NEW |