]> git.tdb.fi Git - r2c2.git/blob - source/engineer/controlpanel.cpp
Use Widget::find_ancestor to reduce code duplication
[r2c2.git] / source / engineer / controlpanel.cpp
1 #include <msp/core/maputils.h>
2 #include <msp/core/raii.h>
3 #include <msp/gltk/button.h>
4 #include <msp/gltk/label.h>
5 #include <msp/gltk/row.h>
6 #include "libr2c2/vehicle.h"
7 #include "controlpanel.h"
8 #include "engineer.h"
9 #include "placementghost.h"
10 #include "trainview.h"
11
12 using namespace std;
13 using namespace Msp;
14 using namespace R2C2;
15
16 ControlPanel::ControlPanel(Engineer &e, Train &t):
17         engineer(e),
18         train(t),
19         updating(false)
20 {
21         Loader::WidgetMap widgets;
22         DataFile::load(*this, "data/controlpanel.ui", widgets);
23
24         dynamic_cast<GLtk::Label *>(get_item(widgets, "lbl_protocol"))->set_text(train.get_protocol());
25         dynamic_cast<GLtk::Label *>(get_item(widgets, "lbl_address"))->set_text(lexical_cast<string>(train.get_address()));
26
27         dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_place"))->signal_clicked.connect(sigc::mem_fun(this, &ControlPanel::place_clicked));
28         dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_take"))->signal_clicked.connect(sigc::mem_fun(this, &ControlPanel::take_clicked));
29         dynamic_cast<GLtk::Button *>(get_item(widgets, "btn_view"))->signal_clicked.connect(sigc::mem_fun(this, &ControlPanel::view_clicked));
30
31         GLtk::Panel *pnl_functions = dynamic_cast<GLtk::Panel *>(get_item(widgets, "pnl_functions"));
32
33         const VehicleType::FunctionMap &funcs = train.get_vehicle(0).get_type().get_functions();
34         GLtk::Row row(*pnl_functions->get_layout());
35         for(VehicleType::FunctionMap::const_iterator i=funcs.begin(); i!=funcs.end(); ++i)
36         {
37                 GLtk::Toggle *tgl = new GLtk::Toggle(i->second);
38                 tgl->signal_toggled.connect(sigc::bind(sigc::mem_fun(this, &ControlPanel::ui_function_toggled), i->first));
39                 pnl_functions->add(*tgl);
40                 tgl_funcs[i->first] = tgl;
41         }
42
43         train.signal_function_changed.connect(sigc::mem_fun(this, &ControlPanel::train_function_changed));
44 }
45
46 void ControlPanel::ui_function_toggled(bool value, unsigned func)
47 {
48         if(!updating)
49                 train.set_function(func, value);
50 }
51
52 void ControlPanel::train_function_changed(unsigned func, bool value)
53 {
54         SetFlag setf(updating);
55         map<unsigned, GLtk::Toggle *>::iterator i = tgl_funcs.find(func);
56         if(i!=tgl_funcs.end())
57                 i->second->set_value(value);
58 }
59
60 void ControlPanel::place_clicked()
61 {
62         signal_grab_pointer.emit();
63         placing = true;
64
65         Layout3D &layout3d = engineer.get_layout_3d();
66         unsigned n_vehs = train.get_n_vehicles();
67         for(unsigned i=0; i<n_vehs; ++i)
68                 ghosts.push_back(new PlacementGhost(layout3d, train.get_vehicle(i).get_type()));
69 }
70
71 void ControlPanel::take_clicked()
72 {
73         train.unplace();
74 }
75
76 void ControlPanel::view_clicked()
77 {
78         TrainView *dlg = new TrainView(engineer, train);
79         find_ancestor<GLtk::Root>()->add(*dlg);
80         dlg->autosize();
81 }
82
83 void ControlPanel::button_press(int x, int y, unsigned btn)
84 {
85         Panel::button_press(x, y, btn);
86
87         if(placing)
88         {
89                 signal_ungrab_pointer.emit();
90                 placing = false;
91
92                 for(vector<PlacementGhost *>::iterator i=ghosts.begin(); i!=ghosts.end(); ++i)
93                         delete *i;
94                 ghosts.clear();
95
96                 if(btn==1 && place_location)
97                         train.place(place_location);
98         }
99 }
100
101 void ControlPanel::pointer_motion(int x, int y)
102 {
103         Panel::pointer_motion(x, y);
104
105         if(placing)
106         {
107                 int rx = x;
108                 int ry = y;
109                 map_coords_to_ancestor(rx, ry, *find_ancestor<GLtk::Root>());
110                 Ray ray = engineer.get_main_view().create_ray(rx, ry);
111                 Track *track = engineer.get_layout().pick<Track>(ray);
112                 if(track)
113                 {
114                         place_location = TrackIter(track, 0).block_iter();
115                         if(place_location)
116                         {
117                                 ghosts.back()->place(place_location.track_iter());
118                                 for(unsigned i=ghosts.size()-1; i--; )
119                                         ghosts[i]->place_before(*ghosts[i+1]);
120                         }
121                 }
122         }
123 }