diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt
index e1e467889..342e3f2c5 100644
--- a/apps/opencs/CMakeLists.txt
+++ b/apps/opencs/CMakeLists.txt
@@ -69,7 +69,7 @@ opencs_units_noqt (view/world
)
opencs_units (view/widget
- scenetoolbar scenetool scenetoolmode pushbutton
+ scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle
)
opencs_units (view/render
diff --git a/apps/opencs/view/widget/pushbutton.cpp b/apps/opencs/view/widget/pushbutton.cpp
index 056e548fb..ccf89e18a 100644
--- a/apps/opencs/view/widget/pushbutton.cpp
+++ b/apps/opencs/view/widget/pushbutton.cpp
@@ -26,6 +26,14 @@ void CSVWidget::PushButton::setExtendedToolTip (const QString& text)
"
(left click to activate,"
"
shift-left click to activate and keep panel open)";
+ case Type_Toggle:
+
+ tooltip += "
(left click to ";
+ tooltip += isChecked() ? "disable" : "enable";
+ tooltip += "
shift-left click to ";
+ tooltip += isChecked() ? "disable" : "enable";
+ tooltip += " and keep panel open)";
+
break;
}
@@ -45,6 +53,9 @@ void CSVWidget::PushButton::keyReleaseEvent (QKeyEvent *event)
if (event->key()==Qt::Key_Return || event->key()==Qt::Key_Enter)
{
mKeepOpen = event->modifiers() & Qt::ShiftModifier;
+
+ setChecked (!isChecked());
+
emit clicked();
}
@@ -61,14 +72,14 @@ CSVWidget::PushButton::PushButton (const QIcon& icon, Type type, const QString&
QWidget *parent)
: QPushButton (icon, "", parent), mKeepOpen (false), mType (type), mToolTip (tooltip)
{
- setCheckable (type==Type_Mode);
+ setCheckable (type==Type_Mode || type==Type_Toggle);
setExtendedToolTip (tooltip);
}
CSVWidget::PushButton::PushButton (Type type, const QString& tooltip, QWidget *parent)
: QPushButton (parent), mKeepOpen (false), mType (type), mToolTip (tooltip)
{
- setCheckable (type==Type_Mode);
+ setCheckable (type==Type_Mode || type==Type_Toggle);
setExtendedToolTip (tooltip);
}
diff --git a/apps/opencs/view/widget/pushbutton.hpp b/apps/opencs/view/widget/pushbutton.hpp
index 9b90bd0c6..eae0f0a24 100644
--- a/apps/opencs/view/widget/pushbutton.hpp
+++ b/apps/opencs/view/widget/pushbutton.hpp
@@ -14,7 +14,8 @@ namespace CSVWidget
enum Type
{
Type_TopMode, // top level button for mode selector panel
- Type_Mode // mode button
+ Type_Mode, // mode button
+ Type_Toggle
};
private:
diff --git a/apps/opencs/view/widget/scenetooltoggle.cpp b/apps/opencs/view/widget/scenetooltoggle.cpp
new file mode 100644
index 000000000..1737bbfc7
--- /dev/null
+++ b/apps/opencs/view/widget/scenetooltoggle.cpp
@@ -0,0 +1,204 @@
+
+#include "scenetooltoggle.hpp"
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include "scenetoolbar.hpp"
+#include "pushbutton.hpp"
+
+void CSVWidget::SceneToolToggle::adjustToolTip()
+{
+ QString toolTip = mToolTip;
+
+ toolTip += "Currently enabled: ";
+
+ bool first = true;
+
+ for (std::map::const_iterator iter (mButtons.begin());
+ iter!=mButtons.end(); ++iter)
+ if (iter->first->isChecked())
+ {
+ if (!first)
+ toolTip += ", ";
+ else
+ first = false;
+
+ toolTip += iter->second.mName;
+ }
+
+ if (first)
+ toolTip += "none";
+
+ toolTip += "(left click to alter selection)";
+
+ setToolTip (toolTip);
+}
+
+void CSVWidget::SceneToolToggle::adjustIcon()
+{
+ unsigned int selection = getSelection();
+ if (!selection)
+ setIcon (QIcon (QString::fromUtf8 (mEmptyIcon.c_str())));
+ else
+ {
+ QPixmap pixmap (48, 48);
+ pixmap.fill (QColor (0, 0, 0, 0));
+
+ {
+ QPainter painter (&pixmap);
+
+ for (std::map::const_iterator iter (mButtons.begin());
+ iter!=mButtons.end(); ++iter)
+ if (iter->first->isChecked())
+ {
+ painter.drawImage (getIconBox (iter->second.mIndex),
+ QImage (QString::fromUtf8 (iter->second.mSmallIcon.c_str())));
+ }
+ }
+
+ setIcon (pixmap);
+ }
+}
+
+QRect CSVWidget::SceneToolToggle::getIconBox (int index) const
+{
+ // layout for a 3x3 grid
+ int xMax = 3;
+ int yMax = 3;
+
+ // icon size
+ int xBorder = 1;
+ int yBorder = 1;
+
+ int iconXSize = (mIconSize-xBorder*(xMax+1))/xMax;
+ int iconYSize = (mIconSize-yBorder*(yMax+1))/yMax;
+
+ int y = index / xMax;
+ int x = index % xMax;
+
+ int total = mButtons.size();
+
+ int actualYIcons = total/xMax;
+
+ if (total % xMax)
+ ++actualYIcons;
+
+ if (actualYIcons!=yMax)
+ {
+ // space out icons vertically, if there aren't enough to populate all rows
+ int diff = yMax - actualYIcons;
+ yBorder += (diff*(yBorder+iconXSize)) / actualYIcons;
+ }
+
+ if (y==actualYIcons-1)
+ {
+ // generating the last row of icons
+ int actualXIcons = total % xMax;
+
+ if (actualYIcons)
+ {
+ // space out icons horizontally, if there aren't enough to fill the last row
+ int diff = xMax - actualYIcons;
+
+ xBorder += (diff*(xBorder+iconYSize)) / actualXIcons;
+ }
+ }
+
+ return QRect ((iconXSize+xBorder)*x+xBorder, (iconYSize+yBorder)*y+yBorder,
+ iconXSize, iconYSize);
+}
+
+CSVWidget::SceneToolToggle::SceneToolToggle (SceneToolbar *parent, const QString& toolTip,
+ const std::string& emptyIcon)
+: SceneTool (parent), mEmptyIcon (emptyIcon), mButtonSize (parent->getButtonSize()),
+ mIconSize (parent->getIconSize()), mToolTip (toolTip), mFirst (0)
+{
+ mPanel = new QFrame (this, Qt::Popup);
+
+ mLayout = new QHBoxLayout (mPanel);
+
+ mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
+
+ mPanel->setLayout (mLayout);
+}
+
+void CSVWidget::SceneToolToggle::showPanel (const QPoint& position)
+{
+ mPanel->move (position);
+ mPanel->show();
+
+ if (mFirst)
+ mFirst->setFocus (Qt::OtherFocusReason);
+}
+
+void CSVWidget::SceneToolToggle::addButton (const std::string& icon, unsigned int id,
+ const std::string& smallIcon, const QString& name, const QString& tooltip)
+{
+ if (mButtons.size()>=9)
+ throw std::runtime_error ("Exceeded number of buttons in toggle type tool");
+
+ PushButton *button = new PushButton (QIcon (QPixmap (icon.c_str())),
+ PushButton::Type_Toggle, tooltip, mPanel);
+ button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
+ button->setIconSize (QSize (mIconSize, mIconSize));
+ button->setFixedSize (mButtonSize, mButtonSize);
+
+ mLayout->addWidget (button);
+
+ ButtonDesc desc;
+ desc.mId = id;
+ desc.mSmallIcon = smallIcon;
+ desc.mName = name;
+ desc.mIndex = mButtons.size();
+
+ mButtons.insert (std::make_pair (button, desc));
+
+ connect (button, SIGNAL (clicked()), this, SLOT (selected()));
+
+ if (mButtons.size()==1)
+ mFirst = button;
+}
+
+unsigned int CSVWidget::SceneToolToggle::getSelection() const
+{
+ unsigned int selection = 0;
+
+ for (std::map::const_iterator iter (mButtons.begin());
+ iter!=mButtons.end(); ++iter)
+ if (iter->first->isChecked())
+ selection |= iter->second.mId;
+
+ return selection;
+}
+
+void CSVWidget::SceneToolToggle::setSelection (unsigned int selection)
+{
+ for (std::map::iterator iter (mButtons.begin());
+ iter!=mButtons.end(); ++iter)
+ iter->first->setChecked (selection & iter->second.mId);
+
+ adjustToolTip();
+ adjustIcon();
+}
+
+void CSVWidget::SceneToolToggle::selected()
+{
+ std::map::const_iterator iter =
+ mButtons.find (dynamic_cast (sender()));
+
+ if (iter!=mButtons.end())
+ {
+ if (!iter->first->hasKeepOpen())
+ mPanel->hide();
+
+ adjustToolTip();
+ adjustIcon();
+
+ emit selectionChanged();
+ }
+}
diff --git a/apps/opencs/view/widget/scenetooltoggle.hpp b/apps/opencs/view/widget/scenetooltoggle.hpp
new file mode 100644
index 000000000..55e697524
--- /dev/null
+++ b/apps/opencs/view/widget/scenetooltoggle.hpp
@@ -0,0 +1,75 @@
+#ifndef CSV_WIDGET_SCENETOOL_TOGGLE_H
+#define CSV_WIDGET_SCENETOOL_TOGGLE_H
+
+#include "scenetool.hpp"
+
+#include