1 #include <msp/core/maputils.h>
2 #include <msp/gltk/button.h>
3 #include <msp/gltk/root.h>
4 #include <msp/input/keys.h>
5 #include <msp/strings/format.h>
6 #include <msp/strings/regex.h>
7 #include "libr2c2/zone.h"
9 #include "timetablepanel.h"
15 class TimetableRowItem: public GLtk::List::MultiColumnItem
18 typedef const Timetable::Row *ValueType;
20 TimetableRowItem(ValueType);
24 string format_time(const Time::TimeDelta &time)
26 unsigned second = time/Time::sec;
27 unsigned hour = second/3600;
28 unsigned minute = second/60%60;
30 return format("%02d:%02d:%02d", hour, minute, second);
34 TimetablePanel::TimetablePanel(Engineer &e, R2C2::Train &t):
42 Loader::WidgetMap widgets;
43 DataFile::load(*this, "data/timetablepanel.ui", widgets);
45 lst_timetable = dynamic_cast<GLtk::List *>(get_item(widgets, "lst_timetable"));
46 lst_timetable->set_data(rows);
47 lst_timetable->set_item_type<TimetableRowItem>();
48 lst_timetable->signal_item_selected.connect(sigc::mem_fun(this, &TimetablePanel::row_selected));
50 drp_type = dynamic_cast<GLtk::Dropdown *>(get_item(widgets, "drp_type"));
51 lbl_target = dynamic_cast<GLtk::Label *>(get_item(widgets, "lbl_target"));
52 ent_time = dynamic_cast<GLtk::Entry *>(get_item(widgets, "ent_time"));
53 drp_direction = dynamic_cast<GLtk::Dropdown *>(get_item(widgets, "drp_direction"));
55 dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_pick"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::pick_clicked));
56 dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_insert"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::insert_clicked));
57 dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_delete"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::delete_clicked));
58 dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_apply"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::apply_clicked));
60 timetable = train.get_ai_of_type<Timetable>();
62 timetable = new Timetable(train);
64 unsigned length = timetable->get_length();
65 for(unsigned i=0; i<length; ++i)
66 rows.append(&timetable->get_row(i));
68 timetable->signal_row_added.connect(sigc::mem_fun(this, &TimetablePanel::row_added));
69 timetable->signal_row_modified.connect(sigc::mem_fun(this, &TimetablePanel::row_modified));
70 timetable->signal_row_removed.connect(sigc::mem_fun(this, &TimetablePanel::row_removed));
73 void TimetablePanel::row_added(unsigned i, const Timetable::Row &row)
78 void TimetablePanel::row_modified(unsigned i, const Timetable::Row &)
83 void TimetablePanel::row_removed(unsigned i)
88 Timetable::Row TimetablePanel::create_row()
92 row.type = static_cast<Timetable::RowType>(drp_type->get_selected_index()+1);
94 row.direction = static_cast<TrackChain::Direction>(drp_direction->get_selected_index());
96 Regex r_time("([01]?[0-9]|2[0-3]):([0-5][0-9])(:([0-5][0-9]))?");
97 RegMatch m = r_time.match(ent_time->get_text());
100 row.time = lexical_cast<unsigned>(m[1].str)*Time::hour;
101 row.time += lexical_cast<unsigned>(m[2].str)*Time::min;
103 row.time += lexical_cast<unsigned>(m[4].str)*Time::sec;
109 void TimetablePanel::row_selected(unsigned i)
111 const Timetable::Row *row = rows.get(i);
114 drp_type->set_selected_index(row->type-1);
115 target = row->target;
117 lbl_target->set_text(target->get_name());
118 drp_direction->set_selected_index(row->direction);
119 ent_time->set_text(format_time(row->time));
123 void TimetablePanel::pick_clicked()
128 signal_grab_pointer.emit();
131 void TimetablePanel::insert_clicked()
133 int index = lst_timetable->get_selected_index();
135 index = timetable->get_length();
136 timetable->insert_row(index, create_row());
139 void TimetablePanel::delete_clicked()
141 int index = lst_timetable->get_selected_index();
143 timetable->remove_row(index);
146 void TimetablePanel::apply_clicked()
148 int index = lst_timetable->get_selected_index();
150 timetable->modify_row(index, create_row());
153 void TimetablePanel::key_press(unsigned key, unsigned mod)
155 Panel::key_press(key, mod);
157 if(key==Input::KEY_SHIFT_R || key==Input::KEY_SHIFT_L)
161 void TimetablePanel::key_release(unsigned key, unsigned mod)
163 Panel::key_release(key, mod);
165 if(key==Input::KEY_SHIFT_R || key==Input::KEY_SHIFT_L)
169 void TimetablePanel::button_press(int x, int y, unsigned btn)
171 Panel::button_press(x, y, btn);
175 signal_ungrab_pointer.emit();
178 delete pick_highlight;
181 if(picked_target && btn==1)
183 target = picked_target;
184 lbl_target->set_text(target->get_name());
189 void TimetablePanel::pointer_motion(int x, int y)
191 Panel::pointer_motion(x, y);
197 map_coords_to_ancestor(rx, ry, *find_ancestor<GLtk::Root>());
198 Ray ray = engineer.get_main_view().create_ray(rx, ry);
199 Track *track = engineer.get_layout().pick<Track>(ray);
205 const set<Zone *> &zones = engineer.get_layout().get_all<Zone>();
206 for(set<Zone *>::const_iterator i=zones.begin(); (!t && i!=zones.end()); ++i)
207 if((*i)->has_track(*track))
212 t = &track->get_block();
217 delete pick_highlight;
218 pick_highlight = new TrackChain3D(engineer.get_layout_3d(), *picked_target);
225 TimetableRowItem::TimetableRowItem(ValueType row)
229 add(*new GLtk::Label(format_time(row->time)));
235 case Timetable::ARRIVE: type = "Arrive at "; break;
236 case Timetable::DEPART: type = "Depart from "; break;
237 case Timetable::THROUGH: type = "Go through "; break;
241 switch(row->direction)
243 case TrackChain::UP: dir = " up"; break;
244 case TrackChain::DOWN: dir = " down"; break;
248 add(*new GLtk::Label(type+row->target->get_name()+dir));
251 add(*new GLtk::Label);
255 add(*new GLtk::Label("--:--:--"));
256 add(*new GLtk::Label("End of timetable"));