/[svn]/gigedit/trunk/src/gigedit/paramedit.cpp
ViewVC logotype

Annotation of /gigedit/trunk/src/gigedit/paramedit.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3364 - (hide annotations) (download)
Tue Nov 14 18:07:25 2017 UTC (6 years, 5 months ago) by schoenebeck
File size: 17821 byte(s)
* Added experimental support for upcoming GTK(MM)4
  (for now up to GTKMM 3.91.2 while still preserving backward compatibility
  down to GTKMM 2).
* Re-merged r2845 to compile now with and without Gtk "Stock ID" API
  (see also r3158).

1 schoenebeck 1225 /*
2 schoenebeck 3364 * Copyright (C) 2006-2017 Andreas Persson
3 schoenebeck 1225 *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License as
6     * published by the Free Software Foundation; either version 2, or (at
7     * your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful, but
10     * WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12     * General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with program; see the file COPYING. If not, write to the Free
16     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17     * 02110-1301 USA.
18     */
19    
20 persson 3202 #include "global.h"
21 schoenebeck 1225 #include "paramedit.h"
22    
23 persson 2169 #include "compat.h"
24 schoenebeck 2541 #include "Settings.h"
25 persson 1831
26 schoenebeck 2541 #include <gtkmm/messagedialog.h>
27    
28 schoenebeck 1225 namespace {
29 schoenebeck 2541 struct CCText {
30     const char* const txt;
31     bool isExtension; ///< True if this is a controller only supported by LinuxSampler, but not supperted by Gigasampler/GigaStudio.
32     };
33     static const CCText controlChangeTexts[] = {
34     // 3 special ones (not being CCs)
35     { _("none") }, { _("channelaftertouch") }, { _("velocity") },
36     {0}, // bank select MSB (hard coded in sampler, so discouraged to be used here, even though considerable)
37     { _("modwheel") }, // "Modulation Wheel or Lever",
38     { _("breath") }, // "Breath Controller",
39     { _("undefined"), true },
40     { _("foot") }, // "Foot Controller",
41     { _("portamentotime") }, // "Portamento Time",
42     { _("data entry MSB"), true },
43     { _("volume"), true },
44     { _("balance"), true },
45     { _("undefined"), true },
46     { _("pan"), true },
47     { _("expression"), true },
48     { _("effect1") }, // "Effect Control 1",
49     { _("effect2") }, // "Effect Control 2",
50     { _("undefined"), true },
51     { _("undefined"), true },
52     { _("genpurpose1") }, // "General Purpose Controller 1",
53     { _("genpurpose2") }, // "General Purpose Controller 2",
54     { _("genpurpose3") }, // "General Purpose Controller 3",
55     { _("genpurpose4") }, // "General Purpose Controller 4",
56     { _("undefined"), true },
57     { _("undefined"), true },
58     { _("undefined"), true },
59     { _("undefined"), true },
60     { _("undefined"), true },
61     { _("undefined"), true },
62     { _("undefined"), true },
63     { _("undefined"), true },
64     { _("undefined"), true },
65     { _("undefined"), true },
66     { _("undefined"), true },
67     { _("undefined"), true },
68 schoenebeck 2538
69     // LSB variant of the various controllers above
70     // (so discouraged to be used here for now)
71 schoenebeck 2541 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
72     {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
73     {0}, {0}, {0}, {0},
74 schoenebeck 2538
75 schoenebeck 2541 { _("sustainpedal") }, // "Damper Pedal on/off (Sustain)",
76     { _("portamento") }, // "Portamento On/Off",
77     { _("sostenuto") }, // "Sustenuto On/Off",
78     { _("softpedal") }, // "Soft Pedal On/Off",
79     { _("legato"), true },
80     { _("hold2"), true },
81     { _("soundvariation"), true },
82     { _("timbre"), true },
83     { _("releasetime"), true },
84     { _("attacktime"), true },
85     { _("brightness"), true },
86     { _("decaytime"), true },
87     { _("vibratorate"), true },
88     { _("vibratodepth"), true },
89     { _("vibratodelay"), true },
90     { _("undefined"), true },
91     { _("genpurpose5") }, // "General Purpose Controller 5",
92     { _("genpurpose6") }, // "General Purpose Controller 6",
93     { _("genpurpose7") }, // "General Purpose Controller 7",
94     { _("genpurpose8") }, // "General Purpose Controller 8",
95     { _("portamentoctrl"), true },
96     { _("undefined"), true },
97     { _("undefined"), true },
98     { _("undefined"), true },
99     {0}, // high resolution velocity prefix (so discouraged to be used here)
100     { _("undefined"), true },
101     { _("undefined"), true },
102     { _("effect1depth") }, // "Effects 1 Depth",
103     { _("effect2depth") }, // "Effects 2 Depth",
104     { _("effect3depth") }, // "Effects 3 Depth",
105     { _("effect4depth") }, // "Effects 4 Depth",
106     { _("effect5depth") }, // "Effects 5 Depth"
107     { _("dataincrement"), true },
108     { _("datadecrement"), true },
109     {0}, // NRPN LSB (so discouraged to be used here)
110     {0}, // NRPN MSB (so discouraged to be used here)
111     {0}, // RPN LSB (so discouraged to be used here)
112     {0}, // RPN MSB (so discouraged to be used here)
113     { _("undefined"), true },
114     { _("undefined"), true },
115     { _("undefined"), true },
116     { _("undefined"), true },
117     { _("undefined"), true },
118     { _("undefined"), true },
119     { _("undefined"), true },
120     { _("undefined"), true },
121     { _("undefined"), true },
122     { _("undefined"), true },
123     { _("undefined"), true },
124     { _("undefined"), true },
125     { _("undefined"), true },
126     { _("undefined"), true },
127     { _("undefined"), true },
128     { _("undefined"), true },
129     { _("undefined"), true },
130     { _("undefined"), true } // CC 119
131 schoenebeck 2538 // (all other ones that follow [CC 120- CC 127] are hard coded channel
132     // mode messages, so those are discouraged to be used here)
133 schoenebeck 1225 };
134     }
135    
136 schoenebeck 2541 #define controlChangeTextsSize (sizeof(controlChangeTexts) / sizeof(CCText))
137 schoenebeck 2538
138 schoenebeck 1225 LabelWidget::LabelWidget(const char* labelText, Gtk::Widget& widget) :
139     label(Glib::ustring(labelText) + ":"),
140     widget(widget)
141     {
142 schoenebeck 3364 #if HAS_GTKMM_ALIGNMENT
143 persson 2169 label.set_alignment(Gtk::ALIGN_START);
144 schoenebeck 3364 #else
145     label.set_halign(Gtk::Align::START);
146     #endif
147 schoenebeck 1225 }
148    
149     void LabelWidget::set_sensitive(bool sensitive)
150     {
151     label.set_sensitive(sensitive);
152     widget.set_sensitive(sensitive);
153     }
154    
155 schoenebeck 2690 ReadOnlyLabelWidget::ReadOnlyLabelWidget(const char* leftHandText)
156     : LabelWidget(leftHandText, text)
157     {
158 schoenebeck 3364 #if HAS_GTKMM_ALIGNMENT
159 schoenebeck 2690 text.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_START);
160 schoenebeck 3364 #else
161     label.set_halign(Gtk::Align::START);
162     label.set_valign(Gtk::Align::START);
163     #endif
164 schoenebeck 2690 }
165    
166     ReadOnlyLabelWidget::ReadOnlyLabelWidget(const char* leftHandText, const char* rightHandText)
167     : LabelWidget(leftHandText, text)
168     {
169 schoenebeck 3364 #if HAS_GTKMM_ALIGNMENT
170 schoenebeck 2690 text.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_START);
171 schoenebeck 3364 #else
172     text.set_halign(Gtk::Align::START);
173     text.set_valign(Gtk::Align::START);
174     #endif
175 schoenebeck 2690 text.set_text(rightHandText);
176     }
177    
178 schoenebeck 1225 NumEntry::NumEntry(const char* labelText, double lower, double upper,
179     int decimals) :
180 persson 2151 LabelWidget(labelText, box),
181 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
182 schoenebeck 1225 adjust(lower, lower, upper, 1, 10),
183 persson 2169 #else
184     adjust(Gtk::Adjustment::create(lower, lower, upper, 1, 10)),
185     #endif
186 schoenebeck 1225 scale(adjust),
187 persson 2151 spinbutton(adjust)
188 schoenebeck 1225 {
189 persson 2423 scale.set_size_request(70);
190 schoenebeck 1225 spinbutton.set_digits(decimals);
191 persson 1460 spinbutton.set_value(0);
192 persson 2507 spinbutton.set_numeric();
193 schoenebeck 1225 scale.set_draw_value(false);
194     box.pack_start(spinbutton, Gtk::PACK_SHRINK);
195     box.add(scale);
196     }
197    
198     NumEntryGain::NumEntryGain(const char* labelText,
199     double lower, double upper,
200     int decimals, double coeff) :
201     NumEntry(labelText, lower, upper, decimals),
202 persson 2151 value(0),
203 persson 1460 coeff(coeff),
204     connected(true)
205 schoenebeck 1225 {
206     spinbutton.signal_value_changed().connect(
207     sigc::mem_fun(*this, &NumEntryGain::value_changed));
208     }
209    
210     void NumEntryGain::value_changed()
211     {
212 persson 1460 if (!connected) return;
213    
214 schoenebeck 1359 const double f = pow(10, spinbutton.get_digits());
215     int new_value = round_to_int(spinbutton.get_value() * f);
216 persson 1460 if (new_value != round_to_int(value / coeff * f)) {
217     value = round_to_int(new_value / f * coeff);
218     sig_changed();
219 schoenebeck 1225 }
220     }
221    
222 persson 1460 void NumEntryGain::set_value(int32_t value)
223 schoenebeck 1225 {
224 persson 1460 if (value != this->value) {
225     this->value = value;
226    
227     connected = false;
228     bool plus6 = value < 0;
229     spinbutton.set_value(plus6 ? 0 : value / coeff);
230     set_sensitive(!plus6);
231     connected = true;
232    
233     sig_changed();
234     }
235 schoenebeck 1225 }
236    
237    
238     BoolEntryPlus6::BoolEntryPlus6(const char* labelText, NumEntryGain& eGain, int32_t plus6value) :
239     LabelWidget(labelText, checkbutton),
240 persson 1262 checkbutton(labelText),
241 schoenebeck 1225 eGain(eGain),
242     plus6value(plus6value)
243     {
244     checkbutton.signal_toggled().connect(
245     sigc::mem_fun(*this, &BoolEntryPlus6::value_changed));
246     }
247    
248     void BoolEntryPlus6::value_changed()
249     {
250 persson 1460 if (checkbutton.get_active()) eGain.set_value(plus6value);
251     else if (eGain.get_value() < 0) eGain.set_value(0);
252 schoenebeck 1225 }
253    
254 persson 1460 int32_t BoolEntryPlus6::get_value() const
255 schoenebeck 1225 {
256 persson 1460 return eGain.get_value();
257 schoenebeck 1225 }
258    
259 persson 1460 void BoolEntryPlus6::set_value(int32_t value)
260     {
261     checkbutton.set_active(value < 0);
262     }
263    
264 schoenebeck 1225 NumEntryPermille::NumEntryPermille(const char* labelText,
265     double lower, double upper, int decimals) :
266 persson 1460 NumEntry(labelText, lower, upper, decimals),
267     value(0)
268 schoenebeck 1225 {
269     spinbutton.signal_value_changed().connect(
270     sigc::mem_fun(*this, &NumEntryPermille::value_changed));
271     }
272    
273     void NumEntryPermille::value_changed()
274     {
275 persson 1460 uint16_t new_value = uint16_t(spinbutton.get_value() * 10 + 0.5);
276     if (new_value != value) {
277     value = uint16_t(spinbutton.get_value() * 10 + 0.5);
278     sig_changed();
279 schoenebeck 1225 }
280     }
281    
282 persson 1460 void NumEntryPermille::set_value(uint16_t value)
283 schoenebeck 1225 {
284 persson 1460 if (value != this->value) {
285     spinbutton.set_value(value / 10.0);
286     }
287 schoenebeck 1225 }
288    
289    
290     NoteEntry::NoteEntry(const char* labelText) :
291     NumEntryTemp<uint8_t>(labelText)
292     {
293 persson 2507 spin_button_show_notes(spinbutton);
294 schoenebeck 1225 }
295    
296 persson 2507 namespace {
297     const char* notes[] = {
298     _("C"), _("C#"), _("D"), _("D#"), _("E"), _("F"),_("F#"),
299     _("G"), _("G#"), _("A"), _("A#"), _("B")
300     };
301 schoenebeck 1225
302 persson 2507 int note_value(const Glib::ustring& note, double* value)
303     {
304     const char* str = note.c_str();
305 schoenebeck 1225
306 persson 2507 int i;
307     for (i = 11 ; i >= 0 ; i--) {
308     if (strncasecmp(str, notes[i], strlen(notes[i])) == 0) break;
309     }
310     if (i >= 0) {
311     char* endptr;
312     long x = strtol(str + strlen(notes[i]), &endptr, 10);
313     if (endptr != str + strlen(notes[i])) {
314     *value = std::max(0L, std::min(i + (x + 1) * 12, 127L));
315     return true;
316     }
317     } else {
318     char* endptr;
319     long x = strtol(str, &endptr, 10);
320     if (endptr != str) {
321     *value = std::max(0L, std::min(x, 127L));
322     return true;
323     }
324     }
325 schoenebeck 3364
326     #if HAS_GTKMM_CPP11_ENUMS
327     return Gtk::SpinButton::INPUT_ERROR;
328     #else
329 persson 2507 return Gtk::INPUT_ERROR;
330 schoenebeck 3364 #endif
331 persson 2507 }
332     }
333    
334     int note_value(const Glib::ustring& note)
335 schoenebeck 1225 {
336 persson 2507 double value = 0;
337     note_value(note, &value);
338     return value;
339     }
340 schoenebeck 1225
341 persson 2507 Glib::ustring note_str(int note)
342     {
343     char buf[10];
344     sprintf(buf, "%s%d", notes[note % 12], note / 12 - 1);
345     return buf;
346     }
347    
348     namespace {
349     // Convert the Entry text to a number
350 schoenebeck 3364 #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
351     int on_input(double& new_value, Gtk::SpinButton* spinbutton) {
352     return note_value(spinbutton->get_text(), &new_value);
353     }
354     #else
355 persson 2507 int on_input(double* new_value, Gtk::SpinButton* spinbutton) {
356     return note_value(spinbutton->get_text(), new_value);
357 schoenebeck 1225 }
358 schoenebeck 3364 #endif
359 persson 2507
360     // Convert the Adjustment position to text
361     bool on_output(Gtk::SpinButton* spinbutton) {
362     spinbutton->set_text(
363     note_str(spinbutton->get_adjustment()->get_value() + 0.5));
364     return true;
365 schoenebeck 1225 }
366     }
367    
368 persson 2507 // Make a SpinButton show notes instead of numbers
369     void spin_button_show_notes(Gtk::SpinButton& spin_button)
370 schoenebeck 1225 {
371 persson 2507 spin_button.set_numeric(false);
372     spin_button.set_width_chars(4);
373     spin_button.signal_input().connect(
374     sigc::bind(sigc::ptr_fun(&on_input), &spin_button));
375     spin_button.signal_output().connect(
376     sigc::bind(sigc::ptr_fun(&on_output), &spin_button));
377 schoenebeck 1225 }
378    
379     ChoiceEntryLeverageCtrl::ChoiceEntryLeverageCtrl(const char* labelText) :
380 schoenebeck 3364 #if HAS_GTKMM_ALIGNMENT
381 persson 2151 LabelWidget(labelText, align),
382     align(0, 0, 0, 0)
383 schoenebeck 3364 #else
384     LabelWidget(labelText, combobox)
385     #endif
386 schoenebeck 1225 {
387 schoenebeck 2538 for (int i = 0 ; i < controlChangeTextsSize ; i++) {
388 schoenebeck 2541 if (controlChangeTexts[i].txt) {
389 schoenebeck 2538 const int cc = i - 3;
390     Glib::ustring s = (i < 3)
391 schoenebeck 2541 ? controlChangeTexts[i].txt
392     : Glib::ustring::compose("CC%1: %2%3", cc, controlChangeTexts[i].txt, controlChangeTexts[i].isExtension ? " [EXT]" : "");
393 persson 2507 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
394 schoenebeck 2538 combobox.append_text(s);
395 persson 2169 #else
396 schoenebeck 2538 combobox.append(s);
397 persson 2169 #endif
398 schoenebeck 1225 }
399     }
400     combobox.signal_changed().connect(
401     sigc::mem_fun(*this, &ChoiceEntryLeverageCtrl::value_changed));
402 schoenebeck 3364 #if HAS_GTKMM_ALIGNMENT
403 schoenebeck 1225 align.add(combobox);
404 schoenebeck 3364 #else
405     combobox.set_halign(Gtk::Align::FILL);
406     combobox.set_valign(Gtk::Align::FILL);
407     #endif
408 persson 1460 value.type = gig::leverage_ctrl_t::type_none;
409     value.controller_number = 0;
410 schoenebeck 1225 }
411    
412     void ChoiceEntryLeverageCtrl::value_changed()
413     {
414 persson 1460 int rowno = combobox.get_active_row_number();
415     switch (rowno)
416     {
417     case -1:
418     break;
419     case 0:
420     value.type = gig::leverage_ctrl_t::type_none;
421     break;
422     case 1:
423     value.type = gig::leverage_ctrl_t::type_channelaftertouch;
424     break;
425     case 2:
426     value.type = gig::leverage_ctrl_t::type_velocity;
427     break;
428     default:
429     value.type = gig::leverage_ctrl_t::type_controlchange;
430     int x = 3;
431 schoenebeck 2538 for (uint cc = 0 ; cc < controlChangeTextsSize - 3 ; cc++) {
432 schoenebeck 2541 if (controlChangeTexts[cc + 3].txt) {
433 persson 1460 if (rowno == x) {
434     value.controller_number = cc;
435 schoenebeck 2541 if (controlChangeTexts[cc + 3].isExtension &&
436     Settings::singleton()->warnUserOnExtensions)
437     {
438     Glib::ustring txt = _("<b>Format Extension</b>\n\nAll controllers marked with \"<b>[EXT]</b>\" are an extension to the original gig sound format. They will only work with LinuxSampler, but they will <b>not work</b> with Gigasampler/GigaStudio!\n\n(You may disable this warning in the <i>Settings</i> menu.)");
439     Gtk::MessageDialog msg(
440     txt, true, Gtk::MESSAGE_WARNING
441     );
442     msg.run();
443     }
444 persson 1460 break;
445 schoenebeck 1225 }
446 persson 1460 x++;
447 schoenebeck 1225 }
448     }
449 persson 1460 break;
450 schoenebeck 1225 }
451 persson 1460 if (rowno >= 0) sig_changed();
452 schoenebeck 1225 }
453    
454 persson 1460 void ChoiceEntryLeverageCtrl::set_value(gig::leverage_ctrl_t value)
455 schoenebeck 1225 {
456 schoenebeck 2538 int comboIndex;
457 persson 1460 switch (value.type)
458 schoenebeck 1225 {
459     case gig::leverage_ctrl_t::type_none:
460 schoenebeck 2538 comboIndex = 0;
461 schoenebeck 1225 break;
462     case gig::leverage_ctrl_t::type_channelaftertouch:
463 schoenebeck 2538 comboIndex = 1;
464 schoenebeck 1225 break;
465     case gig::leverage_ctrl_t::type_velocity:
466 schoenebeck 2538 comboIndex = 2;
467 schoenebeck 1225 break;
468 schoenebeck 2538 case gig::leverage_ctrl_t::type_controlchange: {
469     comboIndex = -1;
470     int x = 3;
471     for (uint cc = 0 ; cc < controlChangeTextsSize - 3 ; cc++) {
472 schoenebeck 2541 if (controlChangeTexts[cc + 3].txt) {
473 persson 1460 if (value.controller_number == cc) {
474 schoenebeck 2538 comboIndex = x;
475 schoenebeck 1225 break;
476     }
477 schoenebeck 2538 x++;
478 schoenebeck 1225 }
479     }
480     break;
481 schoenebeck 2538 }
482 schoenebeck 1225 default:
483 schoenebeck 2538 comboIndex = -1;
484 schoenebeck 1225 break;
485     }
486 schoenebeck 2538 combobox.set_active(comboIndex);
487 schoenebeck 1225 }
488    
489    
490     BoolEntry::BoolEntry(const char* labelText) :
491     LabelWidget(labelText, checkbutton),
492 persson 1460 checkbutton(labelText)
493 schoenebeck 1225 {
494 persson 1460 checkbutton.signal_toggled().connect(sig_changed.make_slot());
495 schoenebeck 1225 }
496    
497    
498     StringEntry::StringEntry(const char* labelText) :
499     LabelWidget(labelText, entry)
500     {
501 persson 1582 entry.signal_changed().connect(sig_changed.make_slot());
502 schoenebeck 1225 }
503    
504 persson 2446 gig::String StringEntry::get_value() const
505     {
506     return gig_from_utf8(entry.get_text());
507     }
508    
509     void StringEntry::set_value(const gig::String& value) {
510     entry.set_text(gig_to_utf8(value));
511     }
512    
513    
514 persson 1582 StringEntryMultiLine::StringEntryMultiLine(const char* labelText) :
515     LabelWidget(labelText, frame)
516 schoenebeck 1225 {
517 persson 1582 text_buffer = text_view.get_buffer();
518     frame.set_shadow_type(Gtk::SHADOW_IN);
519     frame.add(text_view);
520     text_buffer->signal_changed().connect(sig_changed.make_slot());
521 schoenebeck 1225 }
522    
523 persson 1582 gig::String StringEntryMultiLine::get_value() const
524 schoenebeck 1225 {
525 persson 1582 Glib::ustring value = text_buffer->get_text();
526     for (int i = 0 ; (i = value.find("\x0a", i)) >= 0 ; i += 2)
527     value.replace(i, 1, "\x0d\x0a");
528 persson 2446 return gig_from_utf8(value);
529 schoenebeck 1225 }
530 persson 1582
531 persson 2446 void StringEntryMultiLine::set_value(const gig::String& value)
532 persson 1582 {
533 persson 2446 Glib::ustring text = gig_to_utf8(value);
534     for (int i = 0 ; (i = text.find("\x0d\x0a", i, 2)) >= 0 ; i++)
535     text.replace(i, 2, "\x0a");
536     text_buffer->set_text(text);
537 persson 1582 }
538 persson 2423
539    
540 schoenebeck 3364 Table::Table(int x, int y) :
541     #if USE_GTKMM_GRID
542     Gtk::Grid(),
543     cols(x),
544     #else
545     Gtk::Table(x, y),
546     #endif
547     rowno(0)
548     {
549     }
550 persson 2423
551     void Table::add(BoolEntry& boolentry)
552     {
553 schoenebeck 3364 #if USE_GTKMM_GRID
554     attach(boolentry.widget, 0, rowno, 2);
555     #else
556 persson 2423 attach(boolentry.widget, 0, 2, rowno, rowno + 1,
557     Gtk::FILL, Gtk::SHRINK);
558 schoenebeck 3364 #endif
559 persson 2423 rowno++;
560     }
561    
562     void Table::add(BoolEntryPlus6& boolentry)
563     {
564 schoenebeck 3364 #if USE_GTKMM_GRID
565     attach(boolentry.widget, 0, rowno, 2);
566     #else
567 persson 2423 attach(boolentry.widget, 0, 2, rowno, rowno + 1,
568     Gtk::FILL, Gtk::SHRINK);
569 schoenebeck 3364 #endif
570 persson 2423 rowno++;
571     }
572    
573     void Table::add(LabelWidget& prop)
574     {
575 schoenebeck 3364 #if USE_GTKMM_GRID
576     attach(prop.label, 1, rowno);
577     attach(prop.widget, 2, rowno);
578     #else
579 persson 2423 attach(prop.label, 1, 2, rowno, rowno + 1,
580     Gtk::FILL, Gtk::SHRINK);
581     attach(prop.widget, 2, 3, rowno, rowno + 1,
582     Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
583 schoenebeck 3364 #endif
584 persson 2423 rowno++;
585     }

  ViewVC Help
Powered by ViewVC