+#include <msp/input/keys.h>
+#include <msp/strings/format.h>
+#include "designer.h"
+#include "objectselecttool.h"
+
+using namespace std;
+using namespace Msp;
+using namespace R2C2;
+
+ObjectSelectTool::ObjectSelectTool(Designer &d, Input::Keyboard &k, Input::Mouse &m, Selection &s):
+ Tool(d, k, m),
+ selection(s)
+{
+ update_status();
+}
+
+void ObjectSelectTool::key_press(unsigned key)
+{
+ if(key==Input::KEY_ESC)
+ selection.clear();
+ else if(key==Msp::Input::KEY_PLUS)
+ selection.select_more();
+ else if(key==Msp::Input::KEY_L && shift_held)
+ selection.select_blocks();
+ else if(key==Msp::Input::KEY_L)
+ selection.select_linked();
+ else
+ return Tool::key_press(key);
+
+ update_status();
+}
+
+void ObjectSelectTool::button_press(unsigned btn)
+{
+ if(btn==1)
+ {
+ Ray ray = designer.get_view().create_ray(pointer.x, pointer.y);
+ Object *obj = designer.get_layout().pick<Object>(ray);
+ if(obj)
+ {
+ if(!shift_held)
+ selection.clear();
+ selection.toggle_object(obj);
+
+ update_status();
+ }
+ }
+}
+
+void ObjectSelectTool::update_status()
+{
+ const set<Object *> &objects = selection.get_objects();
+ float track_length = 0;
+ unsigned other_count = 0;
+ for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+ {
+ if(Track *track = dynamic_cast<Track *>(*i))
+ track_length += track->get_type().get_total_length();
+ else
+ ++other_count;
+ }
+
+ if(!track_length && !other_count)
+ set_status(string());
+ else
+ {
+ string s;
+ if(track_length)
+ {
+ s += format("%.2fm of track", track_length);
+ if(other_count)
+ s += " and ";
+ }
+ if(other_count)
+ {
+ s += lexical_cast<string>(other_count);
+ if(track_length)
+ s += " other";
+ s += " object";
+ if(other_count>1)
+ s += 's';
+ }
+ s += " selected";
+ set_status(s);
+ }
+}