Display attached+un-embedded composer as an additional ConversationViewer stack page, although it realy should be broken as its own top-level widget - there's already too much state in ConversationViewer. * src/client/conversation-viewer/conversation-viewer.vala: Remove old composer boxes code. Add new ViewState enum, property and methods to define and manipulate the current view state - either conversation or composer. (do_conversation): New method to put the viewer in conversation mode. (do_compose): New method to put the viewer in compose mode, hook up the composer widget, and handle ConversationListView selection management for now. (on_folder_selected, on_conversation_count_changed, on_conversations_selected): Ensure these methods do the right thing depending on the viewer's current view state. (set_paned_composer): Replaced by ::do_compose, fixed call sites. (show_multiple_selected): Minor code clean up - moved down to a more appropriate location. * src/client/composer/composer-box.vala (ComposerBox): Don't attempt to up-manage it's parent's state, since the parent has a much better idea of how best to do that. Likewise move code to manage previous ConversationList selection out, provide signal so the a more appropriate class can manage it instead. * src/client/composer/composer-container.vala: Add some method comments. * ui/conversation-viewer.ui: Add new page to the stack for the composer.
133 lines
5.2 KiB
Vala
133 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);
|
|
}
|
|
}
|