1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2 
3 #include "smcomboboxoperator.hh"
4 
5 #include <assert.h>
6 
7 using namespace SpectMorph;
8 
9 using std::string;
10 using std::vector;
11 
12 #define OPERATOR_TEXT_NONE "<none>"
13 
ComboBoxOperator(Widget * parent,MorphPlan * morph_plan,const OperatorFilter & operator_filter)14 ComboBoxOperator::ComboBoxOperator (Widget *parent, MorphPlan *morph_plan, const OperatorFilter& operator_filter) :
15   Widget (parent),
16   morph_plan (morph_plan),
17   op_filter (operator_filter),
18   op (NULL)
19 {
20   combobox = new ComboBox (this);
21 
22   on_update_combobox_geometry();
23   connect (signal_width_changed, this, &ComboBoxOperator::on_update_combobox_geometry);
24   connect (signal_height_changed, this, &ComboBoxOperator::on_update_combobox_geometry);
25 
26   none_ok = true;
27 
28   on_operators_changed();
29 
30   connect (combobox->signal_item_changed, this, &ComboBoxOperator::on_combobox_changed);
31   connect (morph_plan->signal_plan_changed, this, &ComboBoxOperator::on_operators_changed);
32 }
33 
34 void
on_update_combobox_geometry()35 ComboBoxOperator::on_update_combobox_geometry()
36 {
37   combobox->set_x (0);
38   combobox->set_y (0);
39   combobox->set_width (width());
40   combobox->set_height (height());
41 }
42 
43 void
on_operators_changed()44 ComboBoxOperator::on_operators_changed()
45 {
46   combobox->clear();
47 
48   if (none_ok)
49     combobox->add_item (OPERATOR_TEXT_NONE);
50 
51   for (auto item : str_items)
52     {
53       if (item.headline)
54         combobox->add_item (ComboBoxItem (item.text, true));
55       else
56         combobox->add_item (item.text);
57     }
58 
59   bool add_op_headline = (op_headline != "");
60   for (MorphOperator *morph_op : morph_plan->operators())
61     {
62       if (op_filter (morph_op))
63         {
64           if (add_op_headline)
65             {
66               // if we find any matches, add op_headline once
67               combobox->add_item (ComboBoxItem (op_headline, true));
68               add_op_headline = false;
69             }
70           combobox->add_item (morph_op->name());
71         }
72     }
73 
74   // update selected item
75   string active_name = OPERATOR_TEXT_NONE;
76   if (op)
77     active_name = op->name();
78   if (str_choice != "")
79     active_name = str_choice;
80 
81   combobox->set_text (active_name);
82 }
83 
84 void
on_combobox_changed()85 ComboBoxOperator::on_combobox_changed()
86 {
87   string active_text = combobox->text();
88 
89   op         = NULL;
90   str_choice = "";
91 
92   for (MorphOperator *morph_op : morph_plan->operators())
93     {
94       if (morph_op->name() == active_text)
95         {
96           op         = morph_op;
97           str_choice = "";
98         }
99     }
100   for (auto item : str_items)
101     {
102       if (!item.headline && item.text == active_text)
103         {
104           op         = NULL;
105           str_choice = item.text;
106         }
107     }
108   signal_item_changed();
109 }
110 
111 void
set_active(MorphOperator * new_op)112 ComboBoxOperator::set_active (MorphOperator *new_op)
113 {
114   op         = new_op;
115   str_choice = "";
116 
117   on_operators_changed();
118 }
119 
120 MorphOperator *
active()121 ComboBoxOperator::active()
122 {
123   return op;
124 }
125 
126 void
set_op_headline(const std::string & headline)127 ComboBoxOperator::set_op_headline (const std::string& headline)
128 {
129   op_headline = headline;
130 }
131 
132 void
add_str_choice(const string & str)133 ComboBoxOperator::add_str_choice (const string& str)
134 {
135   str_items.push_back (StrItem {false, str});
136 
137   on_operators_changed();
138 }
139 
140 void
add_str_headline(const std::string & str)141 ComboBoxOperator::add_str_headline (const std::string& str)
142 {
143   str_items.push_back (StrItem {true, str});
144 
145   on_operators_changed();
146 }
147 
148 void
clear_str_choices()149 ComboBoxOperator::clear_str_choices()
150 {
151   str_items.clear();
152   str_choice = "";
153 
154   on_operators_changed();
155 }
156 
157 string
active_str_choice()158 ComboBoxOperator::active_str_choice()
159 {
160   return str_choice;
161 }
162 
163 void
set_active_str_choice(const string & new_str)164 ComboBoxOperator::set_active_str_choice (const string& new_str)
165 {
166   for (auto item : str_items)
167     {
168       if (new_str == item.text)
169         {
170           op         = NULL;
171           str_choice = item.text;
172 
173           on_operators_changed();
174 
175           return;
176         }
177     }
178   fprintf (stderr, "ComboBoxOperator::set_active_str_choice (%s) failed\n", new_str.c_str());
179 
180   str_choice = "";
181   on_operators_changed();
182 }
183 
184 void
set_none_ok(bool new_none_ok)185 ComboBoxOperator::set_none_ok (bool new_none_ok)
186 {
187   none_ok = new_none_ok;
188 
189   on_operators_changed();
190 }
191