]> git.tdb.fi Git - r2c2.git/commitdiff
Add locomotive types
authorMikko Rasa <tdb@tdb.fi>
Wed, 4 Jun 2008 23:51:10 +0000 (23:51 +0000)
committerMikko Rasa <tdb@tdb.fi>
Wed, 4 Jun 2008 23:51:10 +0000 (23:51 +0000)
Buttons for locomotive functions
Various enhancements around the code
UI graphics for dropdown

16 files changed:
engineer.res
gui.blend
gui.png
source/engineer/engineer.cpp
source/engineer/engineer.h
source/engineer/mainpanel.cpp
source/engineer/trainpanel.cpp
source/engineer/trainpanel.h
source/engineer/trainproperties.cpp
source/engineer/trainproperties.h
source/libmarklin/catalogue.cpp
source/libmarklin/catalogue.h
source/libmarklin/locomotive.cpp
source/libmarklin/locomotive.h
source/libmarklin/locotype.cpp [new file with mode: 0644]
source/libmarklin/locotype.h [new file with mode: 0644]

index 7f75ae494214146e84dc095614b84b2882c64d8e..c5650af8252962f377e5049b0c2aa270506220c5 100644 (file)
@@ -68,6 +68,19 @@ graphic "entrycursor"
        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";
@@ -291,3 +304,47 @@ style "root"
 {
        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";
index f53efdaa83519a4d35cafb958bdf09a9308387d6..9407d861862eb0fb707693304464c216474a37f1 100644 (file)
Binary files a/gui.blend and b/gui.blend differ
diff --git a/gui.png b/gui.png
index cb71fa154c327fdca7e46e41667c28c33e534916..b0fec5b3b9912f030ebedf78fa43f355130be3c9 100644 (file)
Binary files a/gui.png and b/gui.png differ
index ec5610396f45f3c7530be5bd5f143fbbfafdfc3c..0d4f7291745473c8785141d9231edc69e7ff670a 100644 (file)
@@ -71,6 +71,7 @@ Engineer::Engineer(int argc, char **argv):
        layout_3d.set_quality(quality);
 
        catalogue.load("tracks.dat");
+       catalogue.load("locos.dat");
 
        const vector<string> &args=getopt.get_args();
        if(args.empty())
@@ -92,37 +93,33 @@ Engineer::~Engineer()
        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)
index 3552badd5a49fc6f749820da51958360c32bd0fa..f6e23bc28e18c1fc27d6b48f1e44c528563176ce 100644 (file)
@@ -8,6 +8,7 @@
 #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"
@@ -48,8 +49,10 @@ public:
        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); }
index c89060a4416b77145337de2f2bffd743493cb6e3..7866a1cf1d1348340f7ccfc7e578a28a10653752 100644 (file)
@@ -71,7 +71,7 @@ void MainPanel::power_off()
 
 void MainPanel::new_loc()
 {
-       engineer.add_train(0);
+       engineer.add_train();
 }
 
 void MainPanel::quit()
index cd41c2343d2adde8a354dbebaa2d307718608163..8c23f26164c3ed15a3ab6ee278af9a9875516be6 100644 (file)
@@ -13,7 +13,7 @@ TrainPanel::TrainPanel(Engineer &e, const GLtk::Resources &r, Train &t):
        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");
@@ -35,13 +35,31 @@ TrainPanel::TrainPanel(Engineer &e, const GLtk::Resources &r, Train &t):
        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));
 
@@ -60,6 +78,13 @@ void TrainPanel::loco_speed_changed(unsigned speed)
        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);
@@ -69,3 +94,8 @@ void TrainPanel::place_clicked()
 {
        engineer.place_train(train);
 }
+
+void TrainPanel::func_clicked(unsigned func)
+{
+       train.get_locomotive().set_function(func, !train.get_locomotive().get_function(func));
+}
index 87e17c9a14570b193c293f6902103407cbe09d68..63e6e734bf8bb12ef665199bbdf7aba1f39a0abd 100644 (file)
@@ -2,6 +2,7 @@
 #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"
@@ -16,17 +17,19 @@ private:
        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
