Fix insertion of processors at the point at which the processor menu was opened; give a visual cue to indicate where a processor will be inserted. Kind of experimental.
git-svn-id: svn://localhost/ardour2/branches/3.0@10236 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
a9ebb3576e
commit
153ee4e441
|
@ -497,7 +497,7 @@ ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelecto
|
|||
, _owner_is_mixer (owner_is_mixer)
|
||||
, ab_direction (true)
|
||||
, _get_plugin_selector (get_plugin_selector)
|
||||
, _placement(PreFader)
|
||||
, _placement (-1)
|
||||
, _rr_selection(rsel)
|
||||
{
|
||||
set_session (sess);
|
||||
|
@ -684,10 +684,11 @@ ProcessorBox::new_send ()
|
|||
}
|
||||
|
||||
void
|
||||
ProcessorBox::show_processor_menu (gint arg)
|
||||
ProcessorBox::show_processor_menu (int arg)
|
||||
{
|
||||
if (processor_menu == 0) {
|
||||
processor_menu = build_processor_menu ();
|
||||
processor_menu->signal_unmap().connect (sigc::mem_fun (*this, &ProcessorBox::processor_menu_unmapped));
|
||||
}
|
||||
|
||||
Gtk::MenuItem* plugin_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/newplugin"));
|
||||
|
@ -714,6 +715,13 @@ ProcessorBox::show_processor_menu (gint arg)
|
|||
paste_action->set_sensitive (!_rr_selection.processors.empty());
|
||||
|
||||
processor_menu->popup (1, arg);
|
||||
|
||||
/* Add a placeholder gap to the processor list to indicate where a processor would be
|
||||
inserted were one chosen from the menu.
|
||||
*/
|
||||
int x, y;
|
||||
processor_display.get_pointer (x, y);
|
||||
_placement = processor_display.add_placeholder (y);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -884,20 +892,6 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev, ProcessorEntry
|
|||
|
||||
} else if (Keyboard::is_context_menu_event (ev)) {
|
||||
|
||||
/* figure out if we are above or below the fader/amp processor,
|
||||
and set the next insert position appropriately.
|
||||
*/
|
||||
|
||||
if (processor) {
|
||||
if (_route->processor_is_prefader (processor)) {
|
||||
_placement = PreFader;
|
||||
} else {
|
||||
_placement = PostFader;
|
||||
}
|
||||
} else {
|
||||
_placement = PostFader;
|
||||
}
|
||||
|
||||
show_processor_menu (ev->time);
|
||||
|
||||
} else if (processor && Keyboard::is_button2_event (ev)
|
||||
|
@ -977,7 +971,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
|
|||
|
||||
Route::ProcessorStreams err_streams;
|
||||
|
||||
if (_route->add_processor (processor, _placement, &err_streams, Config->get_new_plugins_active ())) {
|
||||
if (_route->add_processor_by_index (processor, _placement, &err_streams, Config->get_new_plugins_active ())) {
|
||||
weird_plugin_dialog (**p, err_streams);
|
||||
return true;
|
||||
// XXX SHAREDPTR delete plugin here .. do we even need to care?
|
||||
|
@ -1042,7 +1036,7 @@ void
|
|||
ProcessorBox::choose_insert ()
|
||||
{
|
||||
boost::shared_ptr<Processor> processor (new PortInsert (*_session, _route->pannable(), _route->mute_master()));
|
||||
_route->add_processor (processor, _placement);
|
||||
_route->add_processor_by_index (processor, _placement);
|
||||
}
|
||||
|
||||
/* Caller must not hold process lock */
|
||||
|
@ -1104,7 +1098,7 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
|
|||
break;
|
||||
|
||||
case IOSelector::Accepted:
|
||||
_route->add_processor (processor, _placement);
|
||||
_route->add_processor_by_index (processor, _placement);
|
||||
if (Profile->get_sae()) {
|
||||
processor->activate ();
|
||||
}
|
||||
|
@ -1132,7 +1126,7 @@ ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processo
|
|||
break;
|
||||
|
||||
case IOSelector::Accepted:
|
||||
_route->add_processor (processor, _placement);
|
||||
_route->add_processor_by_index (processor, _placement);
|
||||
if (Profile->get_sae()) {
|
||||
processor->activate ();
|
||||
}
|
||||
|
@ -2401,6 +2395,12 @@ ProcessorBox::hide_things ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProcessorBox::processor_menu_unmapped ()
|
||||
{
|
||||
processor_display.remove_placeholder ();
|
||||
}
|
||||
|
||||
ProcessorWindowProxy::ProcessorWindowProxy (
|
||||
string const & name,
|
||||
XMLNode const * node,
|
||||
|
|
|
@ -240,7 +240,10 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
|
|||
|
||||
boost::shared_ptr<ARDOUR::Processor> _processor_being_created;
|
||||
|
||||
ARDOUR::Placement _placement;
|
||||
/** Index at which to place a new plugin (based on where the menu was opened), or -1 to
|
||||
* put at the end of the plugin list.
|
||||
*/
|
||||
int _placement;
|
||||
|
||||
RouteRedirectSelection& _rr_selection;
|
||||
|
||||
|
@ -265,7 +268,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
|
|||
gint processor_menu_map_handler (GdkEventAny *ev);
|
||||
Gtk::Menu * build_processor_menu ();
|
||||
void build_processor_tooltip (Gtk::EventBox&, std::string);
|
||||
void show_processor_menu (gint arg);
|
||||
void show_processor_menu (int);
|
||||
Gtk::Menu* build_possible_aux_menu();
|
||||
|
||||
void choose_aux (boost::weak_ptr<ARDOUR::Route>);
|
||||
|
@ -289,6 +292,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
|
|||
void reordered ();
|
||||
void report_failed_reorder ();
|
||||
void route_processors_changed (ARDOUR::RouteProcessorChange);
|
||||
void processor_menu_unmapped ();
|
||||
|
||||
void processors_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*);
|
||||
void compute_processor_sort_keys ();
|
||||
|
|
|
@ -237,6 +237,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
|
|||
};
|
||||
|
||||
int add_processor (boost::shared_ptr<Processor>, Placement placement, ProcessorStreams* err = 0, bool activation_allowed = true);
|
||||
int add_processor_by_index (boost::shared_ptr<Processor>, int, ProcessorStreams* err = 0, bool activation_allowed = true);
|
||||
int add_processor (boost::shared_ptr<Processor>, ProcessorList::iterator iter, ProcessorStreams* err = 0, bool activation_allowed = true);
|
||||
int add_processors (const ProcessorList&, boost::shared_ptr<Processor> before, ProcessorStreams* err = 0);
|
||||
int remove_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0);
|
||||
|
|
|
@ -853,6 +853,34 @@ Route::add_processor (boost::shared_ptr<Processor> processor, Placement placemen
|
|||
}
|
||||
|
||||
|
||||
/** Add a processor to a route such that it ends up with a given index into the visible processors.
|
||||
* @param index Index to add the processor at, or -1 to add at the end of the list.
|
||||
*/
|
||||
|
||||
int
|
||||
Route::add_processor_by_index (boost::shared_ptr<Processor> processor, int index, ProcessorStreams* err, bool activation_allowed)
|
||||
{
|
||||
/* XXX this is not thread safe - we don't hold the lock across determining the iter
|
||||
to add before and actually doing the insertion. dammit.
|
||||
*/
|
||||
|
||||
if (index == -1) {
|
||||
return add_processor (processor, _processors.end(), err, activation_allowed);
|
||||
}
|
||||
|
||||
ProcessorList::iterator i = _processors.begin ();
|
||||
int j = 0;
|
||||
while (i != _processors.end() && j < index) {
|
||||
if ((*i)->display_to_user()) {
|
||||
++j;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return add_processor (processor, i, err, activation_allowed);
|
||||
}
|
||||
|
||||
/** Add a processor to the route.
|
||||
* @param iter an iterator in _processors; the new processor will be inserted immediately before this location.
|
||||
*/
|
||||
|
|
|
@ -45,7 +45,7 @@ template <class T>
|
|||
class DnDVBox : public Gtk::EventBox
|
||||
{
|
||||
public:
|
||||
DnDVBox () : _active (0), _drag_icon (0), _expecting_unwanted_button_event (false), _drag_placeholder (0)
|
||||
DnDVBox () : _active (0), _drag_icon (0), _expecting_unwanted_button_event (false), _placeholder (0)
|
||||
{
|
||||
_targets.push_back (Gtk::TargetEntry ("processor"));
|
||||
|
||||
|
@ -165,6 +165,59 @@ public:
|
|||
SelectionChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
/** @param y y coordinate.
|
||||
* @return Pair consisting of the child under y (or 0) and the (fractional) index of the child under y (or -1)
|
||||
*/
|
||||
std::pair<T*, double> get_child_at_position (int y) const
|
||||
{
|
||||
T* before;
|
||||
T* after;
|
||||
|
||||
std::pair<T*, double> r;
|
||||
|
||||
r.second = get_children_around_position (y, &before, &r.first, &after);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void set_spacing (int s) {
|
||||
_internal_vbox.set_spacing (s);
|
||||
}
|
||||
|
||||
void remove_placeholder ()
|
||||
{
|
||||
if (_placeholder) {
|
||||
_internal_vbox.remove (*_placeholder);
|
||||
_placeholder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a placeholder where a child would be put if it were added at the given y position.
|
||||
* @param y y position within the DnDVBox.
|
||||
* @return index of child that the placeholder represents, or -1 if it is at the end of all children.
|
||||
*/
|
||||
int add_placeholder (double y)
|
||||
{
|
||||
return create_or_update_placeholder (get_child_at_position (y).second);
|
||||
}
|
||||
|
||||
/** Children have been reordered by a drag */
|
||||
sigc::signal<void> Reordered;
|
||||
|
||||
/** A button has been pressed over the widget */
|
||||
sigc::signal<bool, GdkEventButton*, T*> ButtonPress;
|
||||
|
||||
/** A button has been release over the widget */
|
||||
sigc::signal<bool, GdkEventButton*, T*> ButtonRelease;
|
||||
|
||||
/** A child has been dropped onto this DnDVBox from another one;
|
||||
* Parameters are the source DnDVBox, our child which the other one was dropped on (or 0) and the DragContext.
|
||||
*/
|
||||
sigc::signal<void, DnDVBox*, T*, Glib::RefPtr<Gdk::DragContext> const & > DropFromAnotherBox;
|
||||
sigc::signal<void> SelectionChanged;
|
||||
|
||||
private:
|
||||
|
||||
/** Look at a y coordinate and find the children below y, and the ones either side.
|
||||
* @param y y position.
|
||||
* @param before Filled in with the child before, or 0.
|
||||
|
@ -188,7 +241,8 @@ public:
|
|||
/* top of current child */
|
||||
double top = 0;
|
||||
/* bottom of current child */
|
||||
double bottom = (*j)->widget().get_allocation().get_height ();
|
||||
Gtk::Allocation const a = (*j)->widget().get_allocation();
|
||||
double bottom = a.get_y() + a.get_height();
|
||||
|
||||
while (y >= bottom && j != _children.end()) {
|
||||
|
||||
|
@ -199,7 +253,8 @@ public:
|
|||
++j;
|
||||
|
||||
if (j != _children.end()) {
|
||||
bottom += (*j)->widget().get_allocation().get_height ();
|
||||
Gtk::Allocation const a = (*j)->widget().get_allocation();
|
||||
bottom = a.get_y() + a.get_height();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,41 +272,6 @@ public:
|
|||
return i + ((y - top) / (*at)->widget().get_allocation().get_height());
|
||||
}
|
||||
|
||||
/** @param y y coordinate.
|
||||
* @return Pair consisting of the child under y (or 0) and the (fractional) index of the child under y (or -1)
|
||||
*/
|
||||
std::pair<T*, double> get_child_at_position (int y) const
|
||||
{
|
||||
T* before;
|
||||
T* after;
|
||||
|
||||
std::pair<T*, double> r;
|
||||
|
||||
r.second = get_children_around_position (y, &before, &r.first, &after);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void set_spacing (int s) {
|
||||
_internal_vbox.set_spacing (s);
|
||||
}
|
||||
|
||||
/** Children have been reordered by a drag */
|
||||
sigc::signal<void> Reordered;
|
||||
|
||||
/** A button has been pressed over the widget */
|
||||
sigc::signal<bool, GdkEventButton*, T*> ButtonPress;
|
||||
|
||||
/** A button has been release over the widget */
|
||||
sigc::signal<bool, GdkEventButton*, T*> ButtonRelease;
|
||||
|
||||
/** A child has been dropped onto this DnDVBox from another one;
|
||||
* Parameters are the source DnDVBox, our child which the other one was dropped on (or 0) and the DragContext.
|
||||
*/
|
||||
sigc::signal<void, DnDVBox*, T*, Glib::RefPtr<Gdk::DragContext> const & > DropFromAnotherBox;
|
||||
sigc::signal<void> SelectionChanged;
|
||||
|
||||
private:
|
||||
void drag_begin (Glib::RefPtr<Gdk::DragContext> const & context, T* child)
|
||||
{
|
||||
_drag_child = child;
|
||||
|
@ -356,17 +376,27 @@ private:
|
|||
_drag_icon = 0;
|
||||
|
||||
_drag_child = 0;
|
||||
remove_drag_placeholder ();
|
||||
remove_placeholder ();
|
||||
|
||||
Reordered (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void remove_drag_placeholder ()
|
||||
/** Insert a placeholder at a given fractional child position, creating it if necessary.
|
||||
* @param c Fractional child position.
|
||||
* @return index of child that the placeholder represents, or -1 if it is at the end of all children.
|
||||
*/
|
||||
int create_or_update_placeholder (double c)
|
||||
{
|
||||
if (_drag_placeholder) {
|
||||
_internal_vbox.remove (*_drag_placeholder);
|
||||
_drag_placeholder = 0;
|
||||
if (_placeholder == 0) {
|
||||
_placeholder = manage (new Gtk::Label (""));
|
||||
_internal_vbox.pack_start (*_placeholder, false, false);
|
||||
_placeholder->show ();
|
||||
}
|
||||
|
||||
/* round up the index, unless we're off the end of the children */
|
||||
int const n = c < 0 ? -1 : int (c + 0.5);
|
||||
_internal_vbox.reorder_child (*_placeholder, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
bool drag_motion (Glib::RefPtr<Gdk::DragContext> const &, int /*x*/, int y, guint)
|
||||
|
@ -387,37 +417,23 @@ private:
|
|||
|
||||
if (top_half && (before == _drag_child || at == _drag_child)) {
|
||||
/* dropping here would have no effect, so remove the visual cue */
|
||||
remove_drag_placeholder ();
|
||||
remove_placeholder ();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!top_half && (at == _drag_child || after == _drag_child)) {
|
||||
/* dropping here would have no effect, so remove the visual cue */
|
||||
remove_drag_placeholder ();
|
||||
remove_placeholder ();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* the index that the placeholder should be put at */
|
||||
int const n = int (c + 0.5);
|
||||
|
||||
if (_drag_placeholder == 0) {
|
||||
_drag_placeholder = manage (new Gtk::Label (""));
|
||||
_internal_vbox.pack_start (*_drag_placeholder, false, false);
|
||||
_drag_placeholder->show ();
|
||||
}
|
||||
|
||||
if (c < 0) {
|
||||
_internal_vbox.reorder_child (*_drag_placeholder, -1);
|
||||
} else {
|
||||
_internal_vbox.reorder_child (*_drag_placeholder, n);
|
||||
}
|
||||
|
||||
create_or_update_placeholder (c);
|
||||
return false;
|
||||
}
|
||||
|
||||
void drag_leave (Glib::RefPtr<Gdk::DragContext> const &, guint)
|
||||
{
|
||||
remove_drag_placeholder ();
|
||||
remove_placeholder ();
|
||||
}
|
||||
|
||||
bool button_press (GdkEventButton* ev, T* child)
|
||||
|
@ -489,7 +505,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return ButtonPress (ev, child); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
|
@ -566,10 +581,10 @@ private:
|
|||
T* _active;
|
||||
Gtk::Window* _drag_icon;
|
||||
bool _expecting_unwanted_button_event;
|
||||
/** A blank label used as a placeholder to indicate where a dragged item would
|
||||
* go if it were dropped now.
|
||||
/** A blank label used as a placeholder to indicate where an item would
|
||||
* go if it were dropped or inserted "now".
|
||||
*/
|
||||
Gtk::Label* _drag_placeholder;
|
||||
Gtk::Label* _placeholder;
|
||||
/** Our child being dragged, or 0 */
|
||||
T* _drag_child;
|
||||
|
||||
|
|
Loading…
Reference in New Issue