Use views to implement NativeWindow and MessageBox on Linux.
This commit is contained in:
parent
1965a5ee50
commit
61db17412c
22 changed files with 384 additions and 1777 deletions
|
@ -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(),
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue