input_window_dialog_win.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/input_window_dialog.h" 6 7#include "base/compiler_specific.h" 8#include "base/message_loop.h" 9#include "base/task.h" 10#include "views/grid_layout.h" 11#include "views/controls/label.h" 12#include "views/controls/textfield/textfield.h" 13#include "views/standard_layout.h" 14#include "views/window/dialog_delegate.h" 15#include "views/window/window.h" 16#include "grit/generated_resources.h" 17 18// Width to make the text field, in pixels. 19static const int kTextfieldWidth = 200; 20 21class ContentView; 22 23// The Windows implementation of the cross platform input dialog interface. 24class WinInputWindowDialog : public InputWindowDialog { 25 public: 26 WinInputWindowDialog(HWND parent, 27 const std::wstring& window_title, 28 const std::wstring& label, 29 const std::wstring& contents, 30 Delegate* delegate); 31 virtual ~WinInputWindowDialog(); 32 33 virtual void Show(); 34 virtual void Close(); 35 36 const std::wstring& window_title() const { return window_title_; } 37 const std::wstring& label() const { return label_; } 38 const std::wstring& contents() const { return contents_; } 39 40 InputWindowDialog::Delegate* delegate() { return delegate_.get(); } 41 42 private: 43 // Our chrome views window. 44 views::Window* window_; 45 46 // Strings to feed to the on screen window. 47 std::wstring window_title_; 48 std::wstring label_; 49 std::wstring contents_; 50 51 // Our delegate. Consumes the window's output. 52 scoped_ptr<InputWindowDialog::Delegate> delegate_; 53}; 54 55// ContentView, as the name implies, is the content view for the InputWindow. 56// It registers accelerators that accept/cancel the input. 57class ContentView : public views::View, 58 public views::DialogDelegate, 59 public views::Textfield::Controller { 60 public: 61 explicit ContentView(WinInputWindowDialog* delegate) 62 : delegate_(delegate), 63 ALLOW_THIS_IN_INITIALIZER_LIST(focus_grabber_factory_(this)) { 64 DCHECK(delegate_); 65 } 66 67 // views::DialogDelegate overrides: 68 virtual bool IsDialogButtonEnabled( 69 MessageBoxFlags::DialogButton button) const; 70 virtual bool Accept(); 71 virtual bool Cancel(); 72 virtual void DeleteDelegate(); 73 virtual std::wstring GetWindowTitle() const; 74 virtual bool IsModal() const { return true; } 75 virtual views::View* GetContentsView(); 76 77 // views::Textfield::Controller overrides: 78 virtual void ContentsChanged(views::Textfield* sender, 79 const std::wstring& new_contents); 80 virtual bool HandleKeystroke(views::Textfield*, 81 const views::Textfield::Keystroke&) { 82 return false; 83 } 84 85 protected: 86 // views::View overrides: 87 virtual void ViewHierarchyChanged(bool is_add, views::View* parent, 88 views::View* child); 89 90 private: 91 // Set up dialog controls and layout. 92 void InitControlLayout(); 93 94 // Sets focus to the first focusable element within the dialog. 95 void FocusFirstFocusableControl(); 96 97 // The Textfield that the user can type into. 98 views::Textfield* text_field_; 99 100 // The delegate that the ContentView uses to communicate changes to the 101 // caller. 102 WinInputWindowDialog* delegate_; 103 104 // Helps us set focus to the first Textfield in the window. 105 ScopedRunnableMethodFactory<ContentView> focus_grabber_factory_; 106 107 DISALLOW_COPY_AND_ASSIGN(ContentView); 108}; 109 110/////////////////////////////////////////////////////////////////////////////// 111// ContentView, views::DialogDelegate implementation: 112 113bool ContentView::IsDialogButtonEnabled( 114 MessageBoxFlags::DialogButton button) const { 115 if (button == MessageBoxFlags::DIALOGBUTTON_OK && 116 !delegate_->delegate()->IsValid(text_field_->text())) { 117 return false; 118 } 119 return true; 120} 121 122bool ContentView::Accept() { 123 delegate_->delegate()->InputAccepted(text_field_->text()); 124 return true; 125} 126 127bool ContentView::Cancel() { 128 delegate_->delegate()->InputCanceled(); 129 return true; 130} 131 132void ContentView::DeleteDelegate() { 133 delete delegate_; 134} 135 136std::wstring ContentView::GetWindowTitle() const { 137 return delegate_->window_title(); 138} 139 140views::View* ContentView::GetContentsView() { 141 return this; 142} 143 144/////////////////////////////////////////////////////////////////////////////// 145// ContentView, views::Textfield::Controller implementation: 146 147void ContentView::ContentsChanged(views::Textfield* sender, 148 const std::wstring& new_contents) { 149 GetDialogClientView()->UpdateDialogButtons(); 150} 151 152/////////////////////////////////////////////////////////////////////////////// 153// ContentView, protected: 154 155void ContentView::ViewHierarchyChanged(bool is_add, 156 views::View* parent, 157 views::View* child) { 158 if (is_add && child == this) 159 InitControlLayout(); 160} 161 162/////////////////////////////////////////////////////////////////////////////// 163// ContentView, private: 164 165void ContentView::InitControlLayout() { 166 text_field_ = new views::Textfield; 167 text_field_->SetText(delegate_->contents()); 168 text_field_->SetController(this); 169 170 using views::ColumnSet; 171 using views::GridLayout; 172 173 // TODO(sky): Vertical alignment should be baseline. 174 GridLayout* layout = CreatePanelGridLayout(this); 175 SetLayoutManager(layout); 176 177 ColumnSet* c1 = layout->AddColumnSet(0); 178 c1->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 179 GridLayout::USE_PREF, 0, 0); 180 c1->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); 181 c1->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, 182 GridLayout::USE_PREF, kTextfieldWidth, kTextfieldWidth); 183 184 layout->StartRow(0, 0); 185 views::Label* label = new views::Label(delegate_->label()); 186 layout->AddView(label); 187 layout->AddView(text_field_); 188 189 MessageLoop::current()->PostTask(FROM_HERE, 190 focus_grabber_factory_.NewRunnableMethod( 191 &ContentView::FocusFirstFocusableControl)); 192} 193 194void ContentView::FocusFirstFocusableControl() { 195 text_field_->SelectAll(); 196 text_field_->RequestFocus(); 197} 198 199WinInputWindowDialog::WinInputWindowDialog(HWND parent, 200 const std::wstring& window_title, 201 const std::wstring& label, 202 const std::wstring& contents, 203 Delegate* delegate) 204 : window_title_(window_title), 205 label_(label), 206 contents_(contents), 207 delegate_(delegate) { 208 window_ = views::Window::CreateChromeWindow(parent, gfx::Rect(), 209 new ContentView(this)); 210 window_->GetClientView()->AsDialogClientView()->UpdateDialogButtons(); 211} 212 213WinInputWindowDialog::~WinInputWindowDialog() { 214} 215 216void WinInputWindowDialog::Show() { 217 window_->Show(); 218} 219 220void WinInputWindowDialog::Close() { 221 window_->Close(); 222} 223 224// static 225InputWindowDialog* InputWindowDialog::Create(HWND parent, 226 const std::wstring& window_title, 227 const std::wstring& label, 228 const std::wstring& contents, 229 Delegate* delegate) { 230 return new WinInputWindowDialog(parent, 231 window_title, 232 label, 233 contents, 234 delegate); 235} 236