2016-05-06 08:33:37 -04:00
|
|
|
/* Copyright 2016 Software Freedom Conservancy Inc.
|
2012-08-30 18:55:37 -07:00
|
|
|
*
|
|
|
|
|
* This software is licensed under the GNU Lesser General Public License
|
2013-04-12 12:31:58 -07:00
|
|
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
2012-08-30 18:55:37 -07:00
|
|
|
*/
|
|
|
|
|
|
Separate composer widget from composer window
In anticipation of inline composition, we need the composer widget to be
separate from the window in which it lives. We introduce a new
interface, ComposerContainer, that the thing that holds to
ComposerWidget must implement.
Separate composer widget from composer window
In anticipation of inline composition, we need the composer widget to be
separate from the window in which it lives. We introduce a new
interface, ComposerContainer, that the thing that holds to
ComposerWidget must implement.
Basic inline composition
Many of the details don't work, or don't work well, but the basics are
in place.
Allow only a single inline composition at a time
With this, we introduce a dialog when you would try to add another. We
also use this when changing the selected conversation with a composer
open.
Compose new messages inline, with no conversation selected
Hook up composer accelerators only when focus is in composer editor
It would be nice to only activate these accelerators when the composer
has focus generally, but that doesn't seem to be easy to detect.
Only disconnect accelerators if they're connected
Maintain focus when composer is popped out
The selection isn't, though.
Fix Tab focus for embedded composer
There are two things that needed to be fixed: The tab key doesn't
usually advance focus for embedded widgets (huh?), so we handle tab
presses by hand for ComposerWidgets. Also, the EmailEntrys do their own
tab handling, which needs to know about the composer widget, not the
toplevel widget in the embedded case.
Remove close() from ComposerContainer interface
I don't think it was actually doing anything, and it conflicts with the new close() method of Gtk.Window.
2014-02-11 00:26:14 -05:00
|
|
|
class AlertDialog : Object {
|
2012-08-30 18:55:37 -07:00
|
|
|
private Gtk.MessageDialog dialog;
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2019-03-28 11:09:39 +01:00
|
|
|
public AlertDialog(Gtk.Window? parent, Gtk.MessageType message_type, string title,
|
|
|
|
|
string? description, string? ok_button, string? cancel_button, string? tertiary_button,
|
|
|
|
|
Gtk.ResponseType tertiary_response_type, string? ok_action_type,
|
|
|
|
|
string? tertiary_action_type = "", Gtk.ResponseType? default_response = null) {
|
|
|
|
|
|
2012-08-30 18:55:37 -07:00
|
|
|
dialog = new Gtk.MessageDialog(parent, Gtk.DialogFlags.DESTROY_WITH_PARENT, message_type,
|
|
|
|
|
Gtk.ButtonsType.NONE, "");
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2016-10-07 15:03:12 +02:00
|
|
|
dialog.text = title;
|
|
|
|
|
dialog.secondary_text = description;
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2019-03-28 11:09:39 +01:00
|
|
|
if (!Geary.String.is_empty_or_whitespace(tertiary_button)) {
|
|
|
|
|
Gtk.Widget? button = dialog.add_button(tertiary_button, tertiary_response_type);
|
|
|
|
|
if (!Geary.String.is_empty_or_whitespace(tertiary_action_type)) {
|
|
|
|
|
button.get_style_context().add_class(tertiary_action_type);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-08-30 18:55:37 -07:00
|
|
|
if (!Geary.String.is_empty_or_whitespace(cancel_button))
|
|
|
|
|
dialog.add_button(cancel_button, Gtk.ResponseType.CANCEL);
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2016-10-07 15:03:12 +02:00
|
|
|
if (!Geary.String.is_empty_or_whitespace(ok_button)) {
|
|
|
|
|
Gtk.Widget? button = dialog.add_button(ok_button, Gtk.ResponseType.OK);
|
|
|
|
|
if (!Geary.String.is_empty_or_whitespace(ok_action_type)) {
|
|
|
|
|
button.get_style_context().add_class(ok_action_type);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-03-28 11:09:39 +01:00
|
|
|
|
|
|
|
|
if (default_response != null) {
|
|
|
|
|
dialog.set_default_response(default_response);
|
|
|
|
|
}
|
2012-08-30 18:55:37 -07:00
|
|
|
}
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2013-09-09 14:44:36 -07:00
|
|
|
public void use_secondary_markup(bool markup) {
|
|
|
|
|
dialog.secondary_use_markup = markup;
|
|
|
|
|
}
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-09-04 17:50:18 -07:00
|
|
|
public Gtk.Box get_message_area() {
|
|
|
|
|
return (Gtk.Box) dialog.get_message_area();
|
|
|
|
|
}
|
2013-03-11 13:36:18 -07:00
|
|
|
|
|
|
|
|
public void set_focus_response(Gtk.ResponseType response) {
|
2015-01-13 13:55:06 -08:00
|
|
|
Gtk.Widget? to_focus = dialog.get_widget_for_response(response);
|
2013-03-11 13:36:18 -07:00
|
|
|
if (to_focus != null)
|
|
|
|
|
to_focus.grab_focus();
|
|
|
|
|
}
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-08-30 18:55:37 -07:00
|
|
|
// Runs dialog, destroys it, and returns selected response
|
|
|
|
|
public Gtk.ResponseType run() {
|
|
|
|
|
Gtk.ResponseType response = (Gtk.ResponseType) dialog.run();
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-08-30 18:55:37 -07:00
|
|
|
dialog.destroy();
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-08-30 18:55:37 -07:00
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ConfirmationDialog : AlertDialog {
|
2019-02-28 09:38:56 +01:00
|
|
|
public ConfirmationDialog(Gtk.Window? parent, string title, string? description,
|
2016-10-07 15:03:12 +02:00
|
|
|
string? ok_button, string? ok_action_type = "") {
|
|
|
|
|
base (parent, Gtk.MessageType.WARNING, title, description, ok_button, Stock._CANCEL,
|
|
|
|
|
null, Gtk.ResponseType.NONE, ok_action_type);
|
2012-08-30 18:55:37 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-08 18:47:23 -07:00
|
|
|
class TernaryConfirmationDialog : AlertDialog {
|
2016-10-07 15:03:12 +02:00
|
|
|
public TernaryConfirmationDialog(Gtk.Window? parent, string title, string? description,
|
2019-03-28 11:09:39 +01:00
|
|
|
string? ok_button, string? tertiary_button, Gtk.ResponseType tertiary_response_type,
|
|
|
|
|
string? ok_action_type = "", string? tertiary_action_type = "",
|
|
|
|
|
Gtk.ResponseType? default_response = null) {
|
|
|
|
|
|
|
|
|
|
base (parent, Gtk.MessageType.WARNING, title, description, ok_button, Stock._CANCEL,
|
|
|
|
|
tertiary_button, tertiary_response_type, ok_action_type, tertiary_action_type,
|
|
|
|
|
default_response);
|
2013-08-08 18:47:23 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-30 18:55:37 -07:00
|
|
|
class ErrorDialog : AlertDialog {
|
2016-10-07 15:03:12 +02:00
|
|
|
public ErrorDialog(Gtk.Window? parent, string title, string? description) {
|
|
|
|
|
base (parent, Gtk.MessageType.ERROR, title, description, Stock._OK, null, null,
|
|
|
|
|
Gtk.ResponseType.NONE, null);
|
2012-08-30 18:55:37 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-04 17:50:18 -07:00
|
|
|
class QuestionDialog : AlertDialog {
|
|
|
|
|
public bool is_checked { get; private set; default = false; }
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-09-04 17:50:18 -07:00
|
|
|
private Gtk.CheckButton? checkbutton = null;
|
2019-02-28 09:38:56 +01:00
|
|
|
|
|
|
|
|
public QuestionDialog(Gtk.Window? parent, string title, string? description,
|
2016-10-07 15:03:12 +02:00
|
|
|
string yes_button, string no_button) {
|
|
|
|
|
base (parent, Gtk.MessageType.QUESTION, title, description, yes_button, no_button, null,
|
|
|
|
|
Gtk.ResponseType.NONE, "suggested-action");
|
2012-09-04 17:50:18 -07:00
|
|
|
}
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2016-10-07 15:03:12 +02:00
|
|
|
public QuestionDialog.with_checkbox(Gtk.Window? parent, string title, string? description,
|
2012-09-04 17:50:18 -07:00
|
|
|
string yes_button, string no_button, string checkbox_label, bool checkbox_default) {
|
2016-10-07 15:03:12 +02:00
|
|
|
this (parent, title, description, yes_button, no_button);
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-09-04 17:50:18 -07:00
|
|
|
checkbutton = new Gtk.CheckButton.with_mnemonic(checkbox_label);
|
|
|
|
|
checkbutton.active = checkbox_default;
|
|
|
|
|
checkbutton.toggled.connect(on_checkbox_toggled);
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-09-04 17:50:18 -07:00
|
|
|
get_message_area().pack_start(checkbutton);
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-09-04 17:50:18 -07:00
|
|
|
// this must be done once all the packing is completed
|
|
|
|
|
get_message_area().show_all();
|
2013-03-11 13:36:18 -07:00
|
|
|
|
|
|
|
|
// the check box may have grabbed keyboard focus, so we put it back to the button
|
|
|
|
|
set_focus_response(Gtk.ResponseType.OK);
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-09-04 17:50:18 -07:00
|
|
|
is_checked = checkbox_default;
|
|
|
|
|
}
|
2019-02-28 09:38:56 +01:00
|
|
|
|
2012-09-04 17:50:18 -07:00
|
|
|
private void on_checkbox_toggled() {
|
|
|
|
|
is_checked = checkbutton.active;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|