summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/views/about_chrome_view.cc2
-rw-r--r--chrome/browser/views/bookmark_editor_view.cc2
-rw-r--r--chrome/browser/views/bug_report_view.cc2
-rw-r--r--chrome/browser/views/clear_browsing_data.cc4
-rw-r--r--chrome/browser/views/constrained_window_impl.cc56
-rw-r--r--chrome/browser/views/constrained_window_impl.h9
-rw-r--r--chrome/browser/views/edit_keyword_controller.cc4
-rw-r--r--chrome/browser/views/first_run_view_base.cc9
-rw-r--r--chrome/browser/views/input_window.cc4
-rw-r--r--chrome/browser/views/shelf_item_dialog.cc4
-rw-r--r--chrome/views/custom_frame_window.cc105
-rw-r--r--chrome/views/dialog_client_view.cc410
-rw-r--r--chrome/views/dialog_client_view.h133
-rw-r--r--chrome/views/dialog_delegate.h26
-rw-r--r--chrome/views/views.vcproj8
-rw-r--r--chrome/views/window.cc103
-rw-r--r--chrome/views/window.h48
-rw-r--r--chrome/views/window_delegate.h7
18 files changed, 714 insertions, 222 deletions
diff --git a/chrome/browser/views/about_chrome_view.cc b/chrome/browser/views/about_chrome_view.cc
index 4ad5908..bc632cd 100644
--- a/chrome/browser/views/about_chrome_view.cc
+++ b/chrome/browser/views/about_chrome_view.cc
@@ -489,5 +489,5 @@ void AboutChromeView::UpdateStatus(GoogleUpdateUpgradeResult result,
// Check button may have appeared/disappeared. We cannot call this during
// ViewHierarchyChanged because the |window()| pointer hasn't been set yet.
if (window())
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
}
diff --git a/chrome/browser/views/bookmark_editor_view.cc b/chrome/browser/views/bookmark_editor_view.cc
index da5a92d..8f6ae2c 100644
--- a/chrome/browser/views/bookmark_editor_view.cc
+++ b/chrome/browser/views/bookmark_editor_view.cc
@@ -391,7 +391,7 @@ void BookmarkEditorView::UserInputChanged() {
url_tf_.SetBackgroundColor(kErrorColor);
else
url_tf_.SetDefaultBackgroundColor();
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
}
void BookmarkEditorView::NewGroup() {
diff --git a/chrome/browser/views/bug_report_view.cc b/chrome/browser/views/bug_report_view.cc
index 45023e5..b46235f 100644
--- a/chrome/browser/views/bug_report_view.cc
+++ b/chrome/browser/views/bug_report_view.cc
@@ -278,7 +278,7 @@ void BugReportView::ItemChanged(ChromeViews::ComboBox* combo_box,
include_page_image_checkbox_->SetEnabled(!is_phishing_report);
include_page_image_checkbox_->SetIsSelected(!is_phishing_report);
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
}
void BugReportView::ContentsChanged(ChromeViews::TextField* sender,
diff --git a/chrome/browser/views/clear_browsing_data.cc b/chrome/browser/views/clear_browsing_data.cc
index b3721ab..2526182 100644
--- a/chrome/browser/views/clear_browsing_data.cc
+++ b/chrome/browser/views/clear_browsing_data.cc
@@ -322,7 +322,7 @@ std::wstring ClearBrowsingDataView::GetItemAt(ChromeViews::ComboBox* source,
void ClearBrowsingDataView::ButtonPressed(ChromeViews::NativeButton* sender) {
// When no checkbox is checked we should not have the action button enabled.
// This forces the button to evaluate what state they should be in.
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
}
////////////////////////////////////////////////////////////////////////////////
@@ -355,7 +355,7 @@ void ClearBrowsingDataView::UpdateControlEnabledState() {
throbber_->Stop();
// Make sure to update the state for OK and Cancel buttons.
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
}
// Convenience method that returns true if the supplied checkbox is selected
diff --git a/chrome/browser/views/constrained_window_impl.cc b/chrome/browser/views/constrained_window_impl.cc
index f666b50..96a63588 100644
--- a/chrome/browser/views/constrained_window_impl.cc
+++ b/chrome/browser/views/constrained_window_impl.cc
@@ -256,7 +256,6 @@ class ConstrainedWindowNonClientView
void SetShowThrobber(bool show_throbber);
// Overridden from ChromeViews::NonClientView:
- virtual void Init(ChromeViews::ClientView* client_view);
virtual gfx::Rect CalculateClientAreaBounds(int width, int height) const;
virtual gfx::Size CalculateWindowSizeForClientSize(int width,
int height) const;
@@ -300,11 +299,6 @@ class ConstrainedWindowNonClientView
void UpdateLocationBar();
bool ShouldDisplayURLField() const;
- // The View that provides the background for the window, and optionally
- // dialog buttons. Note: the non-client view does _not_ own this view, the
- // container does.
- ChromeViews::ClientView* client_view_;
-
ConstrainedWindowImpl* container_;
ChromeViews::WindowDelegate* window_delegate_;
@@ -540,12 +534,6 @@ void ConstrainedWindowNonClientView::Run() {
////////////////////////////////////////////////////////////////////////////////
// ConstrainedWindowNonClientView, ChromeViews::NonClientView implementation:
-void ConstrainedWindowNonClientView::Init(
- ChromeViews::ClientView* client_view) {
- client_view_ = client_view;
- AddChildView(client_view_);
-}
-
gfx::Rect ConstrainedWindowNonClientView::CalculateClientAreaBounds(
int width,
int height) const {
@@ -578,15 +566,9 @@ int ConstrainedWindowNonClientView::NonClientHitTest(const gfx::Point& point) {
// First see if it's within the grow box area, since that overlaps the client
// bounds.
- if (client_view_->PointIsInSizeBox(point))
- return HTBOTTOMRIGHT;
-
- // Then see if it's within the client area.
- if (client_view_) {
- client_view_->GetBounds(&bounds);
- if (bounds.PtInRect(test_point))
- return HTCLIENT;
- }
+ int component = container_->client_view()->NonClientHitTest(point);
+ if (component != HTNOWHERE)
+ return component;
// Then see if the point is within any of the window controls.
close_button_->GetBounds(&bounds);
@@ -596,10 +578,10 @@ int ConstrainedWindowNonClientView::NonClientHitTest(const gfx::Point& point) {
if (bounds.PtInRect(test_point))
return HTSYSMENU;
- int component = GetHTComponentForFrame(point, kResizeAreaSize,
- kResizeAreaCornerSize,
- kResizeAreaNorthSize,
- window_delegate_->CanResize());
+ component = GetHTComponentForFrame(point, kResizeAreaSize,
+ kResizeAreaCornerSize,
+ kResizeAreaNorthSize,
+ window_delegate_->CanResize());
if (component == HTNOWHERE) {
// Finally fall back to the caption.
GetBounds(&bounds, APPLY_MIRRORING_TRANSFORMATION);
@@ -692,26 +674,28 @@ void ConstrainedWindowNonClientView::Layout() {
location_bar_height);
location_bar_->Layout();
}
- if (client_view_)
- client_view_->SetBounds(client_bounds_.ToRECT());
+ container_->client_view()->SetBounds(client_bounds_.ToRECT());
}
void ConstrainedWindowNonClientView::GetPreferredSize(CSize* out) {
DCHECK(out);
- if (client_view_) {
- client_view_->GetPreferredSize(out);
- out->cx += 2 * kWindowHorizontalBorderSize;
- out->cy += CalculateNonClientHeight(ShouldDisplayURLField()) +
- kWindowVerticalBorderSize;
- }
+ container_->client_view()->GetPreferredSize(out);
+ out->cx += 2 * kWindowHorizontalBorderSize;
+ out->cy += CalculateNonClientHeight(ShouldDisplayURLField()) +
+ kWindowVerticalBorderSize;
}
void ConstrainedWindowNonClientView::ViewHierarchyChanged(bool is_add,
View *parent,
View *child) {
- if (is_add && location_bar_ && GetViewContainer() &&
- !(location_bar_->IsInitialized())) {
- location_bar_->Init();
+ if (is_add && GetViewContainer()) {
+ // Add our Client View as we are added to the ViewContainer so that if we
+ // are subsequently resized all the parent-child relationships are
+ // established.
+ if (is_add && GetViewContainer() && child == this)
+ AddChildView(container_->client_view());
+ if (location_bar_ && !location_bar_->IsInitialized())
+ location_bar_->Init();
}
}
diff --git a/chrome/browser/views/constrained_window_impl.h b/chrome/browser/views/constrained_window_impl.h
index 9e8c0b3..31a6d04 100644
--- a/chrome/browser/views/constrained_window_impl.h
+++ b/chrome/browser/views/constrained_window_impl.h
@@ -32,12 +32,15 @@
#include "chrome/browser/constrained_window.h"
#include "chrome/browser/tab_contents_delegate.h"
-#include "chrome/views/client_view.h"
#include "chrome/views/custom_frame_window.h"
class ConstrainedTabContentsWindowDelegate;
class ConstrainedWindowAnimation;
class ConstrainedWindowNonClientView;
+namespace ChromeViews {
+class HWNDView;
+class WindowDelegate;
+}
///////////////////////////////////////////////////////////////////////////////
// ConstrainedWindowImpl
@@ -123,6 +126,8 @@ class ConstrainedWindowImpl : public ConstrainedWindow,
virtual void OnWindowPosChanged(WINDOWPOS* window_pos);
private:
+ friend class ConstrainedWindow;
+
// Use the static factory methods on ConstrainedWindow to construct a
// ConstrainedWindow.
ConstrainedWindowImpl(TabContents* owner,
@@ -132,8 +137,6 @@ class ConstrainedWindowImpl : public ConstrainedWindow,
ChromeViews::WindowDelegate* window_delegate);
void Init(TabContents* owner);
- friend class ConstrainedWindow;
-
// Called after changing either the anchor point or titlebar
// visibility of a suppressed popup. This does the actual resizing.
//
diff --git a/chrome/browser/views/edit_keyword_controller.cc b/chrome/browser/views/edit_keyword_controller.cc
index 8fe9b00..982b6d2 100644
--- a/chrome/browser/views/edit_keyword_controller.cc
+++ b/chrome/browser/views/edit_keyword_controller.cc
@@ -81,7 +81,7 @@ void EditKeywordController::Show() {
ChromeViews::Window::CreateChromeWindow(::IsWindow(parent_) ? parent_ : NULL,
gfx::Rect(), this);
window()->Show();
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
title_tf_->SelectAll();
title_tf_->RequestFocus();
}
@@ -183,7 +183,7 @@ ChromeViews::View* EditKeywordController::GetContentsView() {
void EditKeywordController::ContentsChanged(TextField* sender,
const std::wstring& new_contents) {
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
UpdateImageViews();
}
diff --git a/chrome/browser/views/first_run_view_base.cc b/chrome/browser/views/first_run_view_base.cc
index 4ee8aceb..9f8044c 100644
--- a/chrome/browser/views/first_run_view_base.cc
+++ b/chrome/browser/views/first_run_view_base.cc
@@ -180,12 +180,9 @@ int FirstRunViewBase::GetDefaultImportItems() const {
void FirstRunViewBase::DisableButtons() {
window()->EnableClose(false);
- ChromeViews::ClientView* cv =
- reinterpret_cast<ChromeViews::ClientView*>(GetParent());
- if (cv) {
- cv->ok_button()->SetEnabled(false);
- cv->cancel_button()->SetEnabled(false);
- }
+ ChromeViews::DialogClientView* dcv = GetDialogClientView();
+ dcv->ok_button()->SetEnabled(false);
+ dcv->cancel_button()->SetEnabled(false);
}
bool FirstRunViewBase::CreateDesktopShortcut() {
diff --git a/chrome/browser/views/input_window.cc b/chrome/browser/views/input_window.cc
index f4c560e..2576139 100644
--- a/chrome/browser/views/input_window.cc
+++ b/chrome/browser/views/input_window.cc
@@ -131,7 +131,7 @@ ChromeViews::View* ContentView::GetContentsView() {
void ContentView::ContentsChanged(ChromeViews::TextField* sender,
const std::wstring& new_contents) {
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
}
///////////////////////////////////////////////////////////////////////////////
@@ -187,6 +187,6 @@ ChromeViews::Window* CreateInputWindow(HWND parent_hwnd,
ChromeViews::Window* window =
ChromeViews::Window::CreateChromeWindow(parent_hwnd, gfx::Rect(),
new ContentView(delegate));
- window->UpdateDialogButtons();
+ window->client_view()->AsDialogClientView()->UpdateDialogButtons();
return window;
}
diff --git a/chrome/browser/views/shelf_item_dialog.cc b/chrome/browser/views/shelf_item_dialog.cc
index 670453a..2c3de48 100644
--- a/chrome/browser/views/shelf_item_dialog.cc
+++ b/chrome/browser/views/shelf_item_dialog.cc
@@ -413,7 +413,7 @@ void ShelfItemDialog::ContentsChanged(ChromeViews::TextField* sender,
// so we reset the expected handle to an impossible value.
if (sender == title_field_)
expected_title_handle_ = 0;
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
}
bool ShelfItemDialog::Accept() {
@@ -493,7 +493,7 @@ void ShelfItemDialog::OnSelectionChanged() {
UTF8ToWide(url_table_model_->GetURL(selection).spec()));
if (title_field_)
title_field_->SetText(url_table_model_->GetTitle(selection));
- window()->UpdateDialogButtons();
+ GetDialogClientView()->UpdateDialogButtons();
}
}
diff --git a/chrome/views/custom_frame_window.cc b/chrome/views/custom_frame_window.cc
index 8c6bf98..28146b6 100644
--- a/chrome/views/custom_frame_window.cc
+++ b/chrome/views/custom_frame_window.cc
@@ -49,7 +49,7 @@ namespace ChromeViews {
HCURSOR CustomFrameWindow::resize_cursors_[6];
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// WindowResources
//
// An enumeration of bitmap resources used by this window.
@@ -222,7 +222,7 @@ SkBitmap* InactiveWindowResources::standard_frame_bitmaps_[];
ChromeFont InactiveWindowResources::title_font_;
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
//
// DefaultNonClientView
//
@@ -237,7 +237,6 @@ class DefaultNonClientView : public NonClientView,
virtual ~DefaultNonClientView();
// Overridden from CustomFrameWindow::NonClientView:
- virtual void Init(ClientView* client_view);
virtual gfx::Rect CalculateClientAreaBounds(int width, int height) const;
virtual gfx::Size CalculateWindowSizeForClientSize(int width,
int height) const;
@@ -250,6 +249,7 @@ class DefaultNonClientView : public NonClientView,
virtual void Paint(ChromeCanvas* canvas);
virtual void Layout();
virtual void GetPreferredSize(CSize* out);
+ virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
// BaseButton::ButtonListener implementation:
virtual void ButtonPressed(BaseButton* sender);
@@ -327,7 +327,7 @@ static const int kResizeAreaCornerSize = 16;
static const int kWindowHorizontalBorderSize = 4;
static const int kWindowVerticalBorderSize = 4;
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// DefaultNonClientView, public:
DefaultNonClientView::DefaultNonClientView(
@@ -385,19 +385,9 @@ DefaultNonClientView::DefaultNonClientView(
DefaultNonClientView::~DefaultNonClientView() {
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// DefaultNonClientView, CustomFrameWindow::NonClientView implementation:
-void DefaultNonClientView::Init(ClientView* client_view) {
- client_view_ = client_view;
- AddChildView(client_view_);
- // TODO(beng): (Cleanup) this should mostly move down to Window, because
- // it'll be needed for that version too, but with a virtual
- // override here to update the NC view.
- SetWindowIcon(container_->window_delegate()->GetWindowIcon());
-}
-
-
gfx::Rect DefaultNonClientView::CalculateClientAreaBounds(
int width, int height) const {
int top_margin = CalculateContentsTop();
@@ -440,15 +430,9 @@ int DefaultNonClientView::NonClientHitTest(const gfx::Point& point) {
// First see if it's within the grow box area, since that overlaps the client
// bounds.
- if (client_view_->PointIsInSizeBox(point))
- return HTBOTTOMRIGHT;
-
- // Then see if it's within the client area.
- if (client_view_) {
- client_view_->GetBounds(&bounds, APPLY_MIRRORING_TRANSFORMATION);
- if (bounds.PtInRect(test_point))
- return HTCLIENT;
- }
+ int component = container_->client_view()->NonClientHitTest(point);
+ if (component != HTNOWHERE)
+ return component;
// Then see if the point is within any of the window controls.
close_button_->GetBounds(&bounds, APPLY_MIRRORING_TRANSFORMATION);
@@ -467,7 +451,7 @@ int DefaultNonClientView::NonClientHitTest(const gfx::Point& point) {
if (bounds.PtInRect(test_point))
return HTSYSMENU;
- int component = GetHTComponentForFrame(
+ component = GetHTComponentForFrame(
point,
kResizeAreaSize,
kResizeAreaCornerSize,
@@ -507,7 +491,7 @@ void DefaultNonClientView::EnableClose(bool enable) {
close_button_->SetEnabled(enable);
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// DefaultNonClientView, View overrides:
void DefaultNonClientView::Paint(ChromeCanvas* canvas) {
@@ -537,14 +521,21 @@ void DefaultNonClientView::Layout() {
void DefaultNonClientView::GetPreferredSize(CSize* out) {
DCHECK(out);
- if (client_view_) {
- client_view_->GetPreferredSize(out);
- out->cx += 2 * kWindowHorizontalBorderSize;
- out->cy += CalculateContentsTop() + kWindowVerticalBorderSize;
- }
+ container_->client_view()->GetPreferredSize(out);
+ out->cx += 2 * kWindowHorizontalBorderSize;
+ out->cy += CalculateContentsTop() + kWindowVerticalBorderSize;
}
-////////////////////////////////////////////////////////////////////////////////
+void DefaultNonClientView::ViewHierarchyChanged(bool is_add,
+ View* parent,
+ View* child) {
+ // Add our Client View as we are added to the ViewContainer so that if we are
+ // subsequently resized all the parent-child relationships are established.
+ if (is_add && GetViewContainer() && child == this)
+ AddChildView(container_->client_view());
+}
+
+///////////////////////////////////////////////////////////////////////////////
// DefaultNonClientView, BaseButton::ButtonListener implementation:
void DefaultNonClientView::ButtonPressed(BaseButton* sender) {
@@ -559,7 +550,7 @@ void DefaultNonClientView::ButtonPressed(BaseButton* sender) {
}
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// DefaultNonClientView, private:
void DefaultNonClientView::SetWindowIcon(SkBitmap window_icon) {
@@ -650,7 +641,7 @@ void DefaultNonClientView::PaintClientEdge(ChromeCanvas* canvas) {
SkBitmap* left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT);
CRect client_area_bounds;
- client_view_->GetBounds(&client_area_bounds);
+ container_->client_view()->GetBounds(&client_area_bounds);
canvas->DrawBitmapInt(*top_left, client_area_bounds.left - top_left->width(),
client_area_bounds.top - top->height());
@@ -822,11 +813,9 @@ void DefaultNonClientView::LayoutTitleBar() {
}
void DefaultNonClientView::LayoutClientView() {
- if (client_view_) {
- gfx::Rect client_bounds(
- CalculateClientAreaBounds(GetWidth(), GetHeight()));
- client_view_->SetBounds(client_bounds.ToRECT());
- }
+ gfx::Rect client_bounds(
+ CalculateClientAreaBounds(GetWidth(), GetHeight()));
+ container_->client_view()->SetBounds(client_bounds.ToRECT());
}
// static
@@ -839,7 +828,7 @@ void DefaultNonClientView::InitClass() {
}
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// CustomFrameWindow, public:
CustomFrameWindow::CustomFrameWindow(WindowDelegate* window_delegate)
@@ -859,25 +848,33 @@ CustomFrameWindow::CustomFrameWindow(WindowDelegate* window_delegate,
CustomFrameWindow::~CustomFrameWindow() {
}
-void CustomFrameWindow::Init(HWND owner, const gfx::Rect& bounds) {
- Window::Init(owner, bounds);
- // We need to re-parent the client view to the non-client view.
- GetRootView()->RemoveChildView(client_view_);
- GetRootView()->AddChildView(non_client_view_);
- non_client_view_->Init(client_view_);
- GetRootView()->Layout();
-
- ResetWindowRegion();
-}
-
void CustomFrameWindow::ExecuteSystemMenuCommand(int command) {
if (command)
SendMessage(GetHWND(), WM_SYSCOMMAND, command, 0);
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// CustomFrameWindow, Window overrides:
+void CustomFrameWindow::Init(HWND parent, const gfx::Rect& bounds) {
+ // TODO(beng): (Cleanup) Right now, the only way to specify a different
+ // non-client view is to subclass this object and provide one
+ // by setting this member before calling Init.
+ if (!non_client_view_)
+ non_client_view_ = new DefaultNonClientView(this);
+ Window::Init(parent, bounds);
+ ResetWindowRegion();
+}
+
+void CustomFrameWindow::SetClientView(ClientView* client_view) {
+ DCHECK(client_view && !client_view_ && GetHWND());
+ client_view_ = client_view;
+ // For a CustomFrameWindow, the non-client view is the root.
+ HWNDViewContainer::SetContentsView(non_client_view_);
+ // When the non client view is added to the view hierarchy, it will cause the
+ // client view to be added as well.
+}
+
gfx::Size CustomFrameWindow::CalculateWindowSizeForClientSize(
const gfx::Size& client_size) const {
return non_client_view_->CalculateWindowSizeForClientSize(
@@ -906,7 +903,7 @@ void CustomFrameWindow::SizeWindowToDefault() {
window_size.ToSIZE(), false);
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// CustomFrameWindow, HWNDViewContainer overrides:
static void EnableMenuItem(HMENU menu, UINT command, bool enabled) {
@@ -1161,7 +1158,7 @@ void CustomFrameWindow::OnSize(UINT param, const CSize& size) {
ResetWindowRegion();
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// CustomFrameWindow, private:
void CustomFrameWindow::RunSystemMenu(const CPoint& point) {
diff --git a/chrome/views/dialog_client_view.cc b/chrome/views/dialog_client_view.cc
new file mode 100644
index 0000000..0ce9293
--- /dev/null
+++ b/chrome/views/dialog_client_view.cc
@@ -0,0 +1,410 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <windows.h>
+#include <uxtheme.h>
+#include <vsstyle.h>
+
+#include "chrome/views/dialog_client_view.h"
+
+#include "base/gfx/native_theme.h"
+#include "chrome/browser/standard_layout.h"
+#include "chrome/common/gfx/chrome_canvas.h"
+#include "chrome/common/gfx/chrome_font.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/common/win_util.h"
+#include "chrome/views/dialog_delegate.h"
+#include "chrome/views/window.h"
+#include "generated_resources.h"
+
+namespace ChromeViews {
+
+namespace {
+
+// Updates any of the standard buttons according to the delegate.
+void UpdateButtonHelper(ChromeViews::NativeButton* button_view,
+ ChromeViews::DialogDelegate* delegate,
+ ChromeViews::DialogDelegate::DialogButton button) {
+ std::wstring label = delegate->GetDialogButtonLabel(button);
+ if (!label.empty())
+ button_view->SetLabel(label);
+ button_view->SetEnabled(delegate->IsDialogButtonEnabled(button));
+ button_view->SetVisible(delegate->IsDialogButtonVisible(button));
+}
+
+void FillViewWithSysColor(ChromeCanvas* canvas, View* view, COLORREF color) {
+ SkColor sk_color =
+ SkColorSetRGB(GetRValue(color), GetGValue(color), GetBValue(color));
+ canvas->FillRectInt(sk_color, 0, 0, view->GetWidth(), view->GetHeight());
+}
+
+// DialogButton ----------------------------------------------------------------
+
+// DialogButtons is used for the ok/cancel buttons of the window. DialogButton
+// forwrds AcceleratorPressed to the delegate.
+
+class DialogButton : public NativeButton {
+ public:
+ DialogButton(Window* owner,
+ DialogDelegate::DialogButton type,
+ const std::wstring& title,
+ bool is_default)
+ : NativeButton(title, is_default), owner_(owner), type_(type) {
+ }
+
+ // Overridden to forward to the delegate.
+ virtual bool AcceleratorPressed(const Accelerator& accelerator) {
+ if (!owner_->window_delegate()->AsDialogDelegate()->
+ AreAcceleratorsEnabled(type_)) {
+ return false;
+ }
+ return NativeButton::AcceleratorPressed(accelerator);
+ }
+
+ private:
+ Window* owner_;
+ const DialogDelegate::DialogButton type_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DialogButton);
+};
+
+} // namespace
+
+// static
+ChromeFont DialogClientView::dialog_button_font_;
+static const int kDialogMinButtonWidth = 75;
+static const int kDialogButtonLabelSpacing = 16;
+static const int kDialogButtonContentSpacing = 0;
+
+// The group used by the buttons. This name is chosen voluntarily big not to
+// conflict with other groups that could be in the dialog content.
+static const int kButtonGroup = 6666;
+
+///////////////////////////////////////////////////////////////////////////////
+// DialogClientView, public:
+
+DialogClientView::DialogClientView(Window* owner, View* contents_view)
+ : ClientView(owner, contents_view),
+ ok_button_(NULL),
+ cancel_button_(NULL),
+ extra_view_(NULL),
+ accepted_(false) {
+ InitClass();
+}
+
+DialogClientView::~DialogClientView() {
+}
+
+void DialogClientView::ShowDialogButtons() {
+ DialogDelegate* dd = GetDialogDelegate();
+ int buttons = dd->GetDialogButtons();
+ if (buttons & DialogDelegate::DIALOGBUTTON_OK && !ok_button_) {
+ std::wstring label =
+ dd->GetDialogButtonLabel(DialogDelegate::DIALOGBUTTON_OK);
+ if (label.empty())
+ label = l10n_util::GetString(IDS_OK);
+ ok_button_ = new DialogButton(
+ window(), DialogDelegate::DIALOGBUTTON_OK,
+ label,
+ (dd->GetDefaultDialogButton() & DialogDelegate::DIALOGBUTTON_OK) != 0);
+ ok_button_->SetListener(this);
+ ok_button_->SetGroup(kButtonGroup);
+ if (!cancel_button_)
+ ok_button_->AddAccelerator(Accelerator(VK_ESCAPE, false, false, false));
+ AddChildView(ok_button_);
+ }
+ if (buttons & DialogDelegate::DIALOGBUTTON_CANCEL && !cancel_button_) {
+ std::wstring label =
+ dd->GetDialogButtonLabel(DialogDelegate::DIALOGBUTTON_CANCEL);
+ if (label.empty()) {
+ if (buttons & DialogDelegate::DIALOGBUTTON_OK) {
+ label = l10n_util::GetString(IDS_CANCEL);
+ } else {
+ label = l10n_util::GetString(IDS_CLOSE);
+ }
+ }
+ cancel_button_ = new DialogButton(
+ window(), DialogDelegate::DIALOGBUTTON_CANCEL,
+ label,
+ (dd->GetDefaultDialogButton() & DialogDelegate::DIALOGBUTTON_CANCEL)
+ != 0);
+ cancel_button_->SetListener(this);
+ cancel_button_->SetGroup(kButtonGroup);
+ cancel_button_->AddAccelerator(Accelerator(VK_ESCAPE, false, false, false));
+ AddChildView(cancel_button_);
+ }
+
+ ChromeViews::View* extra_view = dd->GetExtraView();
+ if (extra_view && !extra_view_) {
+ extra_view_ = extra_view;
+ extra_view_->SetGroup(kButtonGroup);
+ AddChildView(extra_view_);
+ }
+ if (!buttons) {
+ // Register the escape key as an accelerator which will close the window
+ // if there are no dialog buttons.
+ AddAccelerator(Accelerator(VK_ESCAPE, false, false, false));
+ }
+}
+
+// Changing dialog labels will change button widths.
+void DialogClientView::UpdateDialogButtons() {
+ DialogDelegate* dd = GetDialogDelegate();
+ int buttons = dd->GetDialogButtons();
+
+ if (buttons & DialogDelegate::DIALOGBUTTON_OK)
+ UpdateButtonHelper(ok_button_, dd, DialogDelegate::DIALOGBUTTON_OK);
+
+ if (buttons & DialogDelegate::DIALOGBUTTON_CANCEL)
+ UpdateButtonHelper(cancel_button_, dd, DialogDelegate::DIALOGBUTTON_CANCEL);
+
+ LayoutDialogButtons();
+ SchedulePaint();
+}
+
+void DialogClientView::AcceptWindow() {
+ accepted_ = true;
+ if (GetDialogDelegate()->Accept(false))
+ window()->Close();
+}
+
+void DialogClientView::CancelWindow() {
+ // Call the standard Close handler, which checks with the delegate before
+ // proceeding. This checking _isn't_ done here, but in the WM_CLOSE handler,
+ // so that the close box on the window also shares this code path.
+ window()->Close();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// DialogClientView, ClientView overrides:
+
+bool DialogClientView::CanClose() const {
+ DialogDelegate* dd = GetDialogDelegate();
+ int buttons = dd->GetDialogButtons();
+ if (buttons & DialogDelegate::DIALOGBUTTON_CANCEL)
+ return dd->Cancel();
+ if (buttons & DialogDelegate::DIALOGBUTTON_OK)
+ return dd->Accept(true);
+ return true;
+}
+
+int DialogClientView::NonClientHitTest(const gfx::Point& point) {
+ if (size_box_bounds_.Contains(point.x() - GetX(), point.y() - GetY()))
+ return HTBOTTOMRIGHT;
+ return ClientView::NonClientHitTest(point);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DialogClientView, View overrides:
+
+void DialogClientView::Paint(ChromeCanvas* canvas) {
+ FillViewWithSysColor(canvas, this, GetSysColor(COLOR_3DFACE));
+}
+
+void DialogClientView::PaintChildren(ChromeCanvas* canvas) {
+ View::PaintChildren(canvas);
+ if (!window()->IsMaximized() && !window()->IsMinimized())
+ PaintSizeBox(canvas);
+}
+
+void DialogClientView::Layout() {
+ if (has_dialog_buttons())
+ LayoutDialogButtons();
+ LayoutContentsView();
+}
+
+void DialogClientView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
+ if (is_add && child == this) {
+ // Can only add and update the dialog buttons _after_ they are added to the
+ // view hierarchy since they are native controls and require the
+ // ViewContainer's HWND.
+ ShowDialogButtons();
+ ClientView::ViewHierarchyChanged(is_add, parent, child);
+ UpdateDialogButtons();
+ Layout();
+ }
+}
+
+void DialogClientView::DidChangeBounds(const CRect& prev, const CRect& next) {
+ Layout();
+}
+
+void DialogClientView::GetPreferredSize(CSize* out) {
+ DCHECK(out);
+ contents_view()->GetPreferredSize(out);
+ int button_height = 0;
+ if (has_dialog_buttons()) {
+ if (cancel_button_)
+ button_height = cancel_button_->GetHeight();
+ else
+ button_height = ok_button_->GetHeight();
+ // Account for padding above and below the button.
+ button_height += kDialogButtonContentSpacing + kButtonVEdgeMargin;
+ }
+ out->cy += button_height;
+}
+
+bool DialogClientView::AcceleratorPressed(const Accelerator& accelerator) {
+ DCHECK(accelerator.GetKeyCode() == VK_ESCAPE); // We only expect Escape key.
+ window()->Close();
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DialogClientView, NativeButton::Listener implementation:
+
+void DialogClientView::ButtonPressed(NativeButton* sender) {
+ if (sender == ok_button_) {
+ AcceptWindow();
+ } else if (sender == cancel_button_) {
+ CancelWindow();
+ } else {
+ NOTREACHED();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DialogClientView, private:
+
+void DialogClientView::PaintSizeBox(ChromeCanvas* canvas) {
+ if (window()->window_delegate()->CanResize() ||
+ window()->window_delegate()->CanMaximize()) {
+ HDC dc = canvas->beginPlatformPaint();
+ SIZE gripper_size = { 0, 0 };
+ gfx::NativeTheme::instance()->GetThemePartSize(
+ gfx::NativeTheme::STATUS, dc, SP_GRIPPER, 1, NULL, TS_TRUE,
+ &gripper_size);
+
+ // TODO(beng): (http://b/1085509) In "classic" rendering mode, there isn't
+ // a theme-supplied gripper. We should probably improvise
+ // something, which would also require changing |gripper_size|
+ // to have different default values, too...
+ CRect gripper_bounds;
+ GetLocalBounds(&gripper_bounds, false);
+ gripper_bounds.left = gripper_bounds.right - gripper_size.cx;
+ gripper_bounds.top = gripper_bounds.bottom - gripper_size.cy;
+ size_box_bounds_ = gripper_bounds;
+ gfx::NativeTheme::instance()->PaintStatusGripper(
+ dc, SP_PANE, 1, 0, gripper_bounds);
+ canvas->endPlatformPaint();
+ }
+}
+
+int DialogClientView::GetButtonWidth(int button) const {
+ DialogDelegate* dd = GetDialogDelegate();
+ std::wstring button_label = dd->GetDialogButtonLabel(
+ static_cast<DialogDelegate::DialogButton>(button));
+ int string_width = dialog_button_font_.GetStringWidth(button_label);
+ return std::max(string_width + kDialogButtonLabelSpacing,
+ kDialogMinButtonWidth);
+}
+
+int DialogClientView::GetButtonsHeight() const {
+ if (has_dialog_buttons()) {
+ if (cancel_button_)
+ return cancel_button_->GetHeight() + kDialogButtonContentSpacing;
+ return ok_button_->GetHeight() + kDialogButtonContentSpacing;
+ }
+ return 0;
+}
+
+void DialogClientView::LayoutDialogButtons() {
+ CRect extra_bounds;
+ if (cancel_button_) {
+ CSize ps;
+ cancel_button_->GetPreferredSize(&ps);
+ CRect lb;
+ GetLocalBounds(&lb, false);
+ int button_width = GetButtonWidth(DialogDelegate::DIALOGBUTTON_CANCEL);
+ CRect bounds;
+ bounds.left = lb.right - button_width - kButtonHEdgeMargin;
+ bounds.top = lb.bottom - ps.cy - kButtonVEdgeMargin;
+ bounds.right = bounds.left + button_width;
+ bounds.bottom = bounds.top + ps.cy;
+ cancel_button_->SetBounds(bounds);
+ // The extra view bounds are dependent on this button.
+ extra_bounds.right = bounds.left;
+ extra_bounds.top = bounds.top;
+ }
+ if (ok_button_) {
+ CSize ps;
+ ok_button_->GetPreferredSize(&ps);
+ CRect lb;
+ GetLocalBounds(&lb, false);
+ int button_width = GetButtonWidth(DialogDelegate::DIALOGBUTTON_OK);
+ int ok_button_right = lb.right - kButtonHEdgeMargin;
+ if (cancel_button_)
+ ok_button_right = cancel_button_->GetX() - kRelatedButtonHSpacing;
+ CRect bounds;
+ bounds.left = ok_button_right - button_width;
+ bounds.top = lb.bottom - ps.cy - kButtonVEdgeMargin;
+ bounds.right = ok_button_right;
+ bounds.bottom = bounds.top + ps.cy;
+ ok_button_->SetBounds(bounds);
+ // The extra view bounds are dependent on this button.
+ extra_bounds.right = bounds.left;
+ extra_bounds.top = bounds.top;
+ }
+ if (extra_view_) {
+ CSize ps;
+ extra_view_->GetPreferredSize(&ps);
+ CRect lb;
+ GetLocalBounds(&lb, false);
+ extra_bounds.left = lb.left + kButtonHEdgeMargin;
+ extra_bounds.bottom = extra_bounds.top + ps.cy;
+ extra_view_->SetBounds(extra_bounds);
+ }
+}
+
+void DialogClientView::LayoutContentsView() {
+ CRect lb;
+ GetLocalBounds(&lb, false);
+ lb.bottom = std::max(0, static_cast<int>(lb.bottom - GetButtonsHeight()));
+ contents_view()->SetBounds(lb);
+ contents_view()->Layout();
+}
+
+DialogDelegate* DialogClientView::GetDialogDelegate() const {
+ DialogDelegate* dd = window()->window_delegate()->AsDialogDelegate();
+ DCHECK(dd);
+ return dd;
+}
+
+// static
+void DialogClientView::InitClass() {
+ static bool initialized = false;
+ if (!initialized) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ dialog_button_font_ = rb.GetFont(ResourceBundle::BaseFont);
+ initialized = true;
+ }
+}
+
+}
diff --git a/chrome/views/dialog_client_view.h b/chrome/views/dialog_client_view.h
new file mode 100644
index 0000000..b2b7c6c
--- /dev/null
+++ b/chrome/views/dialog_client_view.h
@@ -0,0 +1,133 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CHROME_VIEWS_DIALOG_CLIENT_VIEW_H_
+#define CHROME_VIEWS_DIALOG_CLIENT_VIEW_H_
+
+#include "chrome/common/gfx/chrome_font.h"
+#include "chrome/views/client_view.h"
+#include "chrome/views/native_button.h"
+
+namespace ChromeViews {
+
+class DialogDelegate;
+class Window;
+
+///////////////////////////////////////////////////////////////////////////////
+// DialogClientView
+//
+// This ClientView subclass provides the content of a typical dialog box,
+// including a strip of buttons at the bottom right of the window, default
+// accelerator handlers for accept and cancel, and the ability for the
+// embedded contents view to provide extra UI to be shown in the row of
+// buttons.
+//
+class DialogClientView : public ClientView,
+ public NativeButton::Listener {
+ public:
+ DialogClientView(Window* window, View* contents_view);
+ virtual ~DialogClientView();
+
+ // Adds the dialog buttons required by the supplied WindowDelegate to the
+ // view.
+ void ShowDialogButtons();
+
+ // Updates the enabled state and label of the buttons required by the
+ // supplied WindowDelegate
+ void UpdateDialogButtons();
+
+ // Accept the changes made in the window that contains this ClientView.
+ void AcceptWindow();
+
+ // Cancel the changes made in the window that contains this ClientView.
+ void CancelWindow();
+
+ // Accessors in case the user wishes to adjust these buttons.
+ NativeButton* ok_button() const { return ok_button_; }
+ NativeButton* cancel_button() const { return cancel_button_; }
+
+ // Overridden from ClientView:
+ virtual bool CanClose() const;
+ virtual int NonClientHitTest(const gfx::Point& point);
+ virtual DialogClientView* AsDialogClientView() { return this; }
+
+ protected:
+ // View overrides:
+ virtual void Paint(ChromeCanvas* canvas);
+ virtual void PaintChildren(ChromeCanvas* canvas);
+ virtual void Layout();
+ virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
+ virtual void DidChangeBounds(const CRect& prev, const CRect& next);
+ virtual void GetPreferredSize(CSize* out);
+ virtual bool AcceleratorPressed(const Accelerator& accelerator);
+
+ // NativeButton::Listener implementation:
+ virtual void ButtonPressed(NativeButton* sender);
+
+ private:
+ // Paint the size box in the bottom right corner of the window if it is
+ // resizable.
+ void PaintSizeBox(ChromeCanvas* canvas);
+
+ // Returns the width of the specified dialog button using the correct font.
+ int GetButtonWidth(int button) const;
+ int DialogClientView::GetButtonsHeight() const;
+
+ // Position and size various sub-views.
+ void LayoutDialogButtons();
+ void LayoutContentsView();
+
+ bool has_dialog_buttons() const { return ok_button_ || cancel_button_; }
+
+ // Returns the DialogDelegate for the window.
+ DialogDelegate* GetDialogDelegate() const;
+
+ // The dialog buttons.
+ NativeButton* ok_button_;
+ NativeButton* cancel_button_;
+
+ // The button-level extra view, NULL unless the dialog delegate supplies one.
+ View* extra_view_;
+
+ // The layout rect of the size box, when visible.
+ gfx::Rect size_box_bounds_;
+
+ // True if the window was Accepted by the user using the OK button.
+ bool accepted_;
+
+ // Static resource initialization
+ static void InitClass();
+ static ChromeFont dialog_button_font_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DialogClientView);
+};
+
+}
+
+#endif // #ifndef CHROME_VIEWS_DIALOG_CLIENT_VIEW_H_
diff --git a/chrome/views/dialog_delegate.h b/chrome/views/dialog_delegate.h
index 2dc48e6..9ca4ade 100644
--- a/chrome/views/dialog_delegate.h
+++ b/chrome/views/dialog_delegate.h
@@ -30,6 +30,7 @@
#ifndef CHROME_VIEWS_DIALOG_DELEGATE_H__
#define CHROME_VIEWS_DIALOG_DELEGATE_H__
+#include "chrome/views/dialog_client_view.h"
#include "chrome/views/window_delegate.h"
namespace ChromeViews {
@@ -119,6 +120,31 @@ class DialogDelegate : public WindowDelegate {
// instead.
virtual bool Accept(bool window_closing) { return Accept(); }
virtual bool Accept() { return true; }
+
+ // Overridden from WindowDelegate:
+ virtual View* GetInitiallyFocusedView() const {
+ // Try to focus the OK then the Cancel button if present.
+ DialogClientView* dcv = GetDialogClientView();
+ if (GetDialogButtons() & DIALOGBUTTON_OK)
+ return dcv->ok_button();
+ if (GetDialogButtons() & DIALOGBUTTON_CANCEL)
+ return dcv->cancel_button();
+ return NULL;
+ }
+
+ // Overridden from WindowDelegate:
+ virtual ClientView* CreateClientView(Window* window) {
+ return new DialogClientView(window, GetContentsView());
+ }
+
+ // A helper for accessing the DialogClientView object contained by this
+ // delegate's Window.
+ DialogClientView* GetDialogClientView() const {
+ ClientView* client_view = window()->client_view();
+ DialogClientView* dialog_client_view = client_view->AsDialogClientView();
+ DCHECK(dialog_client_view);
+ return dialog_client_view;
+ }
};
} // namespace ChromeViews
diff --git a/chrome/views/views.vcproj b/chrome/views/views.vcproj
index 928ae37..4baf1be 100644
--- a/chrome/views/views.vcproj
+++ b/chrome/views/views.vcproj
@@ -278,6 +278,14 @@
>
</File>
<File
+ RelativePath=".\dialog_client_view.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\dialog_client_view.h"
+ >
+ </File>
+ <File
RelativePath=".\dialog_delegate.h"
>
</File>
diff --git a/chrome/views/window.cc b/chrome/views/window.cc
index 042968b..4243994 100644
--- a/chrome/views/window.cc
+++ b/chrome/views/window.cc
@@ -36,7 +36,6 @@
#include "chrome/common/pref_service.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/win_util.h"
-#include "chrome/views/client_view.h"
#include "chrome/views/custom_frame_window.h"
#include "chrome/views/window_delegate.h"
@@ -65,8 +64,6 @@ Window::Window(WindowDelegate* window_delegate)
is_modal_(false),
restored_enabled_(false),
is_always_on_top_(false),
- use_client_view_(true),
- accepted_(false),
window_closed_(false) {
InitClass();
DCHECK(window_delegate_);
@@ -112,33 +109,25 @@ void Window::Init(HWND parent, const gfx::Rect& bounds) {
if (window_ex_style() == 0)
set_window_ex_style(CalculateWindowExStyle());
- // A child window never owns its own focus manager, it uses the one
- // associated with the root of the window tree...
- if (use_client_view_) {
- View* contents_view = window_delegate_->GetContentsView();
- DCHECK(contents_view);
- client_view_ = new ClientView(this, contents_view);
- // A Window almost always owns its own focus manager, even if it's a child
- // window. File a bug if you find a circumstance where this isn't the case
- // and we can adjust this API. Note that if this is not the case, you'll
- // also have to change SetInitialFocus() as it relies on the window's focus
- // manager.
- HWNDViewContainer::Init(parent, bounds, true);
- SetContentsView(client_view_);
- } else {
- HWNDViewContainer::Init(parent, bounds, true);
- SetContentsView(window_delegate_->GetContentsView());
- }
+ HWNDViewContainer::Init(parent, bounds, true);
win_util::SetWindowUserData(GetHWND(), this);
std::wstring window_title = window_delegate_->GetWindowTitle();
SetWindowText(GetHWND(), window_title.c_str());
+
+ SetClientView(window_delegate_->CreateClientView(this));
SetInitialBounds(bounds);
if (window_delegate_->HasAlwaysOnTopMenu())
AddAlwaysOnTopSystemMenuItem();
}
+void Window::SetClientView(ClientView* client_view) {
+ DCHECK(client_view && !client_view_ && GetHWND());
+ client_view_ = client_view;
+ HWNDViewContainer::SetContentsView(client_view_);
+}
+
gfx::Size Window::CalculateWindowSizeForClientSize(
const gfx::Size& client_size) const {
RECT r = { 0, 0, client_size.width(), client_size.height() };
@@ -197,24 +186,7 @@ void Window::Close() {
return;
}
- bool can_close = true;
- // Ask the delegate if we're allowed to close. The user may not have left the
- // window in a state where this is allowable (e.g. unsaved work). Also, don't
- // call Cancel on the delegate if we've already been accepted and are in the
- // process of being closed. Furthermore, if we have only an OK button, but no
- // Cancel button, and we're closing without being accepted, call Accept to
- // see if we should close.
- if (!accepted_) {
- DialogDelegate* dd = window_delegate_->AsDialogDelegate();
- if (dd) {
- int buttons = dd->GetDialogButtons();
- if (buttons & DialogDelegate::DIALOGBUTTON_CANCEL)
- can_close = dd->Cancel();
- else if (buttons & DialogDelegate::DIALOGBUTTON_OK)
- can_close = dd->Accept(true);
- }
- }
- if (can_close) {
+ if (client_view_->CanClose()) {
SaveWindowPosition();
RestoreEnabledIfNecessary();
HWNDViewContainer::Close();
@@ -256,27 +228,6 @@ void Window::EnableClose(bool enable) {
SWP_NOZORDER);
}
-void Window::UpdateDialogButtons() {
- if (client_view_)
- client_view_->UpdateDialogButtons();
-}
-
-void Window::AcceptWindow() {
- accepted_ = true;
- DialogDelegate* dd = window_delegate_->AsDialogDelegate();
- if (dd)
- accepted_ = dd->Accept(false);
- if (accepted_)
- Close();
-}
-
-void Window::CancelWindow() {
- // Call the standard Close handler, which checks with the delegate before
- // proceeding. This checking _isn't_ done here, but in the WM_CLOSE handler,
- // so that the close box on the window also shares this code path.
- Close();
-}
-
void Window::UpdateWindowTitle() {
std::wstring window_title = window_delegate_->GetWindowTitle();
SetWindowText(GetHWND(), window_title.c_str());
@@ -349,21 +300,19 @@ gfx::Size Window::GetLocalizedContentsSize(int col_resource_id,
return gfx::Size(width, height);
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// Window, protected:
void Window::SizeWindowToDefault() {
- if (client_view_) {
- CSize pref(0, 0);
- client_view_->GetPreferredSize(&pref);
- DCHECK(pref.cx > 0 && pref.cy > 0);
- // CenterAndSizeWindow adjusts the window size to accommodate the non-client
- // area.
- win_util::CenterAndSizeWindow(owning_window(), GetHWND(), pref, true);
- }
+ CSize pref(0, 0);
+ client_view_->GetPreferredSize(&pref);
+ DCHECK(pref.cx > 0 && pref.cy > 0);
+ // CenterAndSizeWindow adjusts the window size to accommodate the non-client
+ // area.
+ win_util::CenterAndSizeWindow(owning_window(), GetHWND(), pref, true);
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// Window, HWNDViewContainer overrides:
void Window::OnActivate(UINT action, BOOL minimized, HWND window) {
@@ -390,12 +339,13 @@ LRESULT Window::OnEraseBkgnd(HDC dc) {
}
LRESULT Window::OnNCHitTest(const CPoint& point) {
- // We paint the size box over the content area sometimes... check to see if
- // the mouse is over it...
+ // First, give the ClientView a chance to test the point to see if it is part
+ // of the non-client area.
CPoint temp = point;
MapWindowPoints(HWND_DESKTOP, GetHWND(), &temp, 1);
- if (client_view_ && client_view_->PointIsInSizeBox(gfx::Point(temp)))
- return HTBOTTOMRIGHT;
+ int component = client_view_->NonClientHitTest(gfx::Point(temp));
+ if (component != HTNOWHERE)
+ return component;
// Otherwise, we let Windows do all the native frame non-client handling for
// us.
@@ -472,13 +422,6 @@ void Window::SetInitialFocus() {
bool focus_set = false;
ChromeViews::View* v = window_delegate_->GetInitiallyFocusedView();
- // For dialogs, try to focus either the OK or Cancel buttons if any.
- if (!v && window_delegate_->AsDialogDelegate() && client_view_) {
- if (client_view_->ok_button())
- v = client_view_->ok_button();
- else if (client_view_->cancel_button())
- v = client_view_->cancel_button();
- }
if (v) {
focus_set = true;
// In order to make that view the initially focused one, we make it the
diff --git a/chrome/views/window.h b/chrome/views/window.h
index d6bb48e..534634c 100644
--- a/chrome/views/window.h
+++ b/chrome/views/window.h
@@ -114,35 +114,19 @@ class Window : public HWNDViewContainer {
virtual void EnableClose(bool enable);
WindowDelegate* window_delegate() const { return window_delegate_; }
- void set_window_delegate(WindowDelegate* delegate) {
- window_delegate_ = delegate;
- }
- // Set whether or not we should insert a client view. See comment below.
- void set_use_client_view(bool use_client_view) {
- use_client_view_ = use_client_view;
- }
+ // Returns the ClientView object used by this Window.
+ ClientView* client_view() const { return client_view_; }
void set_focus_on_creation(bool focus_on_creation) {
focus_on_creation_ = focus_on_creation;
}
- // Updates the enabled state and label of the dialog buttons visible in this
- // window.
- void UpdateDialogButtons();
-
- // Called when the window should be canceled or accepted, if it is a dialog
- // box.
- void AcceptWindow();
- void CancelWindow();
-
// Tell the window to update its title from the delegate.
virtual void UpdateWindowTitle();
// The parent of this window.
- HWND owning_window() const {
- return owning_hwnd_;
- }
+ HWND owning_window() const { return owning_hwnd_; }
// Convenience methods for storing/retrieving window location information
// to/from a PrefService using the specified |entry| name.
@@ -171,6 +155,16 @@ class Window : public HWNDViewContainer {
int row_resource_id);
protected:
+ // Sets the specified view as the ClientView of this Window. The ClientView
+ // is responsible for laying out the Window's contents view, as well as
+ // performing basic hit-testing, and perhaps other responsibilities depending
+ // on the implementation. The Window's view hierarchy takes ownership of the
+ // ClientView unless the ClientView specifies otherwise. This must be called
+ // only once, and after the native window has been created.
+ // This is called by Init. |client_view| cannot be NULL.
+ virtual void SetClientView(ClientView* client_view);
+
+ // Sizes the window to the default size specified by its ClientView.
virtual void SizeWindowToDefault();
// Overridden from HWNDViewContainer:
@@ -183,8 +177,9 @@ class Window : public HWNDViewContainer {
virtual void OnSize(UINT size_param, const CSize& new_size);
virtual void OnSysCommand(UINT notification_code, CPoint click);
- // The client view object that contains the client area of the window,
- // including optional dialog buttons.
+ // A ClientView object or subclass, responsible for sizing the contents view
+ // of the window, hit testing and perhaps other tasks depending on the
+ // implementation.
ClientView* client_view_;
// Our window delegate (see Init method for documentation).
@@ -249,17 +244,6 @@ class Window : public HWNDViewContainer {
// We need to own the text of the menu, the Windows API does not copy it.
std::wstring always_on_top_menu_text_;
- // Whether or not the client view should be inserted into the Window's view
- // hierarchy.
- // TODO(beng): (Cleanup) This is probably a short term measure until I figure
- // out a way to make other Window subclasses (e.g.
- // ConstrainedWindowImpl) and their users jive with the new
- // dialog framework.
- bool use_client_view_;
-
- // True if the window was Accepted by the user using the OK button.
- bool accepted_;
-
// Set to true if the window is in the process of closing .
bool window_closed_;
diff --git a/chrome/views/window_delegate.h b/chrome/views/window_delegate.h
index 8f506d2..67990a0 100644
--- a/chrome/views/window_delegate.h
+++ b/chrome/views/window_delegate.h
@@ -35,6 +35,7 @@
#include <atlmisc.h>
#include <string>
+#include "chrome/views/client_view.h"
#include "chrome/views/window.h"
#include "skia/include/SkBitmap.h"
@@ -139,6 +140,12 @@ class WindowDelegate {
return NULL;
}
+ // Called by the Window to create the Client View used to host the contents
+ // of the window.
+ virtual ClientView* CreateClientView(Window* window) {
+ return new ClientView(window, GetContentsView());
+ }
+
// An accessor to the Window this delegate is bound to.
Window* window() const { return window_.get(); }