diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/views/about_chrome_view.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_editor_view.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/bug_report_view.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/clear_browsing_data.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/constrained_window_impl.cc | 56 | ||||
-rw-r--r-- | chrome/browser/views/constrained_window_impl.h | 9 | ||||
-rw-r--r-- | chrome/browser/views/edit_keyword_controller.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/first_run_view_base.cc | 9 | ||||
-rw-r--r-- | chrome/browser/views/input_window.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/shelf_item_dialog.cc | 4 | ||||
-rw-r--r-- | chrome/views/custom_frame_window.cc | 105 | ||||
-rw-r--r-- | chrome/views/dialog_client_view.cc | 410 | ||||
-rw-r--r-- | chrome/views/dialog_client_view.h | 133 | ||||
-rw-r--r-- | chrome/views/dialog_delegate.h | 26 | ||||
-rw-r--r-- | chrome/views/views.vcproj | 8 | ||||
-rw-r--r-- | chrome/views/window.cc | 103 | ||||
-rw-r--r-- | chrome/views/window.h | 48 | ||||
-rw-r--r-- | chrome/views/window_delegate.h | 7 |
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(); } |