slice 54 74 2 12;
};
+graphic "dropdownbg"
+{
+ texture "gui.png";
+ slice 58 72 30 16;
+ border { top 4; right 20; bottom 4; left 2; };
+};
+
+graphic "dropdownarrow"
+{
+ texture "gui.png";
+ slice 90 75 10 8;
+};
+
graphic "yellowlamp"
{
texture "gui.png";
{
special "children";
};
+
+style "dropdown"
+{
+ font_color 0.0 0.0 0.0;
+
+ part
+ {
+ graphic NORMAL "dropdownbg";
+ };
+
+ part
+ {
+ graphic NORMAL "dropdownarrow";
+ align 1.0 0.5;
+ fill 0.0 0.0;
+ margin { right 2; };
+ };
+
+ special "text"
+ {
+ align 0.0 0.5;
+ fill 0.0 0.0;
+ margin { left 2; };
+ };
+
+ special "list";
+};
+
+style "list"
+{
+ font_color 0.0 0.0 0.0;
+
+ part
+ {
+ graphic NORMAL "entrybg";
+ };
+
+ special "items"
+ {
+ margin { top 2; right 2; bottom 2; left 2; };
+ };
+};
+
+style "vslider";
layout_3d.set_quality(quality);
catalogue.load("tracks.dat");
+ catalogue.load("locos.dat");
const vector<string> &args=getopt.get_args();
if(args.empty())
delete trfc_mgr;
}
-Train *Engineer::add_train(unsigned addr)
+void Engineer::add_train()
{
- if(addr==0)
- {
- train_prop=new TrainProperties(*this, ui_res, 0);
- root->add(*train_prop);
- train_prop->signal_ok.connect(sigc::mem_fun(this, &Engineer::dismiss_train_prop));
- train_prop_stale=false;
- train_prop->set_visible(true);
+ train_prop=new TrainProperties(*this, ui_res, 0);
+ root->add(*train_prop);
+ train_prop->signal_ok.connect(sigc::mem_fun(this, &Engineer::dismiss_train_prop));
+ train_prop_stale=false;
+ train_prop->set_visible(true);
+}
- return 0;
- }
- else
- {
- Locomotive *loco=new Locomotive(control, addr);
- Train *train=new Train(*trfc_mgr, *loco);
- train->set_name(format("Train %d", trfc_mgr->get_trains().size()));
-
- TrainPanel *tpanel=new TrainPanel(*this, ui_res, *train);
- root->add(*tpanel);
- int y=main_panel->get_geometry().y;
- for(list<TrainPanel *>::iterator i=train_panels.begin(); i!=train_panels.end(); ++i)
- y-=(*i)->get_geometry().h;
- tpanel->set_position(0, y-tpanel->get_geometry().h);
- train_panels.push_back(tpanel);
- tpanel->set_visible(true);
-
- place_train(*train);
-
- return train;
- }
+Train *Engineer::add_train(const LocoType &type, unsigned addr)
+{
+ Locomotive *loco=new Locomotive(type, control, addr);
+ Train *train=new Train(*trfc_mgr, *loco);
+ train->set_name(format("Train %d", trfc_mgr->get_trains().size()));
+
+ TrainPanel *tpanel=new TrainPanel(*this, ui_res, *train);
+ root->add(*tpanel);
+ int y=main_panel->get_geometry().y;
+ for(list<TrainPanel *>::iterator i=train_panels.begin(); i!=train_panels.end(); ++i)
+ y-=(*i)->get_geometry().h;
+ tpanel->set_position(0, y-tpanel->get_geometry().h);
+ train_panels.push_back(tpanel);
+ tpanel->set_visible(true);
+
+ place_train(*train);
+
+ return train;
}
void Engineer::place_train(Train &train)
#include <msp/gltk/root.h>
#include "libmarklin/catalogue.h"
#include "libmarklin/control.h"
+#include "libmarklin/locotype.h"
#include "libmarklin/trafficmanager.h"
#include "libmarklin/train.h"
#include "3d/layout.h"
Engineer(int argc, char **argv);
~Engineer();
+ const Marklin::Catalogue &get_catalogue() const { return catalogue; }
Marklin::Control &get_control() { return control; }
- Marklin::Train *add_train(unsigned);
+ void add_train();
+ Marklin::Train *add_train(const Marklin::LocoType &, unsigned);
void place_train(Marklin::Train &);
int main();
void quit() { exit(0); }
void MainPanel::new_loc()
{
- engineer.add_train(0);
+ engineer.add_train();
}
void MainPanel::quit()
engineer(e),
train(t)
{
- set_size(200, 131);
+ set_size(200, 172);
add(*(lbl_addr=new GLtk::Label(res, format("%2d", train.get_locomotive().get_address()))));
lbl_addr->set_style("digital");
lbl_speed->set_geometry(GLtk::Geometry(10, geom.h-63, 35, 24));
train.get_locomotive().signal_speed_changed.connect(sigc::mem_fun(this, &TrainPanel::loco_speed_changed));
+ GLtk::Button *btn;
+
+ const map<unsigned, string> &funcs=train.get_locomotive().get_type().get_functions();
+ unsigned x=10;
+ for(map<unsigned, string>::const_iterator i=funcs.begin(); i!=funcs.end(); ++i, x+=40)
+ {
+ string fname=i->second;
+ fname[0]=toupper(fname[0]);
+ add(*(btn=new GLtk::Button(res, fname)));
+ btn->set_geometry(GLtk::Geometry(x, 68, 40, 24));
+ btn->signal_clicked.connect(sigc::bind(sigc::mem_fun(this, &TrainPanel::func_clicked), i->first));
+
+ GLtk::Indicator *ind=new GLtk::Indicator(res);
+ add(*ind);
+ ind->set_geometry(GLtk::Geometry(x, 92, 40, 12));
+ ind->set_active(train.get_locomotive().get_function(i->first));
+ ind_funcs[i->first]=ind;
+ }
+ train.get_locomotive().signal_function_changed.connect(sigc::mem_fun(this, &TrainPanel::loco_function_changed));
+
add(*(lbl_status=new GLtk::Label(res, train.get_status())));
lbl_status->set_style("digital");
- lbl_status->set_geometry(GLtk::Geometry(10, geom.h-92, geom.w-20, 24));
+ lbl_status->set_geometry(GLtk::Geometry(10, 39, geom.w-20, 24));
train.signal_status_changed.connect(sigc::mem_fun(this, &TrainPanel::train_status_changed));
- GLtk::Button *btn;
-
add(*(btn=new GLtk::Button(res, "Edit")));
btn->set_geometry(GLtk::Geometry(geom.w-50, 10, 40, 24));
lbl_speed->set_text(format("%2d", speed));
}
+void TrainPanel::loco_function_changed(unsigned func, bool value)
+{
+ map<unsigned, GLtk::Indicator *>::iterator i=ind_funcs.find(func);
+ if(i!=ind_funcs.end())
+ i->second->set_active(value);
+}
+
void TrainPanel::train_status_changed(const string &s)
{
lbl_status->set_text(s);
{
engineer.place_train(train);
}
+
+void TrainPanel::func_clicked(unsigned func)
+{
+ train.get_locomotive().set_function(func, !train.get_locomotive().get_function(func));
+}
#define TRAINPANEL_H_
#include <msp/gltk/hslider.h>
+#include <msp/gltk/indicator.h>
#include <msp/gltk/label.h>
#include <msp/gltk/panel.h>
#include "libmarklin/train.h"
Msp::GLtk::Label *lbl_addr;
Msp::GLtk::Label *lbl_name;
Msp::GLtk::HSlider *sld_speed;
- Marklin::Locomotive *loco;
Msp::GLtk::Label *lbl_speed;
Msp::GLtk::Label *lbl_status;
+ std::map<unsigned, Msp::GLtk::Indicator *> ind_funcs;
public:
TrainPanel(Engineer &, const Msp::GLtk::Resources &, Marklin::Train &);
private:
void speed_slider_changed(double);
void loco_speed_changed(unsigned);
+ void loco_function_changed(unsigned, bool);
void train_status_changed(const std::string &);
void place_clicked();
+ void func_clicked(unsigned);
};
#endif
#include <msp/gltk/button.h>
+#include <msp/strings/formatter.h>
#include <msp/strings/lexicalcast.h>
#include "engineer.h"
#include "trainproperties.h"
+using namespace std;
using namespace Msp;
using namespace Marklin;
add(*(ent_addr=new GLtk::Entry(res)));
ent_addr->set_geometry(GLtk::Geometry(10, geom.h-30, 40, 20));
+ add(*(drp_type=new GLtk::Dropdown(res)));
+ drp_type->set_geometry(GLtk::Geometry(60, geom.h-30, geom.w-70, 20));
+
+ const map<unsigned, LocoType *> &locos=engineer.get_catalogue().get_locomotives();
+ for(map<unsigned, LocoType *>::const_iterator i=locos.begin(); i!=locos.end(); ++i)
+ drp_type->append(format("%d %s", i->second->get_article_number(), i->second->get_name()));
+
add(*(ent_name=new GLtk::Entry(res, "Train")));
ent_name->set_geometry(GLtk::Geometry(10, geom.h-55, geom.w-20, 20));
add(*(btn=new GLtk::Button(res, "Cncl")));
btn->set_style("red");
btn->set_geometry(GLtk::Geometry(geom.w-80, 10, 30, 25));
+ btn->signal_clicked.connect(sigc::mem_fun(this, &TrainProperties::cancel_clicked));
}
void TrainProperties::ok_clicked()
{
- if(train)
- {
- }
- else
+ if(!train)
{
- train=engineer.add_train(lexical_cast<unsigned>(ent_addr->get_text()));
- train->set_name(ent_name->get_text());
+ const map<unsigned, LocoType *> &locos=engineer.get_catalogue().get_locomotives();
+ map<unsigned, LocoType *>::const_iterator i=locos.begin();
+ advance(i, drp_type->get_selected_index());
+ train=engineer.add_train(*i->second, lexical_cast<unsigned>(ent_addr->get_text()));
}
+
+ train->set_name(ent_name->get_text());
signal_ok.emit();
}
+
+void TrainProperties::cancel_clicked()
+{
+}
#ifndef TRAINPROPERTIES_H_
#define TRAINPROPERTIES_H_
+#include <msp/gltk/dropdown.h>
#include <msp/gltk/entry.h>
#include <msp/gltk/panel.h>
#include <libmarklin/train.h>
Engineer &engineer;
Marklin::Train *train;
Msp::GLtk::Entry *ent_addr;
+ Msp::GLtk::Dropdown *drp_type;
Msp::GLtk::Entry *ent_name;
public:
TrainProperties(Engineer &, Msp::GLtk::Resources &, Marklin::Train *);
private:
void ok_clicked();
+ void cancel_clicked();
};
#endif
#include <msp/core/refptr.h>
#include <msp/datafile/parser.h>
#include "catalogue.h"
+#include "locotype.h"
#include "tracktype.h"
using namespace std;
delete i->second;
}
-TrackType &Catalogue::get_track(unsigned art_nr)
+TrackType &Catalogue::get_track(unsigned art_nr) const
{
map<unsigned, TrackType *>::const_iterator i=tracks.find(art_nr);
if(i==tracks.end())
return *i->second;
}
+LocoType &Catalogue::get_locomotive(unsigned art_nr) const
+{
+ map<unsigned, LocoType *>::const_iterator i=locos.find(art_nr);
+ if(i==locos.end())
+ throw KeyError("Unknown locomotive type");
+
+ return *i->second;
+}
+
void Catalogue::load(const string &fn)
{
IO::File in(fn.c_str());
Catalogue::Loader::Loader(Catalogue &c):
cat(c)
{
+ add("locomotive", &Loader::locomotive);
add("track", &Loader::track);
}
+void Catalogue::Loader::locomotive(unsigned art_no)
+{
+ map<unsigned, LocoType *>::iterator i=cat.locos.find(art_no);
+ if(i!=cat.locos.end())
+ throw Exception("Duplicate locomotive number");
+
+ RefPtr<LocoType> loco=new LocoType(art_no);
+ load_sub(*loco);
+ unsigned art_nr=loco->get_article_number();
+ cat.locos[art_nr]=loco.release();
+}
+
void Catalogue::Loader::track(unsigned art_no)
{
map<unsigned, TrackType *>::iterator i=cat.tracks.find(art_no);
RefPtr<TrackType> trk=new TrackType(art_no);
load_sub(*trk);
unsigned art_nr=trk->get_article_number();
- cat.tracks.insert(map<unsigned, TrackType *>::value_type(art_nr, trk.release()));
+ cat.tracks[art_nr]=trk.release();
}
} // namespace Marklin
namespace Marklin {
+class LocoType;
class TrackType;
class Catalogue
private:
Catalogue &cat;
+ void locomotive(unsigned);
void track(unsigned);
};
private:
std::map<unsigned, TrackType *> tracks;
+ std::map<unsigned, LocoType *> locos;
public:
~Catalogue();
- TrackType &get_track(unsigned);
+ TrackType &get_track(unsigned) const;
const std::map<unsigned, TrackType *> &get_tracks() const { return tracks; }
+ LocoType &get_locomotive(unsigned) const;
+ const std::map<unsigned, LocoType *> &get_locomotives() const { return locos; }
void load(const std::string &);
};
namespace Marklin {
-Locomotive::Locomotive(Control &c, unsigned a):
+Locomotive::Locomotive(const LocoType &t, Control &c, unsigned a):
+ type(t),
control(c),
addr(a),
speed(0),
funcs&=~(1<<func);
send_command(true);
+
+ signal_function_changed.emit(func, state);
}
void Locomotive::refresh_status()
funcs=(reply[1]&0xF)<<1;
if(reply[1]&0x10)
funcs|=1;
+
+ for(unsigned i=0; i<5; ++i)
+ signal_function_changed.emit(i, (funcs>>i)&1);
}
}
namespace Marklin {
class Control;
+class LocoType;
class Locomotive
{
private:
+ const LocoType &type;
Control &control;
unsigned addr;
unsigned speed;
public:
sigc::signal<void, unsigned> signal_speed_changed;
+ sigc::signal<void, unsigned, bool> signal_function_changed;
- Locomotive(Control &, unsigned);
+ Locomotive(const LocoType &, Control &, unsigned);
+ const LocoType &get_type() const { return type; }
void set_speed(unsigned);
void set_reverse(bool);
void set_function(unsigned, bool);
--- /dev/null
+#include "locotype.h"
+
+using namespace std;
+
+namespace Marklin {
+
+LocoType::LocoType(unsigned an):
+ art_nr(an)
+{ }
+
+
+LocoType::Loader::Loader(LocoType <):
+ ltype(lt)
+{
+ add("function", &Loader::function);
+ add("name", &LocoType::name);
+}
+
+void LocoType::Loader::function(unsigned i, const string &f)
+{
+ ltype.funcs[i]=f;
+}
+
+} // namespace Marklin
--- /dev/null
+#ifndef LIBMARKLIN_LOCOTYPE_H_
+#define LIBMARKLIN_LOCOTYPE_H_
+
+#include <msp/datafile/loader.h>
+
+namespace Marklin {
+
+class LocoType
+{
+public:
+ class Loader: public Msp::DataFile::Loader
+ {
+ private:
+ LocoType <ype;
+
+ public:
+ Loader(LocoType &);
+ LocoType &get_object() const { return ltype; }
+ private:
+ void function(unsigned, const std::string &);
+ };
+
+private:
+ unsigned art_nr;
+ std::string name;
+ std::map<unsigned, std::string> funcs;
+
+public:
+ LocoType(unsigned);
+ unsigned get_article_number() const { return art_nr; }
+ const std::string &get_name() const { return name; }
+ const std::map<unsigned, std::string> &get_functions() const { return funcs; }
+};
+
+} // namespace Marklin
+
+#endif