source: tags/ms_r17q2/WINDOW/AW_select.cxx

Last change on this file was 15781, checked in by westram, 7 years ago
File size: 23.1 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : AW_select.cxx                                      //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in February 2010   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#include "aw_select.hxx"
13#include "aw_window_Xm.hxx"
14#include "aw_root.hxx"
15#include "aw_awar.hxx"
16
17#include <arb_strarray.h>
18#include <arb_strbuf.h>
19#include <arb_str.h>
20#include <arb_sort.h>
21#include <ad_cb.h>
22
23#include <Xm/List.h>
24
25// @@@ rename type_mismatch and other derivates (should make clear that program terminates!)
26__ATTR__NORETURN inline void TERMINATE_selection_type_mismatch(const char *triedType) { type_mismatch(triedType, "selection-list"); }
27
28// --------------------------
29//      AW_selection_list
30
31
32AW_selection_list::AW_selection_list(const char *variable_name_, int variable_type_, Widget select_list_widget_)
33    : variable_name(nulldup(variable_name_)),
34      variable_type(AW_VARIABLE_TYPE(variable_type_)),
35      update_cb(NULL),
36      cl_update(0),
37      select_list_widget(select_list_widget_),
38      list_table(NULL),
39      last_of_list_table(NULL),
40      default_select(NULL),
41      next(NULL)
42{}
43
44AW_selection_list::~AW_selection_list() {
45    clear();
46    free(variable_name);
47}
48
49inline XmString XmStringCreateSimple_wrapper(const char *text) {
50    return XmStringCreateSimple((char*)text);
51}
52
53void AW_selection_list::update() {
54    // Warning:
55    // update() will not set the connected awar to the default value
56    // if it contains a value which is not associated with a list entry!
57
58    size_t count = size();
59    if (default_select) count++;
60
61    XmString *strtab = new XmString[count];
62
63    count = 0;
64    for (AW_selection_list_entry *lt = list_table; lt; lt = lt->next) {
65        const char *s2 = lt->get_displayed();
66        if (!s2[0]) s2 = "  ";
67        strtab[count]  = XmStringCreateSimple_wrapper(s2);
68        count++;
69    }
70
71    if (default_select) {
72        const char *s2 = default_select->get_displayed();
73        if (!strlen(s2)) s2 = "  ";
74        strtab[count] = XmStringCreateSimple_wrapper(s2);
75        count++;
76    }
77    if (!count) {
78        strtab[count] = XmStringCreateSimple_wrapper("   ");
79        count ++;
80    }
81
82    XtVaSetValues(select_list_widget, XmNitemCount, count, XmNitems, strtab, NULL);
83
84    refresh();
85
86    for (size_t i=0; i<count; i++) XmStringFree(strtab[i]);
87    delete [] strtab;
88
89    if (update_cb) update_cb(this, cl_update);
90}
91
92void AW_selection_list::set_update_callback(sellist_update_cb ucb, AW_CL cl_user) {
93    aw_assert(!update_cb || !ucb); // overwrite allowed only with NULL!
94
95    update_cb = ucb;
96    cl_update = cl_user;
97}
98
99void AW_selection_list::refresh() {
100    if (!variable_name) return;     // not connected to awar
101
102    AW_root *root  = AW_root::SINGLETON;
103    bool     found = false;
104    int      pos   = 0;
105    AW_awar *awar  = root->awar(variable_name);
106
107    AW_selection_list_entry *lt;
108
109    switch (variable_type) {
110        case AW_STRING: {
111            char *var_value = awar->read_string();
112            for (lt = list_table; lt; lt = lt->next) {
113                if (strcmp(var_value, lt->get_value().get_string()) == 0) {
114                    found = true;
115                    break;
116                }
117                pos++;
118            }
119            free(var_value);
120            break;
121        }
122        case AW_INT: {
123            int var_value = awar->read_int();
124            for (lt = list_table; lt; lt = lt->next) {
125                if (var_value == lt->get_value().get_int()) {
126                    found = true;
127                    break;
128                }
129                pos++;
130            }
131            break;
132        }
133        case AW_FLOAT: {
134            float var_value = awar->read_float();
135            for (lt = list_table; lt; lt = lt->next) {
136                if (var_value == lt->get_value().get_float()) {
137                    found = true;
138                    break;
139                }
140                pos++;
141            }
142            break;
143        }
144        case AW_POINTER: {
145            GBDATA *var_value = awar->read_pointer();
146            for (lt = list_table; lt; lt = lt->next) {
147                if (var_value == lt->get_value().get_pointer()) {
148                    found = true;
149                    break;
150                }
151                pos++;
152            }
153            break;
154        }
155        default:
156            aw_assert(0);
157            GB_warning("Unknown AWAR type");
158            break;
159    }
160
161    if (found || default_select) {
162        pos++;
163        int top;
164        int vis;
165        XtVaGetValues(select_list_widget,
166                      XmNvisibleItemCount, &vis,
167                      XmNtopItemPosition, &top,
168                      NULL);
169        XmListSelectPos(select_list_widget, pos, False);
170
171        if (pos < top) {
172            if (pos > 1) pos --;
173            XmListSetPos(select_list_widget, pos);
174        }
175        if (pos >= top + vis) {
176            XmListSetBottomPos(select_list_widget, pos + 1);
177        }
178    }
179    else {
180        GBK_terminatef("Selection list '%s' has no default selection", variable_name);
181    }
182}
183
184void AW_selection::refresh() {
185    get_sellist()->clear();
186    fill();
187    get_sellist()->update();
188}
189
190void AW_selection_list::clear() {
191    /** Remove all items from the list. Default item is removed as well.*/
192    while (list_table) {
193        AW_selection_list_entry *nextEntry = list_table->next;
194        delete list_table;
195        list_table = nextEntry;
196    }
197    list_table         = NULL;
198    last_of_list_table = NULL;
199
200    delete_default();
201}
202
203bool AW_selection_list::default_is_selected() const {
204    const AW_scalar *sel = get_selected_value();
205    if (!sel) { // (case should be impossible in gtk port)
206        return true; // handle "nothing" like default
207    }
208    const AW_scalar *def = get_default_value();
209    return def && sel == def;
210}
211
212const AW_scalar *AW_selection_list::get_selected_value() const {
213    int                      i;
214    AW_selection_list_entry *lt;
215    AW_selection_list_entry *found = 0;
216
217    aw_assert(select_list_widget);
218
219    // code below retrieves index of selected
220    // get_index_of_selected() does sth similar, but uses awar-value
221    // @@@ rethink
222
223    for (i=1, lt = list_table; lt; i++, lt = lt->next) {
224        bool is_selected = XmListPosSelected(select_list_widget, i);
225        if (is_selected && !found) found = lt;
226    }
227
228    if (default_select) {
229        bool is_selected = XmListPosSelected(select_list_widget, i);
230        if (is_selected && !found) found = default_select;
231    }
232    return found ? &found->get_value() : NULL;
233}
234
235
236AW_selection_list_entry *AW_selection_list::get_entry_at(int index) const {
237    AW_selection_list_entry *entry = list_table;
238    while (index && entry) {
239        entry = entry->next;
240        index--;
241    }
242    return entry;
243}
244
245
246void AW_selection_list::select_default() {
247    set_awar_value(*get_default_value());
248}
249
250void AW_selection_list::delete_element_at(const int index) {
251    if (index<0) return;
252
253    AW_selection_list_entry *prev = NULL;
254    if (index>0) {
255        prev = get_entry_at(index-1);
256        if (!prev) return; // invalid index
257    }
258
259    int selected_index = get_index_of_selected();
260    if (index == selected_index) select_default();
261
262    AW_selection_list_entry *toDel = prev ? prev->next : list_table;
263    aw_assert(toDel != default_select);
264
265    (prev ? prev->next : list_table) = toDel->next;
266    delete toDel;
267
268    if (last_of_list_table == toDel) last_of_list_table = prev;
269}
270
271void AW_selection_list::delete_value(const AW_scalar& value) {
272    int index = get_index_of(value);
273    delete_element_at(index);
274}
275
276AW_scalar AW_selection_list::get_awar_value() const {
277    AW_awar *awar = AW_root::SINGLETON->awar(variable_name);
278    return AW_scalar(awar);
279}
280
281
282char *AW_selection_list::get_content_as_string(long number_of_lines) {
283    // number_of_lines == 0 -> print all
284
285    AW_selection_list_entry *lt;
286    GBS_strstruct *fd = GBS_stropen(10000);
287
288    for (lt = list_table; lt; lt = lt->next) {
289        number_of_lines--;
290        GBS_strcat(fd, lt->get_displayed());
291        GBS_chrcat(fd, '\n');
292        if (!number_of_lines) break;
293    }
294    return GBS_strclose(fd);
295}
296
297const char *AW_selection_list::get_default_display() const {
298    return default_select ? default_select->get_displayed() : NULL;
299}
300const AW_scalar *AW_selection_list::get_default_value() const {
301    return default_select ? &default_select->get_value() : NULL;
302}
303
304
305int AW_selection_list::get_index_of(const AW_scalar& searched_value) {
306    /*! get index of an entry in the selection list
307     * @return 0..n-1 index of matching element (or -1)
308     */
309
310    int element_index = 0;
311    for (AW_selection_list_iterator entry(this); entry; ++entry) {
312        if (*entry.get_value() == searched_value) return element_index;
313        ++element_index;
314    }
315    return -1;
316}
317
318int AW_selection_list::get_index_of_selected() {
319    // returns index of element (or -1)
320    AW_scalar awar_value = get_awar_value();
321    return get_index_of(awar_value);
322}
323
324void AW_selection_list::init_from_array(const CharPtrArray& entries, const char *default_displayed, const char *default_value) {
325    // update selection list with contents of NULL-terminated array 'entries'
326    //
327    // 'default_displayed' and 'default_value' are used as default selection.
328    // To position the default selection, add 'default_value' to 'entries' as well.
329    //
330    // awar value will be changed to 'defaultEntry' if it does not match any other entry
331    //
332    // Note: This works only with selection lists bound to AW_STRING awars.
333
334    aw_assert(default_displayed);
335    aw_assert(default_value);
336
337    // use copies (just in case default_* points to a value free'd by clear())
338    char *defaultDispCopy  = strdup(default_displayed);
339    char *defaultValueCopy = strdup(default_value);
340
341    bool defInserted = false;
342
343    clear();
344    for (int i = 0; entries[i]; ++i) {
345        if (!defInserted && strcmp(entries[i], defaultValueCopy) == 0) {
346            insert_default(defaultDispCopy, defaultValueCopy);
347            defInserted = true;
348        }
349        else {
350            insert(entries[i], entries[i]);
351        }
352    }
353    if (!defInserted) insert_default(defaultDispCopy, defaultValueCopy);
354    update();
355
356    const AW_scalar *selected = get_selected_value();
357    if (selected) set_awar_value(*selected);
358
359    free(defaultValueCopy);
360    free(defaultDispCopy);
361}
362
363void AW_selection_list::append_entry(AW_selection_list_entry *new_entry) {
364    if (list_table) {
365        last_of_list_table->next = new_entry;
366        last_of_list_table = last_of_list_table->next;
367        last_of_list_table->next = NULL;
368    }
369    else {
370        last_of_list_table = list_table = new_entry;
371    }
372}
373
374void AW_selection_list::delete_default() {
375    /** Removes the default entry from the list*/
376    if (default_select) {
377        delete default_select;
378        default_select = NULL;
379    }
380}
381
382void AW_selection_list::insert(const char *displayed, const AW_scalar& value) {
383    if (!value.matches_variable_type(variable_type)) TERMINATE_selection_type_mismatch(value.get_type_name());
384    append_entry(new AW_selection_list_entry(displayed, value));
385}
386
387void AW_selection_list::insert_default(const char *displayed, const AW_scalar& value) {
388    if (!value.matches_variable_type(variable_type)) TERMINATE_selection_type_mismatch(value.get_type_name());
389    if (default_select) delete_default();
390    default_select = new AW_selection_list_entry(displayed, value);
391}
392
393void AW_selection_list::move_content_to(AW_selection_list *target_list) {
394    //! move all entries (despite default entry) to another AW_selection_list
395
396    if (default_select) {
397        char *defDisp = strdup(default_select->get_displayed());
398        char *defVal  = strdup(default_select->get_value().get_string());
399
400        delete_default();
401        move_content_to(target_list);
402        insert_default(defDisp, defVal);
403
404        free(defVal);
405        free(defDisp);
406    }
407    else {
408        AW_selection_list_entry *entry = list_table;
409        while (entry) {
410            target_list->append_entry(new AW_selection_list_entry(entry->get_displayed(), entry->get_value()));
411            entry = entry->next;
412        }
413        clear();
414    }
415}
416
417void AW_selection_list::move_selection(int offset) {
418    /*! move selection 'offset' position
419     *  offset == 1  -> select next element
420     *  offset == -1 -> select previous element
421     */
422
423    int index = get_index_of_selected();
424    select_element_at(index+offset);
425}
426
427const AW_scalar *AW_selection_list::get_value_at(int index) {
428    // get value of the entry at position 'index' [0..n-1] of the 'selection_list'
429    // returns NULL if index is out of bounds
430
431    AW_selection_list_entry *entry = get_entry_at(index);
432    return entry ? &entry->get_value() : NULL;
433}
434
435void AW_selection_list::select_element_at(int wanted_index) {
436    const AW_scalar *wanted_value = get_value_at(wanted_index);
437
438    if (!wanted_value) {
439        wanted_value = get_default_value();
440        aw_assert(wanted_value); // did set string-awar to "" in the past // @@@ what todo here? maybe just dont select?
441    }
442
443    if (wanted_value) set_awar_value(*wanted_value);
444}
445
446void AW_selection_list::set_awar_value(const AW_scalar& new_value) {
447    AW_awar *awar = AW_root::SINGLETON->awar(variable_name);
448    new_value.write_to(awar);
449}
450
451
452void AW_selection_list::set_file_suffix(const char *suffix) {
453    AW_root *aw_root = AW_root::SINGLETON;
454    char     filter[200];
455    sprintf(filter, "tmp/save_box_sel_%li/filter", (long)this);
456    aw_root->awar_string(filter, suffix);
457    sprintf(filter, "tmp/load_box_sel_%li/filter", (long)this);
458    aw_root->awar_string(filter, suffix);
459}
460
461size_t AW_selection_list::size() {
462    AW_selection_list_entry *lt    = list_table;
463    size_t                  count = 0;
464
465    while (lt) {
466        ++count;
467        lt = lt->next;
468    }
469    return count;
470}
471
472static int sel_sort_backward(const char *d1, const char *d2) { return strcmp(d2, d1); }
473static int sel_isort_backward(const char *d1, const char *d2) { return ARB_stricmp(d2, d1); }
474static int gb_compare_function__2__sellist_cmp_fun(const void *t1, const void *t2, void *v_selcmp) {
475    sellist_cmp_fun selcmp = (sellist_cmp_fun)v_selcmp;
476    return selcmp(static_cast<const AW_selection_list_entry*>(t1)->get_displayed(),
477                  static_cast<const AW_selection_list_entry*>(t2)->get_displayed());
478}
479
480void AW_selection_list::sortCustom(sellist_cmp_fun cmp) {
481    // WARNING: function behaves different in motif and gtk:
482    // gtk also sorts default-element, motif always places default-element @ bottom
483    size_t count = size();
484    if (count) {
485        AW_selection_list_entry **tables = new AW_selection_list_entry *[count];
486        count = 0;
487        for (AW_selection_list_entry *lt = list_table; lt; lt = lt->next) {
488            tables[count++] = lt;
489        }
490
491        GB_sort((void**)tables, 0, count, gb_compare_function__2__sellist_cmp_fun, (void*)cmp);
492
493        size_t i;
494        for (i=0; i<count-1; i++) {
495            tables[i]->next = tables[i+1];
496        }
497        tables[i]->next = 0;
498        list_table = tables[0];
499        last_of_list_table = tables[i];
500
501        delete [] tables;
502    }
503}
504
505void AW_selection_list::sort(bool backward, bool case_sensitive) {
506    // WARNING: function behaves different in motif and gtk:
507    // gtk also sorts default-element, motif always places default-element @ bottom
508    sellist_cmp_fun cmp;
509    if (backward) {
510        if (case_sensitive) cmp = sel_sort_backward;
511        else cmp                = sel_isort_backward;
512    }
513    else {
514        if (case_sensitive) cmp = strcmp;
515        else cmp                = ARB_stricmp;
516    }
517    sortCustom(cmp);
518}
519
520void AW_selection_list::to_array(StrArray& array, bool values) {
521    /*! read contents of selection list into an array.
522     * @param values true->read values, false->read displayed strings
523     * Use GBT_free_names() to free the result.
524     *
525     * Note: if 'values' is true, this function only works for string selection lists!
526     */
527
528    array.reserve(size());
529
530    for (AW_selection_list_entry *lt = list_table; lt; lt = lt->next) {
531        array.put(strdup(values ? lt->get_value().get_string() : lt->get_displayed()));
532    }
533    aw_assert(array.size() == size());
534}
535
536GB_HASH *AW_selection_list::to_hash(bool case_sens) {
537    // creates a hash (key = value of selection list, value = display string from selection list)
538    // (Warning: changing the selection list will render the hash invalid!)
539
540    GB_HASH *hash = GBS_create_hash(size(), case_sens ? GB_MIND_CASE : GB_IGNORE_CASE);
541
542    for (AW_selection_list_entry *lt = list_table; lt; lt = lt->next) {
543        GBS_write_hash(hash, lt->get_value().get_string(), (long)lt->get_displayed());
544    }
545
546    return hash;
547}
548
549char *AW_selection_list_entry::copy_string_for_display(const char *str) {
550    size_t  len     = strlen(str);
551    bool    tooLong = len>MAX_DISPLAY_LENGTH;
552    char   *out;
553    if (tooLong) {
554        out = ARB_strndup(str, MAX_DISPLAY_LENGTH);
555        { // add message about truncation
556            char   *truncated = GBS_global_string_copy(" <truncated - original contains %zu byte>", len);
557            size_t  tlen      = strlen(truncated);
558            aw_assert(MAX_DISPLAY_LENGTH>tlen);
559            memcpy(out+MAX_DISPLAY_LENGTH-tlen, truncated, tlen);
560        }
561        len = MAX_DISPLAY_LENGTH;
562    }
563    else {
564        out = ARB_strduplen(str, len);
565    }
566
567    for (size_t i = 0; i<len; ++i) {
568        switch (out[i]) {
569            case ',':   out[i] = ';'; break;
570            case '\n':  out[i] = '#'; break;
571        }
572    }
573    return out;
574}
575
576// -------------------------
577//      AW_DB_selection
578
579static void AW_DB_selection_refresh_cb(GBDATA *, AW_DB_selection *selection) {
580    selection->refresh();
581}
582
583AW_DB_selection::AW_DB_selection(AW_selection_list *sellist_, GBDATA *gbd_)
584    : AW_selection(sellist_)
585    , gbd(gbd_)
586{
587    GB_transaction ta(gbd);
588    GB_add_callback(gbd, GB_CB_CHANGED, makeDatabaseCallback(AW_DB_selection_refresh_cb, this));
589}
590
591AW_DB_selection::~AW_DB_selection() {
592    GB_transaction ta(gbd);
593    GB_remove_callback(gbd, GB_CB_CHANGED, makeDatabaseCallback(AW_DB_selection_refresh_cb, this));
594}
595
596GBDATA *AW_DB_selection::get_gb_main() {
597    return GB_get_root(gbd);
598}
599
600// --------------------------------------------------------------------------------
601
602#ifdef UNIT_TESTS
603#ifndef TEST_UNIT_H
604#include <test_unit.h>
605#endif
606
607#define TEST_LIST_CONTENT(list,values,expected) do {    \
608        StrArray a;                                     \
609        (list).to_array(a, values);                     \
610        char *str = GBT_join_strings(a, ';');           \
611        TEST_EXPECT_EQUAL(str, expected);               \
612        free(str);                                      \
613    } while(0)
614
615#define TEST_GET_LIST_CONTENT(list,expected) do {       \
616        char *str = (list).get_content_as_string(10);   \
617        TEST_EXPECT_EQUAL(str, expected);               \
618        free(str);                                      \
619    } while(0)
620
621void TEST_selection_list_access() {
622#if defined(ARB_GTK)
623    AW_selection_list list0(NULL, false);
624    AW_selection_list list1(NULL, false);
625    AW_selection_list list2(NULL, false);
626#else // ARB_MOTIF
627    AW_selection_list list0("bla", GB_STRING, NULL);
628    AW_selection_list list1("bla", GB_STRING, NULL);
629    AW_selection_list list2("alb", GB_STRING, NULL);
630#endif
631
632    AW_scalar s1st("1st");
633    AW_scalar s2nd("2nd");
634    AW_scalar s3rd("3rd");
635    AW_scalar sempty("");
636
637    list0.insert_default("First",  s1st);
638    list0.insert        ("Second", s2nd);
639    list0.insert        ("Third",  s3rd);
640
641    list1.insert        ("First",  "1st");
642    list1.insert_default("Second", "2nd");
643    list1.insert        ("Third",  "3rd");
644
645    list2.insert        ("First",   s1st);
646    list2.insert        ("Second",  s2nd);
647    list2.insert        ("Third",   s3rd);
648    list2.insert_default("Default", sempty);
649
650    TEST_EXPECT_EQUAL(list0.size(), 2);
651    TEST_EXPECT_EQUAL(list1.size(), 2);
652    TEST_EXPECT_EQUAL(list2.size(), 3);
653
654    TEST_EXPECT_EQUAL(list1.get_default_value()->get_string(), "2nd");
655    TEST_EXPECT_EQUAL(list1.get_default_display(), "Second");
656
657    TEST_EXPECT_EQUAL(list0.get_index_of(s1st), -1); // default value is not indexed
658    TEST_EXPECT_EQUAL(list0.get_index_of(s2nd), 0);
659    TEST_EXPECT_EQUAL(list0.get_index_of(s3rd), 1);  // = second non-default entry
660
661    TEST_EXPECT_EQUAL(list1.get_index_of(s1st), 0);
662    TEST_EXPECT_EQUAL(list1.get_index_of(s2nd), -1); // default value is not indexed
663    TEST_EXPECT_EQUAL(list1.get_index_of(s3rd), 1);  // = second non-default entry
664
665    TEST_EXPECT_EQUAL(list2.get_index_of(s1st), 0);
666    TEST_EXPECT_EQUAL(list2.get_index_of(s2nd), 1);
667    TEST_EXPECT_EQUAL(list2.get_index_of(s3rd), 2);
668
669    TEST_EXPECT(*list0.get_value_at(0) == s2nd);
670    TEST_EXPECT(*list0.get_value_at(1) == s3rd);
671    TEST_EXPECT_NULL(list0.get_value_at(2));
672
673    TEST_EXPECT(*list1.get_value_at(0) == s1st);
674    TEST_EXPECT(*list1.get_value_at(1) == s3rd);
675    TEST_EXPECT_NULL(list1.get_value_at(2));
676
677    TEST_EXPECT(*list2.get_value_at(0) == s1st);
678    TEST_EXPECT(*list2.get_value_at(1) == s2nd);
679    TEST_EXPECT(*list2.get_value_at(2) == s3rd);
680    TEST_EXPECT_NULL(list2.get_value_at(3));
681
682    TEST_LIST_CONTENT(list1, true,  "1st;3rd");
683    TEST_LIST_CONTENT(list1, false, "First;Third");
684    TEST_GET_LIST_CONTENT(list1,    "First\nThird\n");
685
686    TEST_LIST_CONTENT(list2, true,  "1st;2nd;3rd");
687    TEST_LIST_CONTENT(list2, false, "First;Second;Third");
688    TEST_GET_LIST_CONTENT(list2,    "First\nSecond\nThird\n");
689
690    {
691        AW_selection_list_iterator iter1(&list1);
692        AW_selection_list_iterator iter2(&list2);
693
694        TEST_EXPECT(bool(iter1));
695        TEST_EXPECT(bool(iter2));
696
697        TEST_EXPECT_EQUAL(iter1.get_displayed(), "First");
698        TEST_EXPECT_EQUAL(iter2.get_displayed(), "First");
699
700        TEST_EXPECT(*iter1.get_value() == s1st);
701        TEST_EXPECT(*iter2.get_value() == s1st);
702
703        ++iter1;
704        ++iter2;
705
706        TEST_EXPECT(bool(iter1));
707        TEST_EXPECT(bool(iter2));
708
709        TEST_EXPECT_EQUAL(iter1.get_displayed(), "Third");
710        TEST_EXPECT_EQUAL(iter2.get_displayed(), "Second");
711
712        TEST_EXPECT(*iter1.get_value() == s3rd);
713        TEST_EXPECT(*iter2.get_value() == s2nd);
714
715        ++iter1;
716        ++iter2;
717
718        TEST_REJECT(bool(iter1));
719        TEST_EXPECT(bool(iter2));
720    }
721
722    {
723#if defined(ARB_GTK)
724        AW_selection_list copy1(NULL, false);
725        AW_selection_list copy2(NULL, false);
726#else // ARB_MOTIF
727        AW_selection_list copy1("c1", GB_STRING, NULL);
728        AW_selection_list copy2("c2", GB_STRING, NULL);
729#endif
730
731        list1.move_content_to(&copy1);
732        list2.move_content_to(&copy2);
733
734        TEST_EXPECT_EQUAL(list1.size(), 0);
735        TEST_EXPECT_EQUAL(list2.size(), 0);
736
737        TEST_LIST_CONTENT(copy1, true, "1st;3rd");
738        TEST_LIST_CONTENT(copy2, true, "1st;2nd;3rd");
739    }
740}
741TEST_PUBLISH(TEST_selection_list_access);
742
743#endif // UNIT_TESTS
744
745// --------------------------------------------------------------------------------
746
Note: See TracBrowser for help on using the repository browser.