1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2 //
3 #ifndef SPECTMORPH_BUTTON_HH
4 #define SPECTMORPH_BUTTON_HH
5 
6 #include "smdrawutils.hh"
7 
8 namespace SpectMorph
9 {
10 
11 class Button : public Widget
12 {
13   std::string m_text;
14   bool        highlight = false;
15   bool        pressed = false;
16 
17 public:
18   Signal<> signal_clicked;
19   Signal<> signal_pressed;
20   Signal<> signal_released;
21 
Button(Widget * parent,const std::string & text)22   Button (Widget *parent, const std::string& text) :
23     Widget (parent),
24     m_text (text)
25   {
26   }
27   void
draw(const DrawEvent & devent)28   draw (const DrawEvent& devent) override
29   {
30     cairo_t *cr = devent.cr;
31     DrawUtils du (cr);
32 
33     double space = 2;
34     Color bg_color;
35     if (highlight)
36       bg_color.set_rgb (0.7, 0.7, 0.7);
37     else
38       bg_color.set_rgb (0.5, 0.5, 0.5);
39     if (pressed)
40       bg_color.set_rgb (0.3, 0.3, 0.3);
41 
42     Color frame_color (0.3, 0.3, 0.3);
43     if (pressed)
44       frame_color.set_rgb (0.4, 0.4, 0.4);
45 
46     if (!recursive_enabled())
47       bg_color.set_rgb (0.3, 0.3, 0.3);
48 
49     du.round_box (space, space, width() - 2 * space, height() - 2 * space, 1, 10, frame_color, bg_color);
50 
51     Color text_color (1, 1, 1);
52     if (!recursive_enabled())
53       text_color = Color (0.7, 0.7, 0.7);
54 
55     du.set_color (text_color);
56     du.text (m_text, 0, 0, width(), height(), TextAlign::CENTER);
57   }
58   void
enter_event()59   enter_event() override
60   {
61     highlight = true;
62     update();
63   }
64   void
mouse_press(const MouseEvent & event)65   mouse_press (const MouseEvent& event) override
66   {
67     if (event.button == LEFT_BUTTON)
68       {
69         pressed = true;
70         update();
71         signal_pressed();
72       }
73   }
74   void
mouse_release(const MouseEvent & event)75   mouse_release (const MouseEvent& event) override
76   {
77     if (event.button != LEFT_BUTTON || !pressed)
78       return;
79 
80     pressed = false;
81     update();
82     signal_released();
83 
84     if (event.x >= 0 && event.y >= 0 && event.x < width() && event.y < height())
85       signal_clicked();  // this must be the last line, as deletion can occur afterwards
86   }
87   void
leave_event()88   leave_event() override
89   {
90     highlight = false;
91     pressed = false;
92     update();
93   }
94   void
set_text(const std::string & text)95   set_text (const std::string& text)
96   {
97     if (m_text == text)
98       return;
99 
100     m_text = text;
101     update();
102   }
103 };
104 
105 }
106 
107 #endif
108