summaryrefslogtreecommitdiffstats
path: root/chrome/views/controls/button/native_button.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/views/controls/button/native_button.cc')
-rw-r--r--chrome/views/controls/button/native_button.cc212
1 files changed, 212 insertions, 0 deletions
diff --git a/chrome/views/controls/button/native_button.cc b/chrome/views/controls/button/native_button.cc
new file mode 100644
index 0000000..4da39407
--- /dev/null
+++ b/chrome/views/controls/button/native_button.cc
@@ -0,0 +1,212 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/views/controls/button/native_button.h"
+
+#include "base/logging.h"
+#include "chrome/common/gfx/chrome_canvas.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/views/background.h"
+
+namespace views {
+
+const char NativeButton::kViewClassName[] = "chrome/views/NativeButton";
+
+NativeButton::NativeButton(const std::wstring& label)
+ : enforce_dlu_min_size_(true) {
+ Init(label, false);
+}
+
+NativeButton::NativeButton(const std::wstring& label, bool is_default)
+ : enforce_dlu_min_size_(true) {
+ Init(label, is_default);
+}
+
+NativeButton::~NativeButton() {
+}
+
+std::string NativeButton::GetClassName() const {
+ return kViewClassName;
+}
+
+void NativeButton::SetListener(Listener *l) {
+ listener_ = l;
+}
+
+void NativeButton::SetPadding(CSize size) {
+ padding_ = size;
+}
+
+gfx::Size NativeButton::GetPreferredSize() {
+ HWND hwnd = GetNativeControlHWND();
+ if (hwnd) {
+ SIZE sz = {0, 0};
+ ::SendMessage(hwnd,
+ BCM_GETIDEALSIZE,
+ 0,
+ reinterpret_cast<LPARAM>(&sz));
+ sz.cx += 2 * padding_.cx;
+ sz.cy += 2 * padding_.cy;
+
+ if (enforce_dlu_min_size_) {
+ if (min_dlu_size_.width()) {
+ sz.cx =
+ std::max(static_cast<int>(sz.cx),
+ font_.horizontal_dlus_to_pixels(min_dlu_size_.width()));
+ }
+ if (min_dlu_size_.height())
+ sz.cy = std::max(static_cast<int>(sz.cy),
+ font_.vertical_dlus_to_pixels(min_dlu_size_.height()));
+ }
+ return gfx::Size(sz.cx, sz.cy);
+ }
+ return gfx::Size();
+}
+
+void NativeButton::SetLabel(const std::wstring& l) {
+ // Even though we create a flipped HWND for a native button when the locale
+ // is right-to-left, Windows does not render text for the button using a
+ // right-to-left context (perhaps because the parent HWND is not flipped).
+ // The result is that RTL strings containing punctuation marks are not
+ // displayed properly. For example, the string "...ABC" (where A, B and C are
+ // Hebrew characters) is displayed as "ABC..." which is incorrect.
+ //
+ // In order to overcome this problem, we mark the localized Hebrew strings as
+ // RTL strings explicitly (using the appropriate Unicode formatting) so that
+ // Windows displays the text correctly regardless of the HWND hierarchy.
+ std::wstring localized_label;
+ if (l10n_util::AdjustStringForLocaleDirection(l, &localized_label))
+ label_.assign(localized_label);
+ else
+ label_.assign(l);
+
+ SetAccessibleName(l);
+ UpdateNativeButton();
+}
+
+const std::wstring NativeButton::GetLabel() const {
+ return label_;
+}
+
+HWND NativeButton::CreateNativeControl(HWND parent_container) {
+ DWORD flags = WS_CHILD | BS_PUSHBUTTON;
+ if (is_default_)
+ flags |= BS_DEFPUSHBUTTON;
+ HWND r = ::CreateWindowEx(GetAdditionalExStyle(), L"BUTTON", L"", flags, 0, 0,
+ width(), height(), parent_container, NULL,
+ NULL, NULL);
+ SendMessage(r, WM_SETFONT, reinterpret_cast<WPARAM>(font_.hfont()), FALSE);
+ ConfigureNativeButton(r);
+ return r;
+}
+
+LRESULT NativeButton::OnNotify(int w_param, LPNMHDR l_param) {
+ return 0;
+}
+
+LRESULT NativeButton::OnCommand(UINT code, int id, HWND source) {
+ if (code == BN_CLICKED)
+ Clicked();
+ return 0;
+}
+
+void NativeButton::UpdateNativeButton() {
+ HWND hwnd = GetNativeControlHWND();
+ if (hwnd)
+ ConfigureNativeButton(hwnd);
+}
+
+void NativeButton::ConfigureNativeButton(HWND hwnd) {
+ ::SetWindowText(hwnd, label_.c_str());
+}
+
+void NativeButton::SetDefaultButton(bool is_default_button) {
+ if (is_default_button == is_default_)
+ return;
+ is_default_ = is_default_button;
+ if (is_default_button)
+ AddAccelerator(Accelerator(VK_RETURN, false, false, false));
+ else
+ RemoveAccelerator(Accelerator(VK_RETURN, false, false, false));
+ SendMessage(GetNativeControlHWND(), BM_SETSTYLE,
+ is_default_button ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON, true);
+}
+
+bool NativeButton::AcceleratorPressed(const Accelerator& accelerator) {
+ if (enabled_) {
+ Clicked();
+ return true;
+ }
+ return false;
+}
+
+bool NativeButton::GetAccessibleRole(VARIANT* role) {
+ DCHECK(role);
+
+ role->vt = VT_I4;
+ role->lVal = ROLE_SYSTEM_PUSHBUTTON;
+ return true;
+}
+
+bool NativeButton::GetAccessibleName(std::wstring* name) {
+ if (!accessible_name_.empty()) {
+ *name = accessible_name_;
+ return true;
+ }
+ return false;
+}
+
+void NativeButton::SetAccessibleName(const std::wstring& name) {
+ accessible_name_.assign(name);
+}
+
+void NativeButton::Init(const std::wstring& label, bool is_default) {
+ // Marking the string as an RTL string if the locale is RTL. Refer to
+ // the comments in NativeButton::SetLabel for more details.
+ std::wstring localized_label;
+ if (l10n_util::AdjustStringForLocaleDirection(label, &localized_label))
+ label_.assign(localized_label);
+ else
+ label_.assign(label);
+
+ l10n_util::AdjustStringForLocaleDirection(label, &label_);
+ listener_ = NULL;
+ SetAccessibleName(label);
+ // The padding of 8 is a bit arbitrary, there appears to be no way to
+ // get a recommended padding, and this value varies greatly among windows
+ // dialogs.
+ //
+ // The min size in DLUs comes from
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwue/html/ch14e.asp
+ padding_ = CSize(8, 0);
+ is_default_ = is_default;
+ min_dlu_size_.SetSize(50, 14);
+ SetFocusable(true);
+ if (is_default)
+ AddAccelerator(Accelerator(VK_RETURN, false, false, false));
+}
+
+void NativeButton::Clicked() {
+ DCHECK(enabled_);
+ // Give the focus to the button.
+ RequestFocus();
+
+ if (listener_)
+ listener_->ButtonPressed(this);
+}
+
+bool NativeButton::NotifyOnKeyDown() const {
+ return true;
+}
+
+bool NativeButton::OnKeyDown(int virtual_key_code) {
+ if (virtual_key_code == VK_RETURN) {
+ Clicked();
+ return true;
+ }
+ return false;
+}
+
+} // namespace views