index 1a918ad19f6c1bacda3fea692b8f4a4a5ad10804..36f932523ff627517732a0455573c164ed8691dd 100644 (file)
@@ -1,8 +1,10 @@
 #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;
 
@@ -16,6 +18,13 @@ TrainProperties::TrainProperties(Engineer &e, GLtk::Resources &r, Train *t):
        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));
 
@@ -29,17 +38,23 @@ TrainProperties::TrainProperties(Engineer &e, GLtk::Resources &r, Train *t):
        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()
+{
+}
index 5d24613a7329a3cf718189a94adf635fc0ff6760..20ab3349fa4f85815ea7648bf2b86a3a3030495f 100644 (file)
@@ -1,6 +1,7 @@
 #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>
@@ -13,6 +14,7 @@ private:
        Engineer &engineer;
        Marklin::Train *train;
        Msp::GLtk::Entry *ent_addr;
+       Msp::GLtk::Dropdown *drp_type;
        Msp::GLtk::Entry *ent_name;
 
 public:
@@ -21,6 +23,7 @@ public:
        TrainProperties(Engineer &, Msp::GLtk::Resources &, Marklin::Train *);
 private:
        void ok_clicked();
+       void cancel_clicked();
 };
 
 #endif
index 00c27738cfb118a06040d626fe90064e036435cd..3ab96a99ebbadb325f821c1c52e74ba083ee1ac0 100644 (file)
@@ -1,6 +1,7 @@
 #include <msp/core/refptr.h>
 #include <msp/datafile/parser.h>
 #include "catalogue.h"
+#include "locotype.h"
 #include "tracktype.h"
 
 using namespace std;
@@ -14,7 +15,7 @@ Catalogue::~Catalogue()
                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())
@@ -23,6 +24,15 @@ TrackType &Catalogue::get_track(unsigned art_nr)
        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());
@@ -36,9 +46,22 @@ void Catalogue::load(const string &fn)
 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);
@@ -48,7 +71,7 @@ void Catalogue::Loader::track(unsigned 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
index 66e34667e2f161bfba4c90b42d55150062b78f8f..4179ea75aa339ceedb781d147d3338a33b152b52 100644 (file)
@@ -6,6 +6,7 @@
 
 namespace Marklin {
 
+class LocoType;
 class TrackType;
 
 class Catalogue
@@ -18,17 +19,21 @@ public:
        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 &);
 };
 
index 0de0110f3cafd673ec55347ec3fb71c9e987cc74..530a111d7963a4ee1074f6d2f70a778cc98633d6 100644 (file)
@@ -10,7 +10,8 @@ using namespace Msp;
 
 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),
@@ -56,6 +57,8 @@ void Locomotive::set_function(unsigned func, bool state)
                funcs&=~(1<<func);
 
        send_command(true);
+
+       signal_function_changed.emit(func, state);
 }
 
 void Locomotive::refresh_status()
@@ -105,6 +108,9 @@ void Locomotive::status_reply(Error err, const string &reply)
                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);
        }
 }
 
index eae99f57dddfdb66e5f7183fa3fa52356a540e97..a127a173c3af4a395e0dad757467c7bdc393cbfb 100644 (file)
@@ -9,10 +9,12 @@
 namespace Marklin {
 
 class Control;
+class LocoType;
 
 class Locomotive
 {
 private:
+       const LocoType &type;
        Control  &control;
        unsigned addr;
        unsigned speed;
@@ -21,9 +23,11 @@ private:
 
 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);
diff --git a/source/libmarklin/locotype.cpp b/source/libmarklin/locotype.cpp
new file mode 100644 (file)
index 0000000..31a995a
--- /dev/null
@@ -0,0 +1,24 @@
+#include "locotype.h"
+
+using namespace std;
+
+namespace Marklin {
+
+LocoType::LocoType(unsigned an):
+       art_nr(an)
+{ }
+
+
+LocoType::Loader::Loader(LocoType &lt):
+       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
diff --git a/source/libmarklin/locotype.h b/source/libmarklin/locotype.h
new file mode 100644 (file)
index 0000000..bce5c57
--- /dev/null
@@ -0,0 +1,37 @@
+#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 &ltype;
+
+       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