1 /***************************************************************************
2 * Copyright (C) 2015 by Pere Ràfols Soler *
3 * sapista2@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 #include "button.h"
22 #include "colors.h"
23
24 #define OUTER_BORDER 2
25
Button(const Glib::ustring & label)26 Button::Button ( const Glib::ustring& label ):
27 m_label(label), m_bFocus(false), m_bPress(false)
28 {
29 set_size_request( 12 + 10*m_label.length(), 20);
30
31 //Connect mouse signals
32 add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::LEAVE_NOTIFY_MASK);
33 signal_button_press_event().connect(sigc::mem_fun(*this, &Button::on_button_press_event),true);
34 signal_button_release_event().connect(sigc::mem_fun(*this, &Button::on_button_release_event),true);
35 signal_motion_notify_event().connect(sigc::mem_fun(*this, &Button::on_mouse_motion_event),true);
36 signal_leave_notify_event().connect(sigc::mem_fun(*this, &Button::on_mouse_leave_widget),true);
37 }
38
~Button()39 Button::~Button()
40 {
41
42 }
43
on_button_press_event(GdkEventButton * event)44 bool Button::on_button_press_event ( GdkEventButton* event )
45 {
46 //Check click type
47 if( event->button == 1 && event->type == GDK_BUTTON_PRESS)
48 {
49 m_bPress = event->x > OUTER_BORDER &&
50 event->x < (width - OUTER_BORDER) &&
51 event->y > OUTER_BORDER &&
52 event->y < (height - OUTER_BORDER);
53 m_sigPress.emit();
54 redraw();
55 }
56 return true;
57 }
58
on_button_release_event(GdkEventButton * event)59 bool Button::on_button_release_event ( GdkEventButton* event )
60 {
61 if( event->x > OUTER_BORDER &&
62 event->x < (width - OUTER_BORDER) &&
63 event->y > OUTER_BORDER &&
64 event->y < (height - OUTER_BORDER))
65 {
66 m_sigClick.emit();
67 }
68 m_sigRelease.emit();
69 m_bPress = false;
70 m_bFocus = false;
71 redraw();
72 return true;
73 }
74
on_mouse_motion_event(GdkEventMotion * event)75 bool Button::on_mouse_motion_event ( GdkEventMotion* event )
76 {
77 m_bFocus = event->x > OUTER_BORDER &&
78 event->x < (width - OUTER_BORDER) &&
79 event->y > OUTER_BORDER &&
80 event->y < (height - OUTER_BORDER);
81 redraw();
82 return true;
83 }
84
on_mouse_leave_widget(GdkEventCrossing * event)85 bool Button::on_mouse_leave_widget ( GdkEventCrossing* event )
86 {
87 m_bFocus = false;
88 redraw();
89 m_sigRelease.emit();
90 return true;
91 }
92
93
set_label(const Glib::ustring & label)94 void Button::set_label ( const Glib::ustring& label )
95 {
96 m_label = label;
97 redraw();
98 }
99
signal_clicked()100 Button::signal_Click Button::signal_clicked()
101 {
102 return m_sigClick;
103 }
104
signal_press()105 Button::signal_Click Button::signal_press()
106 {
107 return m_sigPress;
108 }
109
signal_release()110 Button::signal_Click Button::signal_release()
111 {
112 return m_sigRelease;
113 }
114
115
redraw()116 void Button::redraw()
117 {
118 Glib::RefPtr<Gdk::Window> win = get_window();
119 if(win)
120 {
121 Gdk::Rectangle r(0, 0, get_allocation().get_width(), get_allocation().get_height());
122 win->invalidate_rect(r, false);
123 }
124 }
125
on_expose_event(GdkEventExpose * event)126 bool Button::on_expose_event ( GdkEventExpose* event )
127 {
128 Glib::RefPtr<Gdk::Window> window = get_window();
129 if(window)
130 {
131 Gtk::Allocation allocation = get_allocation();
132 width = allocation.get_width();
133 height = allocation.get_height();
134
135 Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
136
137 //Paint backgroud
138 cr->save();
139 cr->set_source_rgb(BACKGROUND_R, BACKGROUND_G, BACKGROUND_B);
140 cr->paint(); //Fill all with background color
141 cr->restore();
142
143 //Draw button rectangle
144 cr->save();
145 double radius = height / 5.0;
146 double degrees = M_PI / 180.0;
147 cr->begin_new_sub_path();
148 cr->arc (width - OUTER_BORDER - radius, OUTER_BORDER + radius, radius, -90 * degrees, 0 * degrees);
149 cr->arc (width - OUTER_BORDER - radius, height - OUTER_BORDER - radius, radius, 0 * degrees, 90 * degrees);
150 cr->arc (OUTER_BORDER + radius, height- OUTER_BORDER - radius, radius, 90 * degrees, 180 * degrees);
151 cr->arc ( OUTER_BORDER + radius, OUTER_BORDER + radius, radius, 180 * degrees, 270 * degrees);
152 cr->close_path();
153
154 if(m_bFocus)
155 {
156 cr->set_source_rgb(0.2, 0.6, 0.5);
157 }
158 else if(m_bPress)
159 {
160 cr->set_source_rgb(0.5, 0.7, 0.8);
161 }
162 else
163 {
164 cr->set_source_rgb(0.5, 0.5, 0.5);
165 }
166
167 cr->set_line_width(1);
168 cr->stroke_preserve();
169
170 Cairo::RefPtr<Cairo::LinearGradient> bkg_gradient_ptr = Cairo::LinearGradient::create(width/2, OUTER_BORDER, width/2, height - OUTER_BORDER);
171 bkg_gradient_ptr->add_color_stop_rgba (0.0, 0.1, 0.2, 0.2, 0.3 );
172
173 if(m_bPress)
174 {
175 bkg_gradient_ptr->add_color_stop_rgba (0.7, 0.1, 0.2, 0.3, 0.8 );
176 }
177 else
178 {
179 bkg_gradient_ptr->add_color_stop_rgba (0.7, 0.4, 0.4, 0.4, 0.8 );
180 }
181
182 cr->set_source(bkg_gradient_ptr);
183 cr->fill();
184 cr->restore();
185
186 //Label
187 cr->save();
188 if(m_bFocus)
189 {
190 cr->set_source_rgb(0.2, 0.6, 0.5);
191 }
192 else if(m_bPress)
193 {
194 cr->set_source_rgb(0.7, 0.7, 0.9);
195 }
196 else
197 {
198 cr->set_source_rgb(TEXT_R, TEXT_G, TEXT_B);
199 }
200
201
202 Glib::RefPtr<Pango::Layout> pangoLayout = Pango::Layout::create(cr);
203 Pango::FontDescription font_desc("sans 11px");
204 pangoLayout->set_font_description(font_desc);
205 pangoLayout->set_width(Pango::SCALE * (width - OUTER_BORDER));
206 pangoLayout->set_height(Pango::SCALE * (height - OUTER_BORDER));
207 pangoLayout->set_alignment(Pango::ALIGN_CENTER);
208 cr->move_to(OUTER_BORDER, OUTER_BORDER + 2);
209 pangoLayout->set_text(m_label.c_str());
210 pangoLayout->show_in_cairo_context(cr);
211 cr->stroke();
212 cr->restore();
213
214 }
215
216 return true;
217 }
218