Canola  0.8.D001
canola/slider.cc
Go to the documentation of this file.
00001 //
00002 // canola - canon canola 1614p emulator
00003 // Copyright (C) 2012 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License, version 3, as
00007 // published by the Free Software Foundation.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program. If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include <lib/ac/assert.h>
00019 
00020 #include <lib/std_string_printf.h>
00021 
00022 #include <canola/load_image.h>
00023 #include <canola/slider.h>
00024 
00025 
00026 slider::~slider()
00027 {
00028 }
00029 
00030 
00031 static img_ptr_t
00032 load_image(const std::string &name, int n)
00033 {
00034     std::string filename = std_string_printf("%s-switch-%d", name.c_str(), n);
00035     return load_gui_image(filename);
00036 }
00037 
00038 
00039 slider::slider(const std::string &name, int a_nvalues, bool act_on_rel) :
00040     nvalues(a_nvalues),
00041     value(0),
00042     down(false),
00043     inside(false),
00044     old_value(0),
00045     frac(1),
00046     activate_on_release(act_on_rel)
00047 {
00048     assert(nvalues >= 2);
00049     for (int n = 0; n < nvalues; ++n)
00050         value_images.push_back(load_image(name, n));
00051 
00052     appearance.set(value_images[value]);
00053     add(appearance);
00054 
00055     set_size_request
00056     (
00057         value_images[0]->get_width(),
00058         value_images[0]->get_height()
00059     );
00060 
00061     signal_button_press_event().connect(sigc::mem_fun(this,
00062         &slider::on_button_press));
00063     signal_button_release_event().connect(sigc::mem_fun(this,
00064         &slider::on_button_release));
00065     signal_motion_notify_event().connect(sigc::mem_fun(this,
00066         &slider::on_motion_notify));
00067 
00068     show_all_children();
00069     frac = value_images[value]->get_width() / nvalues;
00070     assert(frac >= 1);
00071 
00072     override_background_color(custom_widget_background, Gtk::STATE_FLAG_NORMAL);
00073 }
00074 
00075 
00076 bool
00077 slider::on_button_press(GdkEventButton *ep)
00078 {
00079     down = true;
00080     inside = true;
00081     old_value = value;
00082     update_value(ep->x, ep->y);
00083     return true;
00084 }
00085 
00086 
00087 bool
00088 slider::on_button_release(GdkEventButton *)
00089 {
00090     if (activate_on_release)
00091     {
00092         if (inside)
00093             value_changed_source.emit();
00094     }
00095     down = false;
00096     inside = false;
00097     old_value = value;
00098     return true;
00099 }
00100 
00101 
00102 bool
00103 slider::on_motion_notify(GdkEventMotion *ep)
00104 {
00105     if (!down)
00106         return false;
00107     update_value(ep->x, ep->y);
00108     return true;
00109 }
00110 
00111 
00112 void
00113 slider::update_value(int x, int y)
00114 {
00115     pixbuf_pointer p = value_images[value];
00116     x -= (get_allocated_width() - p->get_width()) / 2;
00117     y -= (get_allocated_height() - p->get_height()) / 2;
00118 
00119     if (x > 0 && x < p->get_width() && y > 0 && y < p->get_height())
00120     {
00121         inside = true;
00122         int n = x / frac;
00123         if (n < 0)
00124             n = 0;
00125         else if (n >= nvalues)
00126             n = nvalues - 1;
00127         if (n != value)
00128         {
00129             value = n;
00130             appearance.set(value_images[value]);
00131             if (!activate_on_release)
00132                 value_changed_source.emit();
00133         }
00134     }
00135     else
00136     {
00137         if (inside)
00138         {
00139             value = old_value;
00140             appearance.set(value_images[value]);
00141             if (!activate_on_release)
00142                 value_changed_source.emit();
00143         }
00144         inside = false;
00145     }
00146 }
00147 
00148 
00149 int
00150 slider::get_value(void)
00151     const
00152 {
00153     return value;
00154 }
00155 
00156 
00157 slider::value_changed_signal_t &
00158 slider::value_changed_signal(void)
00159 {
00160     return value_changed_source;
00161 }
00162 
00163 
00164 void
00165 slider::set_value(int n)
00166 {
00167     if (n < 0)
00168         value = 0;
00169     else if (n >= nvalues)
00170         value = nvalues - 1;
00171     else
00172         value = n;
00173     appearance.set(value_images[value]);
00174 }