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"));
54 dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_pick"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::pick_clicked));
55 dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_insert"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::insert_clicked));
56 dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_delete"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::delete_clicked));
57 dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_apply"))->signal_clicked.connect(sigc::mem_fun(this, &TimetablePanel::apply_clicked));
59 timetable = train.get_ai_of_type<Timetable>();
61 timetable = new Timetable(train);
63 unsigned length = timetable->get_length();
64 for(unsigned i=0; i<length; ++i)
65 rows.append(&timetable->get_row(i));
67 timetable->signal_row_added.connect(sigc::mem_fun(this, &TimetablePanel::row_added));
68 timetable->signal_row_modified.connect(sigc::mem_fun(this, &TimetablePanel::row_modified));
69 timetable->signal_row_removed.connect(sigc::mem_fun(this, &TimetablePanel::row_removed));
72 void TimetablePanel::row_added(unsigned i, const Timetable::Row &row)
77 void TimetablePanel::row_modified(unsigned i, const Timetable::Row &)
82 void TimetablePanel::row_removed(unsigned i)
87 Timetable::Row TimetablePanel::create_row()
91 row.type = static_cast<Timetable::RowType>(drp_type->get_selected_index()+1);
94 Regex r_time("([01]?[0-9]|2[0-3]):([0-5][0-9])(:([0-5][0-9]))?");
95 RegMatch m = r_time.match(ent_time->get_text());
98 row.time = lexical_cast<unsigned>(m[1].str)*Time::hour;
99 row.time += lexical_cast<unsigned>(m[2].str)*Time::min;
101 row.time += lexical_cast<unsigned>(m[4].str)*Time::sec;
107 void TimetablePanel::row_selected(unsigned i)
109 const Timetable::Row *row = rows.get(i);
112 drp_type->set_selected_index(row->type-1);
114 lbl_target->set_text(row->target->get_name());
115 ent_time->set_text(format_time(row->time));
119 void TimetablePanel::pick_clicked()
124 signal_grab_pointer.emit();
127 void TimetablePanel::insert_clicked()
129 int index = lst_timetable->get_selected_index();
131 index = timetable->get_length();
132 timetable->insert_row(index, create_row());
135 void TimetablePanel::delete_clicked()
137 int index = lst_timetable->get_selected_index();
139 timetable->remove_row(index);
142 void TimetablePanel::apply_clicked()
144 int index = lst_timetable->get_selected_index();
146 timetable->modify_row(index, create_row());
149 void TimetablePanel::key_press(unsigned key, unsigned mod)
151 Panel::key_press(key, mod);
153 if(key==Input::KEY_SHIFT_R || key==Input::KEY_SHIFT_L)
157 void TimetablePanel::key_release(unsigned key, unsigned mod)
159 Panel::key_release(key, mod);
161 if(key==Input::KEY_SHIFT_R || key==Input::KEY_SHIFT_L)
165 void TimetablePanel::button_press(int x, int y, unsigned btn)
167 Panel::button_press(x, y, btn);
171 signal_ungrab_pointer.emit();
174 delete pick_highlight;
177 if(picked_target && btn==1)
179 target = picked_target;
180 lbl_target->set_text(target->get_name());
185 void TimetablePanel::pointer_motion(int x, int y)
187 Panel::pointer_motion(x, y);
193 map_coords_to_ancestor(rx, ry, *find_ancestor<GLtk::Root>());
194 Ray ray = engineer.get_main_view().create_ray(rx, ry);
195 Track *track = engineer.get_layout().pick<Track>(ray);
201 const set<Zone *> &zones = engineer.get_layout().get_all<Zone>();
202 for(set<Zone *>::const_iterator i=zones.begin(); (!t && i!=zones.end()); ++i)
203 if((*i)->has_track(*track))
208 t = &track->get_block();
213 delete pick_highlight;
214 pick_highlight = new TrackChain3D(engineer.get_layout_3d(), *picked_target);
221 TimetableRowItem::TimetableRowItem(ValueType row)
225 add(*new GLtk::Label(format_time(row->time)));
231 case Timetable::ARRIVE: type = "Arrive at "; break;
232 case Timetable::DEPART: type = "Depart from "; break;
233 case Timetable::THROUGH: type = "Go through "; break;
235 add(*new GLtk::Label(type+row->target->get_name()));
238 add(*new GLtk::Label);
242 add(*new GLtk::Label("--:--:--"));
243 add(*new GLtk::Label("End of timetable"));