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