Use views to implement NativeWindow and MessageBox on Linux.

This commit is contained in:
Cheng Zhao 2014-07-04 01:30:36 +08:00
parent 1965a5ee50
commit 61db17412c
22 changed files with 384 additions and 1777 deletions

View file

@ -27,7 +27,6 @@ class FileChooserDialog {
else if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
confirm_text = GTK_STOCK_OPEN;
// GtkWindow* window = parent_window ? parent_window->GetNativeWindow() : NULL;
GtkWindow* window = NULL;
dialog_ = gtk_file_chooser_dialog_new(
title.c_str(),

View file

@ -1,136 +0,0 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/ui/message_box.h"
#include "atom/browser/native_window.h"
#include "base/callback.h"
#include "base/strings/string_util.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
#include "ui/base/gtk/gtk_signal.h"
namespace atom {
namespace {
class MessageBox {
public:
MessageBox(NativeWindow* parent_window,
MessageBoxType type,
const std::vector<std::string>& buttons,
const std::string& title,
const std::string& message,
const std::string& detail)
: cancel_id_(0),
dialog_scope_(new NativeWindow::DialogScope(parent_window)) {
// GtkWindow* window = parent_window ? parent_window->GetNativeWindow() : NULL;
GtkWindow* window = NULL;
dialog_ = gtk_dialog_new_with_buttons(
title.c_str(),
window,
static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
NULL);
for (size_t i = 0; i < buttons.size(); ++i)
gtk_dialog_add_button(GTK_DIALOG(dialog_),
TranslateToStock(i, buttons[i]),
i);
GtkWidget* content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog_));
GtkWidget* message_label = gtk_util::CreateBoldLabel(message);
gtk_util::LeftAlignMisc(message_label);
gtk_box_pack_start(GTK_BOX(content_area), message_label, FALSE, FALSE, 0);
GtkWidget* detail_label = gtk_label_new(detail.c_str());
gtk_util::LeftAlignMisc(detail_label);
gtk_box_pack_start(GTK_BOX(content_area), detail_label, FALSE, FALSE, 0);
gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
}
~MessageBox() {
gtk_widget_destroy(dialog_);
}
const char* TranslateToStock(int id, const std::string& text) {
if (LowerCaseEqualsASCII(text, "cancel")) {
cancel_id_ = id;
return GTK_STOCK_CANCEL;
} else if (LowerCaseEqualsASCII(text, "no")) {
cancel_id_ = id;
return GTK_STOCK_NO;
} else if (LowerCaseEqualsASCII(text, "ok")) {
return GTK_STOCK_OK;
} else if (LowerCaseEqualsASCII(text, "yes")) {
return GTK_STOCK_YES;
} else {
return text.c_str();
}
}
void RunAsynchronous(const MessageBoxCallback& callback) {
callback_ = callback;
g_signal_connect(dialog_, "delete-event",
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
g_signal_connect(dialog_, "response",
G_CALLBACK(OnResponseDialogThunk), this);
gtk_widget_show_all(dialog_);
}
CHROMEGTK_CALLBACK_1(MessageBox, void, OnResponseDialog, int);
GtkWidget* dialog() const { return dialog_; }
int cancel_id() const { return cancel_id_; }
private:
GtkWidget* dialog_;
MessageBoxCallback callback_;
scoped_ptr<NativeWindow::DialogScope> dialog_scope_;
// The id to return when the dialog is closed without pressing buttons.
int cancel_id_;
DISALLOW_COPY_AND_ASSIGN(MessageBox);
};
void MessageBox::OnResponseDialog(GtkWidget* widget, int response) {
gtk_widget_hide_all(dialog_);
if (response < 0)
callback_.Run(cancel_id_);
else
callback_.Run(response);
delete this;
}
} // namespace
int ShowMessageBox(NativeWindow* parent_window,
MessageBoxType type,
const std::vector<std::string>& buttons,
const std::string& title,
const std::string& message,
const std::string& detail) {
MessageBox message_box(parent_window, type, buttons, title, message, detail);
gtk_widget_show_all(message_box.dialog());
int response = gtk_dialog_run(GTK_DIALOG(message_box.dialog()));
if (response < 0)
return message_box.cancel_id();
else
return response;
}
void ShowMessageBox(NativeWindow* parent_window,
MessageBoxType type,
const std::vector<std::string>& buttons,
const std::string& title,
const std::string& message,
const std::string& detail,
const MessageBoxCallback& callback) {
MessageBox* message_box = new MessageBox(
parent_window, type, buttons, title, message, detail);
message_box->RunAsynchronous(callback);
}
} // namespace atom

View file

@ -9,8 +9,9 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "skia/ext/skia_utils_win.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/message_box_view.h"
#include "ui/views/layout/grid_layout.h"
@ -26,8 +27,7 @@ namespace {
// conflict with other groups that could be in the dialog content.
const int kButtonGroup = 1127;
class MessageDialog : public base::MessageLoop::Dispatcher,
public views::WidgetDelegate,
class MessageDialog : public views::WidgetDelegate,
public views::View,
public views::ButtonListener {
public:
@ -39,7 +39,7 @@ class MessageDialog : public base::MessageLoop::Dispatcher,
const std::string& detail);
virtual ~MessageDialog();
void Show();
void Show(base::RunLoop* run_loop = NULL);
int GetResult() const;
@ -49,9 +49,6 @@ class MessageDialog : public base::MessageLoop::Dispatcher,
}
private:
// Overridden from MessageLoop::Dispatcher:
virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
// Overridden from views::WidgetDelegate:
virtual base::string16 GetWindowTitle() const;
virtual void WindowClosing() OVERRIDE;
@ -76,6 +73,7 @@ class MessageDialog : public base::MessageLoop::Dispatcher,
base::string16 title_;
views::Widget* widget_;
views::MessageBoxView* message_box_view_;
base::RunLoop* run_loop_;
scoped_ptr<NativeWindow::DialogScope> dialog_scope_;
std::vector<views::LabelButton*> buttons_;
MessageBoxCallback callback_;
@ -95,24 +93,27 @@ MessageDialog::MessageDialog(NativeWindow* parent_window,
: should_close_(false),
delete_on_close_(false),
result_(-1),
title_(UTF8ToUTF16(title)),
title_(base::UTF8ToUTF16(title)),
widget_(NULL),
message_box_view_(NULL),
run_loop_(NULL),
dialog_scope_(new NativeWindow::DialogScope(parent_window)) {
DCHECK_GT(buttons.size(), 0u);
set_owned_by_client();
set_background(views::Background::CreateStandardPanelBackground());
views::MessageBoxView::InitParams params(UTF8ToUTF16(title));
params.message = UTF8ToUTF16(message + "\n" + detail);
std::string content = message + "\n" + detail;
views::MessageBoxView::InitParams params(base::UTF8ToUTF16(content));
message_box_view_ = new views::MessageBoxView(params);
AddChildView(message_box_view_);
for (size_t i = 0; i < buttons.size(); ++i) {
views::LabelButton* button = new views::LabelButton(
this, UTF8ToUTF16(buttons[i]));
this, base::UTF8ToUTF16(buttons[i]));
button->set_tag(i);
button->set_min_size(gfx::Size(60, 20));
button->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
button->set_min_size(gfx::Size(60, 30));
button->SetStyle(views::Button::STYLE_BUTTON);
button->SetHorizontalAlignment(gfx::ALIGN_CENTER);
button->SetGroup(kButtonGroup);
buttons_.push_back(button);
@ -129,20 +130,17 @@ MessageDialog::MessageDialog(NativeWindow* parent_window,
if (parent_window)
widget_params.parent = parent_window->GetNativeWindow();
widget_ = new views::Widget;
widget_->set_frame_type(views::Widget::FRAME_TYPE_FORCE_NATIVE);
widget_->Init(widget_params);
// Bind to ESC.
AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
set_background(views::Background::CreateSolidBackground(
skia::COLORREFToSkColor(GetSysColor(COLOR_WINDOW))));
}
MessageDialog::~MessageDialog() {
}
void MessageDialog::Show() {
void MessageDialog::Show(base::RunLoop* run_loop) {
run_loop_ = run_loop;
widget_->Show();
}
@ -164,13 +162,7 @@ int MessageDialog::GetResult() const {
////////////////////////////////////////////////////////////////////////////////
// MessageDialog, private:
bool MessageDialog::Dispatch(const base::NativeEvent& event) {
TranslateMessage(&event);
DispatchMessage(&event);
return !should_close_;
}
string16 MessageDialog::GetWindowTitle() const {
base::string16 MessageDialog::GetWindowTitle() const {
return title_;
}
@ -181,6 +173,8 @@ void MessageDialog::WindowClosing() {
if (delete_on_close_) {
callback_.Run(GetResult());
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
} else if (run_loop_) {
run_loop_->Quit();
}
}
@ -269,11 +263,11 @@ int ShowMessageBox(NativeWindow* parent_window,
const std::string& message,
const std::string& detail) {
MessageDialog dialog(parent_window, type, buttons, title, message, detail);
dialog.Show();
{
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoopForUI::current());
base::RunLoop run_loop(&dialog);
base::RunLoop run_loop;
dialog.Show(&run_loop);
run_loop.Run();
}