/* ZynAddSubFX - a software synthesizer Fl_Osc_Slider.cpp - OSC Based Slider Copyright (C) 2016 Mark McCurry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include #include "Fl_Osc_Slider.H" #include "Fl_Osc_Interface.h" #include "Fl_Osc_Pane.H" #include #include #include #include #include #include "../Misc/Util.h" static double min__(double a, double b) { return awrite("/learn", "s", (loc+ext).c_str()); return 1; } else if(shift_middle) { osc->write("/unlearn", "s", (loc+ext).c_str()); return 1; } int handled; float rounded; const float range = maximum() - minimum(); const float absrange = (range > 0 ? range : -range)+1; int old_mod_state; const float normal_step = range / W; switch (ev) { case FL_PUSH: just_pushed = true; mod_state = Fl::event_state() & MOD_MASK; slow_state = 0; start_pos = horizontal() ? Fl::event_x() : Fl::event_y(); handled = mod_state ? 1 : Fl_Slider::handle(ev, X, Y, W, H); break; case FL_MOUSEWHEEL: mod_state = Fl::event_state() & MOD_MASK; if (Fl::event_buttons()) return 1; if (this == Fl::belowmouse() && Fl::e_dy != 0) { int step_ = 1, divisor = 16; switch (mod_state) { case FL_SHIFT: if (absrange > divisor * 8) step_ = 8; case FL_SHIFT | FL_CTRL: break; case FL_CTRL: divisor = 128; default: step_ = absrange / divisor; if (step_ < 1) step_ = 1; } int dy = minimum() <= maximum() ? -Fl::e_dy : Fl::e_dy; // Flip sense for vertical sliders. dy = this->horizontal() ? dy : -dy; handle_drag(clamp(value() + step_ * dy)); } return 1; case FL_RELEASE: handled = Fl_Slider::handle(ev, X, Y, W, H); if (Fl::event_clicks() == 1) { Fl::event_clicks(0); value(reset_value); } else { rounded = floorf(value() + 0.5); value(clamp(rounded)); } value_damage(); do_callback(); break; case FL_DRAG: { old_mod_state = mod_state; mod_state = Fl::event_state() & MOD_MASK; if (slow_state == 0 && mod_state == 0) { int delta = (horizontal() ? Fl::event_x() : Fl::event_y()) - start_pos; if (delta < -1 || delta > 1) Fl::event_clicks(0); return Fl_Slider::handle(ev, X, Y, W, H); } if (mod_state != 0) { slow_state = 1; } else if (slow_state == 1) slow_state = 2; if (just_pushed || old_mod_state != mod_state) { just_pushed = false; old_value = value(); start_pos = horizontal() ? Fl::event_x() : Fl::event_y(); if (slow_state == 1) { denominator = 2.0; float step_ = step(); if (step_ == 0) step_ = 1; if (absrange / W / step_ > 32) switch (mod_state) { case FL_CTRL: denominator = 0.15; break; case FL_SHIFT: denominator = 0.7; break; case MOD_MASK: denominator = 3.0; break; } else if (mod_state & FL_SHIFT) denominator = 5.0; if (range < 0) denominator *= -1; } } int delta = (horizontal() ? Fl::event_x() : Fl::event_y()) - start_pos; if (delta < -1 || delta > 1) Fl::event_clicks(0); float new_value; if (slow_state == 1) { new_value = old_value + delta / denominator; } else { new_value = old_value + delta * normal_step; } const float clamped_value = clamp(new_value); rounded = floor(clamped_value + 0.5); if (new_value != clamped_value) { start_pos = horizontal() ? Fl::event_x() : Fl::event_y(); old_value = rounded; if (slow_state == 2 && ((horizontal() && (Fl::event_x() < X || Fl::event_x() > X + W)) || (!horizontal() && (Fl::event_y() < Y || Fl::event_y() > Y + H)))) slow_state = 0; } value(rounded); value_damage(); do_callback(); handled = 1; break; } default: handled = Fl_Slider::handle(ev, X, Y, W, H); } return handled; } int Fl_Osc_Slider::handle(int ev) { return handle(ev, x()+Fl::box_dx(box()), y()+Fl::box_dy(box()), w()-Fl::box_dw(box()), h()-Fl::box_dh(box())); } void Fl_Osc_Slider::update(void) { oscWrite(ext, ""); } void Fl_Osc_Slider::_cb(Fl_Widget *w, void *) { static_cast(w)->cb(); }