00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <mapviz_plugins/string_plugin.h>
00032
00033 #include <pluginlib/class_list_macros.h>
00034 #include <mapviz/select_topic_dialog.h>
00035
00036 #include <QFontDialog>
00037
00038 PLUGINLIB_EXPORT_CLASS(mapviz_plugins::StringPlugin, mapviz::MapvizPlugin)
00039
00040 namespace mapviz_plugins
00041 {
00042 const char* StringPlugin::COLOR_KEY = "color";
00043 const char* StringPlugin::FONT_KEY = "font";
00044 const char* StringPlugin::TOPIC_KEY = "topic";
00045 const char* StringPlugin::ANCHOR_KEY = "anchor";
00046 const char* StringPlugin::UNITS_KEY = "units";
00047 const char* StringPlugin::OFFSET_X_KEY = "offset_x";
00048 const char* StringPlugin::OFFSET_Y_KEY = "offset_y";
00049
00050 StringPlugin::StringPlugin() :
00051 config_widget_(new QWidget()),
00052 anchor_(TOP_LEFT),
00053 units_(PIXELS),
00054 offset_x_(0),
00055 offset_y_(0),
00056 has_message_(false),
00057 has_painted_(false),
00058 color_(Qt::black)
00059 {
00060 ui_.setupUi(config_widget_);
00061
00062 QPalette p(config_widget_->palette());
00063 p.setColor(QPalette::Background, Qt::white);
00064 config_widget_->setPalette(p);
00065
00066
00067 QPalette p3(ui_.status->palette());
00068 p3.setColor(QPalette::Text, Qt::red);
00069 ui_.status->setPalette(p3);
00070
00071 QObject::connect(ui_.selecttopic, SIGNAL(clicked()), this, SLOT(SelectTopic()));
00072 QObject::connect(ui_.topic, SIGNAL(editingFinished()), this, SLOT(TopicEdited()));
00073 QObject::connect(ui_.anchor, SIGNAL(activated(QString)), this, SLOT(SetAnchor(QString)));
00074 QObject::connect(ui_.units, SIGNAL(activated(QString)), this, SLOT(SetUnits(QString)));
00075 QObject::connect(ui_.offsetx, SIGNAL(valueChanged(int)), this, SLOT(SetOffsetX(int)));
00076 QObject::connect(ui_.offsety, SIGNAL(valueChanged(int)), this, SLOT(SetOffsetY(int)));
00077 QObject::connect(ui_.font_button, SIGNAL(clicked()), this, SLOT(SelectFont()));
00078 QObject::connect(ui_.color, SIGNAL(colorEdited(const QColor &)), this, SLOT(SelectColor()));
00079
00080 font_.setFamily(tr("Helvetica"));
00081 ui_.font_button->setFont(font_);
00082 ui_.font_button->setText(font_.family());
00083
00084 ui_.color->setColor(color_);
00085 }
00086
00087 StringPlugin::~StringPlugin()
00088 {
00089 }
00090
00091 bool StringPlugin::Initialize(QGLWidget* canvas)
00092 {
00093 canvas_ = canvas;
00094 return true;
00095 }
00096
00097 void StringPlugin::Draw(double x, double y, double scale)
00098 {
00099
00100 }
00101
00102 void StringPlugin::Paint(QPainter* painter, double x, double y, double scale)
00103 {
00104 if (has_message_)
00105 {
00106 painter->save();
00107 painter->resetTransform();
00108 painter->setFont(font_);
00109
00110 if (!has_painted_)
00111 {
00112
00113
00114
00115
00116
00117
00118
00119 QPen invisPen(QBrush(Qt::transparent), 1);
00120 painter->setPen(invisPen);
00121 PaintText(painter);
00122 has_painted_ = true;
00123 }
00124 QPen pen(QBrush(color_), 1);
00125 painter->setPen(pen);
00126 PaintText(painter);
00127
00128 painter->restore();
00129 PrintInfo("OK");
00130 }
00131 else
00132 {
00133 PrintWarning("No messages received.");
00134 }
00135 }
00136
00137 void StringPlugin::PaintText(QPainter* painter)
00138 {
00139
00140 int x_offset = offset_x_;
00141 int y_offset = offset_y_;
00142 if (units_ == PERCENT)
00143 {
00144 x_offset = static_cast<int>((float)(offset_x_ * canvas_->width()) / 100.0);
00145 y_offset = static_cast<int>((float)(offset_y_ * canvas_->height()) / 100.0);
00146 }
00147
00148 int right = static_cast<int>((float)canvas_->width() - message_.size().width()) - x_offset;
00149 int bottom = static_cast<int>((float)canvas_->height() - message_.size().height()) - y_offset;
00150 int yCenter = static_cast<int>((float)canvas_->height() / 2.0 - message_.size().height()/2.0);
00151 int xCenter = static_cast<int>((float)canvas_->width() / 2.0 - message_.size().width()/2.0);
00152
00153 QPoint ulPoint;
00154
00155 switch (anchor_)
00156 {
00157 case TOP_LEFT:
00158 ulPoint.setX(x_offset);
00159 ulPoint.setY(y_offset);
00160 break;
00161 case TOP_CENTER:
00162 ulPoint.setX(xCenter);
00163 ulPoint.setY(y_offset);
00164 break;
00165 case TOP_RIGHT:
00166 ulPoint.setX(right);
00167 ulPoint.setY(y_offset);
00168 break;
00169 case CENTER_LEFT:
00170 ulPoint.setX(x_offset);
00171 ulPoint.setY(yCenter);
00172 break;
00173 case CENTER:
00174 ulPoint.setX(xCenter);
00175 ulPoint.setY(yCenter);
00176 break;
00177 case CENTER_RIGHT:
00178 ulPoint.setX(right);
00179 ulPoint.setY(yCenter);
00180 break;
00181 case BOTTOM_LEFT:
00182 ulPoint.setX(x_offset);
00183 ulPoint.setY(bottom);
00184 break;
00185 case BOTTOM_CENTER:
00186 ulPoint.setX(xCenter);
00187 ulPoint.setY(bottom);
00188 break;
00189 case BOTTOM_RIGHT:
00190 ulPoint.setX(right);
00191 ulPoint.setY(bottom);
00192 break;
00193 }
00194 painter->drawStaticText(ulPoint, message_);
00195 }
00196
00197 void StringPlugin::LoadConfig(const YAML::Node& node, const std::string& path)
00198 {
00199 if (node[TOPIC_KEY])
00200 {
00201 ui_.topic->setText(QString(node[TOPIC_KEY].as<std::string>().c_str()));
00202 TopicEdited();
00203 }
00204
00205 if (node[FONT_KEY])
00206 {
00207 font_.fromString(QString(node[FONT_KEY].as<std::string>().c_str()));
00208 ui_.font_button->setFont(font_);
00209 ui_.font_button->setText(font_.family());
00210 }
00211
00212 if (node[COLOR_KEY])
00213 {
00214 color_ = QColor(node[COLOR_KEY].as<std::string>().c_str());
00215 ui_.color->setColor(QColor(color_.name().toStdString().c_str()));
00216 }
00217
00218 if (node[ANCHOR_KEY])
00219 {
00220 std::string anchor = node[ANCHOR_KEY].as<std::string>();
00221 ui_.anchor->setCurrentIndex(ui_.anchor->findText(anchor.c_str()));
00222 SetAnchor(anchor.c_str());
00223 }
00224
00225 if (node[UNITS_KEY])
00226 {
00227 std::string units = node[UNITS_KEY].as<std::string>();
00228 ui_.units->setCurrentIndex(ui_.units->findText(units.c_str()));
00229 SetUnits(units.c_str());
00230 }
00231
00232 if (node[OFFSET_X_KEY])
00233 {
00234 offset_x_ = node[OFFSET_X_KEY].as<int>();
00235 ui_.offsetx->setValue(offset_x_);
00236 }
00237
00238 if (node[OFFSET_Y_KEY])
00239 {
00240 offset_y_ = node[OFFSET_Y_KEY].as<int>();
00241 ui_.offsety->setValue(offset_y_);
00242 }
00243 }
00244
00245 void StringPlugin::SaveConfig(YAML::Emitter& emitter, const std::string& path)
00246 {
00247 emitter << YAML::Key << FONT_KEY << YAML::Value << font_.toString().toStdString();
00248 emitter << YAML::Key << COLOR_KEY << YAML::Value << color_.name().toStdString();
00249 emitter << YAML::Key << TOPIC_KEY << YAML::Value << ui_.topic->text().toStdString();
00250 emitter << YAML::Key << ANCHOR_KEY << YAML::Value << AnchorToString(anchor_);
00251 emitter << YAML::Key << UNITS_KEY << YAML::Value << UnitsToString(units_);
00252 emitter << YAML::Key << OFFSET_X_KEY << YAML::Value << offset_x_;
00253 emitter << YAML::Key << OFFSET_Y_KEY << YAML::Value << offset_y_;
00254 }
00255
00256 QWidget* StringPlugin::GetConfigWidget(QWidget* parent)
00257 {
00258 config_widget_->setParent(parent);
00259 return config_widget_;
00260 }
00261
00262 void StringPlugin::PrintError(const std::string& message)
00263 {
00264 PrintErrorHelper(ui_.status, message);
00265 }
00266
00267 void StringPlugin::PrintInfo(const std::string& message)
00268 {
00269 PrintInfoHelper(ui_.status, message);
00270 }
00271
00272 void StringPlugin::PrintWarning(const std::string& message)
00273 {
00274 PrintWarningHelper(ui_.status, message);
00275 }
00276
00277 void StringPlugin::SelectColor()
00278 {
00279 color_ = ui_.color->color();
00280 }
00281
00282 void StringPlugin::SelectFont()
00283 {
00284 bool ok;
00285 QFont font = QFontDialog::getFont(&ok, font_, canvas_);
00286 if (ok)
00287 {
00288 font_ = font;
00289 message_.prepare(QTransform(), font_);
00290 ui_.font_button->setFont(font_);
00291 ui_.font_button->setText(font_.family());
00292 }
00293 }
00294
00295 void StringPlugin::SelectTopic()
00296 {
00297 ros::master::TopicInfo topic = mapviz::SelectTopicDialog::selectTopic(
00298 "std_msgs/String");
00299
00300 if (!topic.name.empty())
00301 {
00302 ui_.topic->setText(QString::fromStdString(topic.name));
00303 TopicEdited();
00304 }
00305 }
00306
00307 void StringPlugin::TopicEdited()
00308 {
00309 std::string topic = ui_.topic->text().trimmed().toStdString();
00310 if (topic != topic_)
00311 {
00312 initialized_ = false;
00313 has_message_ = false;
00314 PrintWarning("No messages received.");
00315
00316 string_sub_.shutdown();
00317
00318 topic_ = topic;
00319 if (!topic.empty())
00320 {
00321 string_sub_ = node_.subscribe(topic_, 1, &StringPlugin::stringCallback, this);
00322
00323 ROS_INFO("Subscribing to %s", topic_.c_str());
00324 }
00325 }
00326 }
00327
00328 void StringPlugin::SetAnchor(QString anchor)
00329 {
00330 if (anchor == "top left")
00331 {
00332 anchor_ = TOP_LEFT;
00333 }
00334 else if (anchor == "top center")
00335 {
00336 anchor_ = TOP_CENTER;
00337 }
00338 else if (anchor == "top right")
00339 {
00340 anchor_ = TOP_RIGHT;
00341 }
00342 else if (anchor == "center left")
00343 {
00344 anchor_ = CENTER_LEFT;
00345 }
00346 else if (anchor == "center")
00347 {
00348 anchor_ = CENTER;
00349 }
00350 else if (anchor == "center right")
00351 {
00352 anchor_ = CENTER_RIGHT;
00353 }
00354 else if (anchor == "bottom left")
00355 {
00356 anchor_ = BOTTOM_LEFT;
00357 }
00358 else if (anchor == "bottom center")
00359 {
00360 anchor_ = BOTTOM_CENTER;
00361 }
00362 else if (anchor == "bottom right")
00363 {
00364 anchor_ = BOTTOM_RIGHT;
00365 }
00366 }
00367
00368 void StringPlugin::SetUnits(QString units)
00369 {
00370 if (units == "pixels")
00371 {
00372 units_ = PIXELS;
00373 }
00374 else if (units == "percent")
00375 {
00376 units_ = PERCENT;
00377 }
00378 }
00379
00380 void StringPlugin::SetOffsetX(int offset)
00381 {
00382 offset_x_ = offset;
00383 }
00384
00385 void StringPlugin::SetOffsetY(int offset)
00386 {
00387 offset_y_ = offset;
00388 }
00389
00390 void StringPlugin::stringCallback(const std_msgs::StringConstPtr& str)
00391 {
00392 message_.setText(QString(str->data.c_str()));
00393 message_.prepare(QTransform(), font_);
00394
00395 has_message_ = true;
00396 has_painted_ = false;
00397 initialized_ = true;
00398 }
00399
00400 std::string StringPlugin::AnchorToString(StringPlugin::Anchor anchor)
00401 {
00402 std::string anchor_string = "top left";
00403
00404 if (anchor == TOP_LEFT)
00405 {
00406 anchor_string = "top left";
00407 }
00408 else if (anchor == TOP_CENTER)
00409 {
00410 anchor_string = "top center";
00411 }
00412 else if (anchor == TOP_RIGHT)
00413 {
00414 anchor_string = "top right";
00415 }
00416 else if (anchor == CENTER_LEFT)
00417 {
00418 anchor_string = "center left";
00419 }
00420 else if (anchor == CENTER)
00421 {
00422 anchor_string = "center";
00423 }
00424 else if (anchor == CENTER_RIGHT)
00425 {
00426 anchor_string = "center right";
00427 }
00428 else if (anchor == BOTTOM_LEFT)
00429 {
00430 anchor_string = "bottom left";
00431 }
00432 else if (anchor == BOTTOM_CENTER)
00433 {
00434 anchor_string = "bottom center";
00435 }
00436 else if (anchor == BOTTOM_RIGHT)
00437 {
00438 anchor_string = "bottom right";
00439 }
00440
00441 return anchor_string;
00442 }
00443
00444 std::string StringPlugin::UnitsToString(StringPlugin::Units units)
00445 {
00446 std::string units_string = "pixels";
00447
00448 if (units == PIXELS)
00449 {
00450 units_string = "pixels";
00451 }
00452 else if (units == PERCENT)
00453 {
00454 units_string = "percent";
00455 }
00456
00457 return units_string;
00458 }
00459 }