Make Dropdown menus at least as wide as the button
[ardour.git] / gtk2_ardour / plugin_eq_gui.cc
index a005f7467362ee5fc1e2bb5a2e58467c56a724e1..069f3733e1ee4ed72c702b0d41d63a219af756ef 100644 (file)
 
 */
 
+#include <algorithm>
 #include <math.h>
+#include <iomanip>
 #include <iostream>
+#include <sstream>
 
 #ifdef COMPILER_MSVC
 #include <float.h>
@@ -46,7 +49,7 @@
 #include "ardour_ui.h"
 #include "gui_thread.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace ARDOUR;
 
@@ -75,8 +78,13 @@ PluginEqGui::PluginEqGui(boost::shared_ptr<ARDOUR::PluginInsert> pluginInsert)
        _analysis_height = 256.0;
        _analysis_area->set_size_request(_analysis_width, _analysis_height);
 
+       _analysis_area->add_events(Gdk::POINTER_MOTION_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK);
+
        _analysis_area->signal_expose_event().connect( sigc::mem_fun (*this, &PluginEqGui::expose_analysis_area));
        _analysis_area->signal_size_allocate().connect( sigc::mem_fun (*this, &PluginEqGui::resize_analysis_area));
+       _analysis_area->signal_motion_notify_event().connect( sigc::mem_fun (*this, &PluginEqGui::analysis_area_mouseover));
+       _analysis_area->signal_leave_notify_event().connect( sigc::mem_fun (*this, &PluginEqGui::analysis_area_mouseexit));
+       _analysis_area->signal_button_press_event().connect( sigc::mem_fun (*this, &PluginEqGui::analysis_area_mousedown));
 
        // dB selection
        dBScaleModel = Gtk::ListStore::create(dBColumns);
@@ -117,10 +125,16 @@ PluginEqGui::PluginEqGui(boost::shared_ptr<ARDOUR::PluginInsert> pluginInsert)
        _phase_button->set_active(true);
        _phase_button->signal_toggled().connect( sigc::mem_fun(*this, &PluginEqGui::redraw_scales));
 
+       // Freq/dB info for mouse over
+       _pointer_info = new Gtk::Label ("", 1, 0.5);
+       _pointer_info->set_size_request(_analysis_width / 4, -1);
+       _pointer_info->set_name("PluginAnalysisInfoLabel");
+
        // populate table
-       attach( *manage(_analysis_area), 1, 3, 1, 2);
+       attach( *manage(_analysis_area), 1, 4, 1, 2);
        attach( *manage(dBSelectBin),    1, 2, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
-       attach( *manage(_phase_button),  2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
+       attach( *manage(_phase_button),  2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
+       attach( *manage(_pointer_info),  3, 4, 2, 3, Gtk::FILL, Gtk::SHRINK);
 }
 
 PluginEqGui::~PluginEqGui()
@@ -287,6 +301,8 @@ PluginEqGui::resize_analysis_area (Gtk::Allocation& size)
                cairo_surface_destroy (_analysis_scale_surface);
                _analysis_scale_surface = 0;
        }
+
+       _pointer_info->set_size_request(_analysis_width / 4, -1);
 }
 
 bool
@@ -426,6 +442,47 @@ PluginEqGui::run_impulse_analysis()
        ARDOUR_UI::instance()->drop_process_buffers ();
 }
 
+void
+PluginEqGui::update_pointer_info(float x, float y)
+{
+       const int freq = std::max(1, (int) roundf((powf(10, x / _analysis_width * _log_max) - 1) * _samplerate / 2.0 / _log_coeff));
+       const float dB = _max_dB - y / _analysis_height * ( _max_dB - _min_dB );
+       std::stringstream ss;
+       ss << std::fixed;
+       if (freq >= 10000) {
+               ss <<  std::setprecision (1) << freq / 1000.0 << "kHz";
+       } else if (freq >= 1000) {
+               ss <<  std::setprecision (2) << freq / 1000.0 << "kHz";
+       } else {
+               ss <<  std::setprecision (0) << freq << "Hz";
+       }
+       ss << "  " << std::setw(5) << std::setprecision (1) << std::showpos << dB;
+       ss << std::setw(0) << "dB";
+       _pointer_info->set_text(ss.str());
+}
+
+bool
+PluginEqGui::analysis_area_mouseover(GdkEventMotion *event)
+{
+       update_pointer_info(event->x, event->y);
+       return true;
+}
+
+bool
+PluginEqGui::analysis_area_mouseexit(GdkEventCrossing *)
+{
+       _pointer_info->set_text("");
+       return true;
+}
+
+bool
+PluginEqGui::analysis_area_mousedown(GdkEventButton *event)
+{
+       update_pointer_info(event->x, event->y);
+       return true;
+}
+
+
 bool
 PluginEqGui::expose_analysis_area(GdkEventExpose *)
 {
@@ -751,26 +808,19 @@ PluginEqGui::plot_signal_amplitude_difference(Gtk::Widget *w, cairo_t *cr)
        float height = w->get_height();
 
        cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
-       cairo_set_line_width (cr, 2.5);
+       cairo_set_line_width (cr, 1.5);
 
        for (uint32_t i = 0; i < _signal_input_fft->bins()-1; i++) {
                // x coordinate of bin i
                x  = log10f(1.0 + (float)i / (float)_signal_input_fft->bins() * _log_coeff) / _log_max;
                x *= _analysis_width;
 
-               float power_out = power_to_dB(_signal_output_fft->power_at_bin(i));
-               float power_in  = power_to_dB(_signal_input_fft ->power_at_bin(i));
-               float power = power_out - power_in;
+               float power_out = _signal_output_fft->power_at_bin (i) + 1e-30;
+               float power_in  = _signal_input_fft ->power_at_bin (i) + 1e-30;
+               float power = power_to_dB (power_out / power_in);
 
-               if (ISINF(power)) {
-                       if (power < 0) {
-                               power = _min_dB - 1.0;
-                       } else {
-                               power = _max_dB - 1.0;
-                       }
-               } else if (ISNAN(power)) {
-                       power = _min_dB - 1.0;
-               }
+               assert (!ISINF(power));
+               assert (!ISNAN(power));
 
                float yCoeff = ( power - _min_dB) / (_max_dB - _min_dB);