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