]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/GBox.C
Menu icons, gtk stock icons in toolbar
[lyx.git] / src / frontends / gtk / GBox.C
1 /**
2  * \file GBox.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Spray
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "GBox.h"
14
15 #include "ghelpers.h"
16
17 #include "controllers/ControlBox.h"
18
19 #include "insets/insetbox.h"
20 #include "lengthcommon.h"
21 #include "lyxrc.h" // to set the default length values
22
23 using std::string;
24 using std::vector;
25
26 namespace lyx {
27 namespace frontend {
28
29 namespace {
30 string defaultUnit("cm");
31 } // namespace anon
32
33 GBox::GBox(Dialog & parent)
34         : GViewCB<ControlBox, GViewGladeB>(parent, _("Box Settings"), false)
35 {}
36
37
38 void GBox::doBuild()
39 {
40         string const gladeName = findGladeFile("box");
41         xml_ = Gnome::Glade::Xml::create(gladeName);
42
43         Gtk::Button * closebutton;
44         xml_->get_widget("Close", closebutton);
45         setCancel(closebutton);
46
47         xml_->get_widget("Type", typecombo_);
48         bcview().addReadOnly(typecombo_);
49         xml_->get_widget("InnerBox", innerboxcombo_);
50         bcview().addReadOnly(innerboxcombo_);
51         xml_->get_widget("WidthUnits", widthunitscombo_);
52         bcview().addReadOnly(widthunitscombo_);
53         xml_->get_widget("HeightUnits", heightunitscombo_);
54         bcview().addReadOnly(heightunitscombo_);
55         xml_->get_widget("BoxVertical", boxvertcombo_);
56         bcview().addReadOnly(boxvertcombo_);
57         xml_->get_widget("ContentVertical", contentvertcombo_);
58         bcview().addReadOnly(contentvertcombo_);
59         xml_->get_widget("ContentHorizontal", contenthorzcombo_);
60         bcview().addReadOnly(contenthorzcombo_);
61         xml_->get_widget("Width", widthspin_);
62         bcview().addReadOnly(widthspin_);
63         xml_->get_widget("Height", heightspin_);
64         bcview().addReadOnly(heightspin_);
65
66         cols_.add(stringcol_);
67
68         // fill the box type choice
69         box_gui_tokens(ids_, gui_names_);
70         PopulateComboBox(typecombo_, gui_names_);
71         typecombo_->signal_changed().connect(
72                 sigc::mem_fun(*this, &GBox::onTypeComboChanged));
73
74         // set up innerbox (populated in setInnerType)
75         innerboxstore_ = Gtk::ListStore::create(cols_);
76         innerboxcombo_->set_model(innerboxstore_);
77         Gtk::CellRendererText * cell = Gtk::manage(new Gtk::CellRendererText);
78         innerboxcombo_->pack_start(*cell, true);
79         innerboxcombo_->add_attribute(*cell, "text", 0);
80
81         innerboxcombo_->signal_changed().connect(
82                 sigc::mem_fun(*this, &GBox::onInnerBoxComboChanged));
83
84         boxvertcombo_->signal_changed().connect(
85                 sigc::mem_fun(*this, &GBox::onAlignChanged));
86         contenthorzcombo_->signal_changed().connect(
87                 sigc::mem_fun(*this, &GBox::onAlignChanged));
88         contentvertcombo_->signal_changed().connect(
89                 sigc::mem_fun(*this, &GBox::onAlignChanged));
90
91         heightunitscombo_->signal_changed().connect(
92                 sigc::mem_fun(*this, &GBox::onHeightChanged));
93         widthunitscombo_->signal_changed().connect(
94                 sigc::mem_fun(*this, &GBox::onWidthChanged));
95
96         heightspin_->signal_value_changed().connect(
97                 sigc::mem_fun(*this, &GBox::onHeightChanged));
98         widthspin_->signal_value_changed().connect(
99                 sigc::mem_fun(*this, &GBox::onWidthChanged));
100
101
102         widthunitsstore_ = Gtk::ListStore::create(cols_);
103         widthunitscombo_->set_model(widthunitsstore_);
104         cell = Gtk::manage(new Gtk::CellRendererText);
105         widthunitscombo_->pack_start(*cell, true);
106         widthunitscombo_->add_attribute(*cell, "text", 0);
107         //widthunitscombo_ is populated in setSpecial
108
109         box_gui_tokens_special_length(ids_spec_, gui_names_spec_);
110         vector<string> heightunits = buildLengthUnitList();
111         // Append special entries, skipping the first item "None"
112         heightunits.insert(heightunits.end(),
113                 ++gui_names_spec_.begin(), gui_names_spec_.end());
114
115         PopulateComboBox(heightunitscombo_, heightunits);
116 }
117
118
119 void GBox::PopulateComboBox(Gtk::ComboBox * combo,
120                                   vector<string> const & strings
121                                   )
122 {
123         Glib::RefPtr<Gtk::ListStore> model = Gtk::ListStore::create(cols_);
124         vector<string>::const_iterator it = strings.begin();
125         vector<string>::const_iterator end = strings.end();
126         for(; it != end; ++it)
127                 (*model->append())[stringcol_] = *it;
128
129         combo->set_model(model);
130         Gtk::CellRendererText * cell = Gtk::manage(new Gtk::CellRendererText);
131         combo->pack_start(*cell, true);
132         combo->add_attribute(*cell, "text", 0);
133 }
134
135
136 void GBox::update()
137 {
138         applylock_ = true;
139
140         defaultUnit = getDefaultUnit();
141
142         char c = controller().params().pos;
143         boxvertcombo_->set_active(string("tcb").find(c, 0));
144         c = controller().params().inner_pos;
145         contentvertcombo_->set_active(string("tcbs").find(c, 0));
146         c = controller().params().hor_pos;
147         contenthorzcombo_->set_active(string("lcrs").find(c, 0));
148
149         string type(controller().params().type);
150         for (unsigned int i = 0; i < gui_names_.size(); ++i) {
151                 if (type == ids_[i])
152                         typecombo_->set_active(i);
153         }
154
155         applylock_ = false;
156         updateInnerBoxCombo();
157         applylock_ = true;
158
159         bool ibox = controller().params().inner_box;
160         boxvertcombo_->set_sensitive(ibox);
161         contentvertcombo_->set_sensitive(ibox);
162         contenthorzcombo_->set_sensitive(!ibox);
163         setSpecial(ibox);
164
165         widthspin_->get_adjustment()->set_value(controller().params().width.value());
166         unitsComboFromLength(widthunitscombo_, stringcol_,
167                              controller().params().width, defaultUnit);
168
169         string const special(controller().params().special);
170         if (!special.empty() && special != "none") {
171                 string spc;
172                 for (unsigned int i = 0; i < gui_names_spec_.size(); ++i) {
173                         if (special == ids_spec_[i])
174                                 spc = gui_names_spec_[i];
175                 }
176                 for (int j = 0; j < widthunitsstore_->children().size(); ++j) {
177                         if (widthunitsstore_->children()[j][stringcol_] == spc)
178                                 widthunitscombo_->set_active(j);
179                 }
180         }
181
182         heightspin_->get_adjustment()->set_value(controller().params().height.value());
183         unitsComboFromLength(heightunitscombo_, stringcol_,
184                              controller().params().height, defaultUnit);
185
186         string const height_special(controller().params().height_special);
187         if (!height_special.empty() && height_special != "none") {
188                 string hspc;
189                 for (unsigned int i = 0; i < gui_names_spec_.size(); ++i) {
190                         if (height_special == ids_spec_[i]) {
191                                 hspc = gui_names_spec_[i];
192                         }
193                 }
194                 for (int j = 0; j < heightunitscombo_->get_model()->children().size(); ++j) {
195                         if (heightunitscombo_->get_model()->children()[j][stringcol_] == hspc) {
196                                 heightunitscombo_->set_active(j);
197                         }
198                 }
199         }
200
201         heightspin_->set_sensitive(ibox);
202         heightunitscombo_->set_sensitive(ibox);
203         applylock_ = false;
204 }
205
206
207 void GBox::setSpecial(bool ibox)
208 {
209         bool const oldlock = applylock_;
210         applylock_ = true;
211
212         unsigned int const initselection = widthunitscombo_->get_active_row_number();
213         widthunitsstore_->clear();
214         vector<string> normalunits = buildLengthUnitList();
215         if (ibox) {
216                 vector<string>::const_iterator it = normalunits.begin();
217                 vector<string>::const_iterator end = normalunits.end();
218                 for(; it != end; ++it)
219                         (*widthunitsstore_->append())[stringcol_] = *it;
220         } else {
221                 vector<string>::const_iterator it = normalunits.begin();
222                 vector<string>::const_iterator end = normalunits.end();
223                 for(; it != end; ++it)
224                         (*widthunitsstore_->append())[stringcol_] = *it;
225                 // Skip the first item "None"
226                 it = ++gui_names_spec_.begin();
227                 end = gui_names_spec_.end();
228                 for(; it != end; ++it)
229                         (*widthunitsstore_->append())[stringcol_] = *it;
230         }
231
232         int const store_size = widthunitsstore_->children().size();
233         if (initselection >= store_size) {
234                 widthunitscombo_->set_active(0);
235                 onWidthChanged();
236         } else {
237                 widthunitscombo_->set_active(initselection);
238         }
239         applylock_ = oldlock;
240 }
241
242
243 void GBox::updateInnerBoxCombo()
244 {
245         bool const oldlock = applylock_;
246         applylock_ = true;
247         // with "frameless" boxes, inner box is mandatory (i.e. is the actual box)
248         // we have to remove "none" then and adjust the combo
249
250         // default: minipage
251         unsigned int i = 2;
252         if (!controller().params().inner_box)
253                 // none
254                 i = 0;
255         if (controller().params().use_parbox)
256                 // parbox
257                 i = 1;
258         bool frameless = (controller().params().type == "Frameless");
259
260         int const oldsize = innerboxstore_->children().size();
261         // Store the initial selection in 0,1,2 format
262         int oldselection = -1;
263         if (oldsize == 2)
264                 oldselection = innerboxcombo_->get_active_row_number() + 1;
265         else if (oldsize == 3)
266                 oldselection = innerboxcombo_->get_active_row_number();
267
268         if (frameless && oldsize != 2) {
269                 innerboxstore_->clear();
270                 (*innerboxstore_->append())[stringcol_] = _("Parbox");
271                 (*innerboxstore_->append())[stringcol_] = _("Minipage");
272                 // Cope when the backend asks for no inner box in
273                 // a frameless box
274                 if (i == 0) {
275                         applylock_ = false;
276                         innerboxcombo_->set_active(i);
277                         applylock_ = true;
278                 } else
279                         innerboxcombo_->set_active(i - 1);
280         } else if (!frameless && oldsize != 3) {
281                 innerboxstore_->clear();
282                 (*innerboxstore_->append())[stringcol_] = _("None");
283                 (*innerboxstore_->append())[stringcol_] = _("Parbox");
284                 (*innerboxstore_->append())[stringcol_] = _("Minipage");
285                 innerboxcombo_->set_active(i);
286         } else {
287                 // we're not changing the liststore, just selecting i
288                 if (frameless)
289                         innerboxcombo_->set_active(i - 1);
290                 else
291                         innerboxcombo_->set_active(i);
292         }
293
294         // Update the width units list if we've changed inner box type
295         if (i != oldselection)
296                 setSpecial(i != 0);
297
298         applylock_ = oldlock;
299 }
300
301
302 void GBox::onInnerBoxComboChanged()
303 {
304         if (applylock_)
305                 return;
306
307         controller().params().use_parbox =
308                 (*innerboxcombo_->get_active())[stringcol_] ==  _("Parbox");
309
310         bool const ibox = (*innerboxcombo_->get_active())[stringcol_] != _("None");
311         controller().params().inner_box = ibox;
312         setSpecial(ibox);
313
314         boxvertcombo_->set_sensitive(ibox);
315         contentvertcombo_->set_sensitive(ibox);
316         contenthorzcombo_->set_sensitive(!ibox);
317         heightspin_->set_sensitive(ibox);
318         heightunitscombo_->set_sensitive(ibox);
319         // wtf? form_->set_sensitive(ibox);
320
321         controller().dispatchParams();
322 }
323
324
325 void GBox::onTypeComboChanged()
326 {
327         int const index = typecombo_->get_active_row_number();
328         controller().params().type = ids_[index];
329
330         bool frameless = (index == 0);
331         if (frameless) {
332                 boxvertcombo_->set_sensitive(true);
333                 contentvertcombo_->set_sensitive(true);
334                 contenthorzcombo_->set_sensitive(false);
335                 heightspin_->set_sensitive(true);
336                 heightunitscombo_->set_sensitive(true);
337                 //wtf? form_->setSpecial(true);
338         }
339         //int itype = innerboxcombo_->get_active_row_number();
340         controller().dispatchParams();
341
342         updateInnerBoxCombo();
343 }
344
345
346 void GBox::onHeightChanged()
347 {
348         if (applylock_)
349                 return;
350
351         // "None"
352         int i = 0;
353         bool spec = false;
354         Glib::ustring special = (*heightunitscombo_->get_active())[stringcol_];
355         for (int j = 1; j < gui_names_spec_.size() ; ++j) {
356                 if (gui_names_spec_[j] == special) {
357                         i=j;
358                         spec = true;
359                 }
360         }
361         controller().params().height_special = ids_spec_[i];
362
363         string height;
364         if (spec) {
365                 height = heightspin_->get_text();
366                 // beware: bogosity! the unit is simply ignored in this case
367                 height += "in";
368         } else {
369                 Glib::ustring const heightunit =
370                         (*heightunitscombo_->get_active())[stringcol_];
371                 height = heightspin_->get_text() + heightunit;
372         }
373
374         controller().params().height = LyXLength(height);
375         controller().dispatchParams();
376 }
377
378
379 void GBox::onWidthChanged()
380 {
381         if (applylock_)
382                 return;
383
384         int i = 0;
385         bool spec = false;
386         Glib::ustring special = (*widthunitscombo_->get_active())[stringcol_];
387         for (int j = 1; j < gui_names_spec_.size() ; ++j) {
388                 if (gui_names_spec_[j] == special) {
389                         i=j;
390                         spec = true;
391                 }
392         }
393         controller().params().special = ids_spec_[i];
394
395         string width;
396         if (spec) {
397                 width = widthspin_->get_text();
398                 // beware: bogosity! the unit is simply ignored in this case
399                 width += "in";
400         } else {
401                 Glib::ustring const widthunit =
402                         (*widthunitscombo_->get_active())[stringcol_];
403                 width = widthspin_->get_text() + widthunit;
404         }
405
406         controller().params().width = LyXLength(width);
407         controller().dispatchParams();
408 }
409
410
411 void GBox::onAlignChanged()
412 {
413         if (applylock_)
414                 return;
415
416         controller().params().pos =
417                 "tcb"[boxvertcombo_->get_active_row_number()];
418         controller().params().inner_pos =
419                 "tcbs"[contenthorzcombo_->get_active_row_number()];
420         controller().params().hor_pos =
421                 "lcrs"[contentvertcombo_->get_active_row_number()];
422
423         controller().dispatchParams();
424 }
425
426 } // namespace frontend
427 } // namespace lyx