]> git.tdb.fi Git - r2c2.git/blob - source/engineer/trainlistdialog.cpp
Persist most dialogs across runs
[r2c2.git] / source / engineer / trainlistdialog.cpp
1 #include <msp/core/maputils.h>
2 #include <msp/gltk/button.h>
3 #include <msp/gltk/style.h>
4 #include "engineer.h"
5 #include "libr2c2/train.h"
6 #include "newtraindialog.h"
7 #include "traindialog.h"
8 #include "trainlistdialog.h"
9
10 using namespace std;
11 using namespace Msp;
12 using namespace R2C2;
13
14 class TrainItem: public GLtk::List::MultiColumnItem
15 {
16 public:
17         typedef R2C2::Train *ValueType;
18
19         TrainItem(ValueType);
20 };
21
22
23 class DetectedLocoItem: public GLtk::List::MultiColumnItem
24 {
25 public:
26         typedef const Driver::DetectedLocomotive *ValueType;
27
28         DetectedLocoItem(ValueType);
29 };
30
31
32 TrainListDialog::TrainListDialog(Engineer &e):
33         DynamicDialog(e.get_user_interface()),
34         engineer(e),
35         layout(engineer.get_layout())
36 {
37         Loader::WidgetMap widgets;
38         DataFile::load(*this, "data/trainlistdialog.ui", widgets);
39
40         lst_trains = dynamic_cast<GLtk::List *>(get_item(widgets, "lst_trains"));
41         lst_trains->set_data(trains);
42         lst_trains->set_item_type<TrainItem>();
43
44         lst_imported = dynamic_cast<GLtk::List *>(get_item(widgets, "lst_imported"));
45         lst_imported->set_data(detected_locos);
46         lst_imported->set_item_type<DetectedLocoItem>();
47
48         dynamic_cast<GLtk::Toggle *>(get_item(widgets, "tgl_trains"))->signal_toggled.connect(sigc::bind(sigc::mem_fun(this, &TrainListDialog::tab_toggled), lst_trains));
49         dynamic_cast<GLtk::Toggle *>(get_item(widgets, "tgl_import"))->signal_toggled.connect(sigc::bind(sigc::mem_fun(this, &TrainListDialog::tab_toggled), lst_imported));
50
51         dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_new"))->signal_clicked.connect(sigc::mem_fun(this, &TrainListDialog::new_clicked));
52         dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_show"))->signal_clicked.connect(sigc::mem_fun(this, &TrainListDialog::show_clicked));
53
54         const map<unsigned, Train *> &ltrains = layout.get_trains();
55         for(map<unsigned, Train *>::const_iterator i=ltrains.begin(); i!=ltrains.end(); ++i)
56         {
57                 trains.append(i->second);
58                 i->second->signal_name_changed.connect(sigc::hide(sigc::bind(sigc::mem_fun(this, &TrainListDialog::train_name_changed), sigc::ref(*i->second))));
59         }
60
61         if(layout.has_driver())
62         {
63                 Driver &driver = layout.get_driver();
64                 driver.signal_locomotive_detected.connect(sigc::mem_fun(this, &TrainListDialog::locomotive_detected));
65                 driver.signal_locomotive_gone.connect(sigc::mem_fun(this, &TrainListDialog::locomotive_gone));
66
67                 unsigned i = 0;
68                 while(const Driver::DetectedLocomotive *loco = driver.enumerate_detected_locos(i++))
69                         detected_locos.append(loco);
70         }
71         layout.signal_train_added.connect(sigc::mem_fun(this, &TrainListDialog::train_added));
72         layout.signal_train_removed.connect(sigc::mem_fun(this, &TrainListDialog::train_removed));
73 }
74
75 void TrainListDialog::new_clicked()
76 {
77         NewTrainDialog *dlg = new NewTrainDialog(engineer);
78         if(lst_imported->is_visible())
79         {
80                 int selected = lst_imported->get_selected_index();
81                 if(selected>=0)
82                         dlg->prefill(*detected_locos.get(selected));
83         }
84         find_ancestor<GLtk::Root>()->add(*dlg);
85         dlg->autosize();
86 }
87
88 void TrainListDialog::show_clicked()
89 {
90         int index = lst_trains->get_selected_index();
91         if(index>=0)
92         {
93                 TrainDialog *dlg = new TrainDialog(engineer, *trains.get(index));
94                 find_ancestor<GLtk::Root>()->add(*dlg);
95         }
96 }
97
98 void TrainListDialog::tab_toggled(bool value, GLtk::Widget *wdg)
99 {
100         wdg->set_visible(value);
101 }
102
103 void TrainListDialog::locomotive_detected(const Driver::DetectedLocomotive &loco)
104 {
105         detected_locos.append(&loco);
106 }
107
108 void TrainListDialog::locomotive_gone(const Driver::DetectedLocomotive &loco)
109 {
110         int index = detected_locos.find(&loco);
111         if(index>=0)
112                 detected_locos.remove(index);
113 }
114
115 void TrainListDialog::train_added(Train &train)
116 {
117         unsigned n_items = trains.size();
118         unsigned i;
119         for(i=0; i<n_items; ++i)
120                 if(trains.get(i)->get_address()>train.get_address())
121                         break;
122         trains.insert(i, &train);
123
124         train.signal_name_changed.connect(sigc::hide(sigc::bind(sigc::mem_fun(this, &TrainListDialog::train_name_changed), sigc::ref(train))));
125 }
126
127 void TrainListDialog::train_removed(Train &train)
128 {
129         int i = trains.find(&train);
130         if(i>=0)
131                 trains.remove(i);
132 }
133
134 void TrainListDialog::train_name_changed(Train &train)
135 {
136         trains.refresh(&train);
137 }
138
139 bool TrainListDialog::save_state(DataFile::Statement &st) const
140 {
141         st.keyword = "trainlistdialog";
142         save_position(st.sub);
143
144         return true;
145 }
146
147
148 TrainItem::TrainItem(ValueType train)
149 {
150         add(*new GLtk::Label(train->get_protocol()));
151         add(*new GLtk::Label(lexical_cast<string>(train->get_address())));
152         add(*new GLtk::Label(train->get_name()));
153 }
154
155
156 DetectedLocoItem::DetectedLocoItem(ValueType loco)
157 {
158         add(*new GLtk::Label(loco->protocol));
159         add(*new GLtk::Label(lexical_cast<string>(loco->address)));
160         add(*new GLtk::Label(loco->name));
161 }