const Msp::GLtk::Resources &get_ui_resources() const { return ui_res; }
Msp::GLtk::Root &get_root() const { return *root; }
const Marklin::Catalogue &get_catalogue() const { return catalogue; }
+ const Marklin::Layout &get_layout() const { return layout; }
Marklin::Control &get_control() { return control; }
Marklin::TrafficManager &get_traffic_manager() { return *trfc_mgr; }
void place_train(Marklin::Train &);
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2009 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <msp/gltk/label.h>
+#include "engineer.h"
+#include "libmarklin/route.h"
+#include "routeselect.h"
+
+using namespace std;
+using namespace Msp;
+using namespace Marklin;
+
+RouteSelect::RouteSelect(Engineer &e, const GLtk::Resources &r, Train &t):
+ GLtk::Widget(r),
+ Dialog(r),
+ engineer(e),
+ train(t)
+{
+ set_size(200, 95);
+
+ GLtk::Label *label;
+ add(*(label = new GLtk::Label(res, "Select route")));
+ label->set_geometry(GLtk::Geometry(10, geom.h-25, geom.w-20, 20));
+
+ add(*(drp_route = new GLtk::Dropdown(res)));
+ drp_route->set_geometry(GLtk::Geometry(10, geom.h-50, geom.w-20, 20));
+ drp_route->append("(none)");
+ drp_route->set_selected_index(0);
+ const set<Route *> &routes = engineer.get_layout().get_routes();
+ unsigned n = 1;
+ for(set<Route *>::const_iterator i=routes.begin(); i!=routes.end(); ++i, ++n)
+ {
+ drp_route->append((*i)->get_name());
+ if(*i==train.get_route())
+ drp_route->set_selected_index(n);
+ }
+}
+
+void RouteSelect::on_ok_clicked()
+{
+ if(drp_route->get_selected_index()>0)
+ {
+ const set<Route *> &routes = engineer.get_layout().get_routes();
+ set<Route *>::const_iterator i = routes.begin();
+ advance(i, drp_route->get_selected_index()-1);
+
+ train.set_route(*i);
+ }
+ else
+ train.set_route(0);
+}
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2009 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef ROUTESELECT_H_
+#define ROUTESELECT_H_
+
+#include <msp/gltk/dropdown.h>
+#include "libmarklin/train.h"
+#include "dialog.h"
+
+class Engineer;
+
+class RouteSelect: public Dialog
+{
+private:
+ Engineer &engineer;
+ Marklin::Train &train;
+ Msp::GLtk::Dropdown *drp_route;
+
+public:
+ RouteSelect(Engineer &, const Msp::GLtk::Resources &, Marklin::Train &);
+private:
+ virtual void on_ok_clicked();
+};
+
+#endif
#include <msp/strings/formatter.h>
#include "libmarklin/locomotive.h"
#include "engineer.h"
+#include "routeselect.h"
#include "trainpanel.h"
#include "trainproperties.h"
engineer(e),
train(t)
{
- set_size(200, 145);
+ set_size(200, 170);
add(*(lbl_addr=new GLtk::Label(res, format("%2d", train.get_locomotive().get_address()))));
lbl_addr->set_style("digital");
tgl_forward->set_value(!train.get_locomotive().get_reverse());
tgl_forward->signal_toggled.connect(sigc::mem_fun(this, &TrainPanel::forward_toggled));
+ add(*(lbl_route=new GLtk::Label(res, "Free run")));
+ lbl_route->set_style("digital");
+ lbl_route->set_geometry(GLtk::Geometry(10, 58, geom.w-20, 24));
+ train.signal_route_changed.connect(sigc::mem_fun(this, &TrainPanel::train_route_changed));
+
add(*(lbl_status=new GLtk::Label(res, train.get_status())));
lbl_status->set_style("digital");
lbl_status->set_geometry(GLtk::Geometry(10, 34, geom.w-20, 24));
add(*(btn=new GLtk::Button(res, "GoTo")));
btn->set_geometry(GLtk::Geometry(geom.w-130, 10, 40, 24));
+
+ add(*(btn=new GLtk::Button(res, "Route")));
+ btn->set_geometry(GLtk::Geometry(geom.w-170, 10, 40, 24));
+ btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::route_clicked));
}
void TrainPanel::speed_slider_changed(double v)
i->second->set_value(value);
}
+void TrainPanel::train_route_changed(const Route *r)
+{
+ if(r)
+ lbl_route->set_text(r->get_name());
+ else
+ lbl_route->set_text("Free run");
+}
+
void TrainPanel::train_status_changed(const string &s)
{
lbl_status->set_text(s);
dialog->set_visible(true);
}
+void TrainPanel::route_clicked()
+{
+ RouteSelect *dialog = new RouteSelect(engineer, res, train);
+ engineer.get_root().add(*dialog);
+ dialog->set_position(geom.x+geom.w, geom.y+geom.h-dialog->get_geometry().h);
+ dialog->set_visible(true);
+}
+
void TrainPanel::forward_toggled(bool value)
{
train.set_reverse(!value);
#include <msp/gltk/label.h>
#include <msp/gltk/panel.h>
#include <msp/gltk/toggle.h>
+#include "libmarklin/route.h"
#include "libmarklin/train.h"
class Engineer;
Msp::GLtk::Label *lbl_name;
Msp::GLtk::HSlider *sld_speed;
Msp::GLtk::Label *lbl_speed;
+ Msp::GLtk::Label *lbl_route;
Msp::GLtk::Label *lbl_status;
Msp::GLtk::Toggle *tgl_forward;
std::map<unsigned, Msp::GLtk::Toggle *> tgl_funcs;
void speed_slider_changed(double);
void train_speed_changed(unsigned);
void loco_function_changed(unsigned, bool);
+ void train_route_changed(const Marklin::Route *);
void train_status_changed(const std::string &);
void place_clicked();
void edit_clicked();
+ void route_clicked();
void forward_toggled(bool);
void func_toggled(bool, unsigned);
};
#include <msp/time/utils.h>
#include "control.h"
#include "except.h"
+#include "route.h"
#include "tracktype.h"
#include "trafficmanager.h"
#include "train.h"
loco.set_reverse(rev);
}
+void Train::set_route(const Route *r)
+{
+ route = r;
+ signal_route_changed.emit(route);
+}
+
void Train::place(Block *block, unsigned entry)
{
for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end();)
Block *link = last->block->get_link(exit);
if(link && link->reserve(this))
{
+ if(route && link->get_turnout_id())
+ {
+ int path = route->get_turnout(link->get_turnout_id());
+ if(path>=0)
+ trfc_mgr.get_control().get_turnout(link->get_turnout_id()).set_path(path);
+ }
rsv_blocks.push_back(BlockRef(link, link->get_endpoint_by_link(*last->block)));
last = &rsv_blocks.back();
if(last->block->get_sensor_id())
{
if(real<=real_speed[0].speed)
return 0;
- if(real>=real_speed[14].speed)
- return 14;
unsigned low = 0;
unsigned high = 0;
- for(high=0; real_speed[high].speed<real; ++high)
- if(real_speed[high].weight)
- low = high;
+ for(unsigned i=0; (!high && i<=14); ++i)
+ if(real_speed[i].weight)
+ {
+ if(real_speed[i].speed<real)
+ low = i;
+ else
+ high = i;
+ }
+ if(!high)
+ {
+ if(!low)
+ return 0;
+ return min(static_cast<unsigned>(low*real/real_speed[low].speed), 14U);
+ }
float f = (real-real_speed[low].speed)/(real_speed[high].speed-real_speed[low].speed);
return static_cast<unsigned>(low*(1-f)+high*f+0.5);
namespace Marklin {
class Locomotive;
+class Route;
class Sensor;
class TrafficManager;
class Turnout;
sigc::signal<void, const std::string &> signal_name_changed;
sigc::signal<void, unsigned> signal_target_speed_changed;
+ sigc::signal<void, const Route *> signal_route_changed;
sigc::signal<void, const std::string &> signal_status_changed;
private:
std::list<BlockRef> cur_blocks;
std::list<BlockRef> rsv_blocks;
unsigned target_speed;
+ const Route *route;
Msp::Time::TimeStamp try_reserve;
std::string status;
void set_name(const std::string &);
void set_speed(unsigned);
void set_reverse(bool);
+ void set_route(const Route *);
const std::string &get_name() const { return name; }
Locomotive &get_locomotive() const { return loco; }
unsigned get_target_speed() const { return target_speed; }
+ const Route *get_route() const { return route; }
const std::string &get_status() const { return status; }
const Point &get_position() const { return pos; }
void place(Block *, unsigned);