Now using these instead of the old composer's actions. This led to quite some changes: * Use GLib.ActionEntry instead of Gtk.ActionEntry in composer-widget.vala * Action names can now be specified in the UI files. * Use templates for the ComposerHeaderBar. Remove Pillbar as superclass, since that was no longer necessary. * Merge ComposerToolbar into ComposerWidget. * Since actions can now be parameterized, some methods could be merged (e.g. font size methods). * The menu button in the composer now automatically uses a popover. * Some methods and classes really deserved more comments. * necessary POTFILES.in changes Signed-off-by: Niels De Graef <nielsdegraef@gmail.com>
132 lines
5.2 KiB
Vala
132 lines
5.2 KiB
Vala
/* Copyright 2016 Software Freedom Conservancy Inc.
|
|
*
|
|
* This software is licensed under the GNU Lesser General Public License
|
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
|
*/
|
|
|
|
/**
|
|
* A generic interface for widgets that have a single ComposerWidget-child.
|
|
*/
|
|
public interface ComposerContainer {
|
|
// The ComposerWidget-child.
|
|
protected abstract ComposerWidget composer { get; set; }
|
|
|
|
// Workaround to retrieve all Gtk.Actions with conflicting accelerators
|
|
protected const string[] conflicting_actions = {
|
|
GearyController.ACTION_MARK_AS_UNREAD,
|
|
GearyController.ACTION_FORWARD_MESSAGE
|
|
};
|
|
|
|
// We use old_accelerators to keep track of the accelerators we temporarily disabled.
|
|
protected abstract Gee.MultiMap<string, string>? old_accelerators { get; set; }
|
|
|
|
// The toplevel window for the container. Note that it needs to be a GtkApplicationWindow.
|
|
public abstract Gtk.ApplicationWindow top_window { get; }
|
|
|
|
public virtual void present() {
|
|
this.top_window.present();
|
|
}
|
|
|
|
public virtual unowned Gtk.Widget get_focus() {
|
|
return this.top_window.get_focus();
|
|
}
|
|
|
|
public abstract void close_container();
|
|
|
|
/**
|
|
* Hides the widget (and possibly its parent). Usecase is when you don't want to close just yet
|
|
* but the composer should not be visible any longer (e.g. when you're still saving a draft).
|
|
*/
|
|
public abstract void vanish();
|
|
|
|
/**
|
|
* Removes the composer from this ComposerContainer (e.g. when detaching)
|
|
*/
|
|
public abstract void remove_composer();
|
|
|
|
protected virtual bool on_focus_in() {
|
|
if (this.old_accelerators == null) {
|
|
this.old_accelerators = new Gee.HashMultiMap<string, string>();
|
|
add_accelerators();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected virtual bool on_focus_out() {
|
|
if (this.old_accelerators != null) {
|
|
remove_accelerators();
|
|
this.old_accelerators = null;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Adds the accelerators for the child composer, and temporarily removes conflicting
|
|
* accelerators from existing actions.
|
|
*/
|
|
protected virtual void add_accelerators() {
|
|
GearyApplication app = GearyApplication.instance;
|
|
|
|
// Check for actions with conflicting accelerators
|
|
foreach (string action in ComposerWidget.action_accelerators.get_keys()) {
|
|
foreach (string accelerator in ComposerWidget.action_accelerators[action]) {
|
|
string[] actions = app.get_actions_for_accel(accelerator);
|
|
|
|
foreach (string conflicting_action in actions) {
|
|
remove_conflicting_accelerator(conflicting_action, accelerator);
|
|
this.old_accelerators[conflicting_action] = accelerator;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Very stupid workaround while we still use Gtk.Actions in the GearyController
|
|
foreach (string conflicting_action in conflicting_actions)
|
|
app.actions.get_action(conflicting_action).disconnect_accelerator();
|
|
|
|
// Now add our actions to the window and their accelerators
|
|
foreach (string action in ComposerWidget.action_accelerators.get_keys()) {
|
|
this.top_window.add_action(composer.get_action(action));
|
|
app.set_accels_for_action("win." + action,
|
|
ComposerWidget.action_accelerators[action].to_array());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes the accelerators for the child composer, and restores previously removed accelerators.
|
|
*/
|
|
protected virtual void remove_accelerators() {
|
|
foreach (string action in ComposerWidget.action_accelerators.get_keys())
|
|
GearyApplication.instance.set_accels_for_action("win." + action, {});
|
|
|
|
// Very stupid workaround while we still use Gtk.Actions in the GearyController
|
|
foreach (string conflicting_action in conflicting_actions)
|
|
GearyApplication.instance.actions.get_action(conflicting_action).connect_accelerator();
|
|
|
|
foreach (string action in old_accelerators.get_keys())
|
|
foreach (string accelerator in this.old_accelerators[action])
|
|
restore_conflicting_accelerator(action, accelerator);
|
|
}
|
|
|
|
// Helper method. Removes the given conflicting accelerator from the action's accelerators.
|
|
private void remove_conflicting_accelerator(string action, string accelerator) {
|
|
GearyApplication app = GearyApplication.instance;
|
|
string[] accelerators = app.get_accels_for_action(action);
|
|
if (accelerators.length == 0)
|
|
return;
|
|
|
|
string[] without_accel = new string[accelerators.length - 1];
|
|
foreach (string a in accelerators)
|
|
if (a != accelerator)
|
|
without_accel += a;
|
|
|
|
app.set_accels_for_action(action, without_accel);
|
|
}
|
|
|
|
// Helper method. Adds the given accelerator back to the action's accelerators.
|
|
private void restore_conflicting_accelerator(string action, string accelerator) {
|
|
GearyApplication app = GearyApplication.instance;
|
|
string[] accelerators = app.get_accels_for_action(action);
|
|
accelerators += accelerator;
|
|
app.set_accels_for_action(action, accelerators);
|
|
}
|
|
}
|