forked from mirror/openmw-tes3mp
added scene toolbar toggle widget
This commit is contained in:
parent
bb9e5f9eb1
commit
71ce78f949
5 changed files with 295 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -26,6 +26,14 @@ void CSVWidget::PushButton::setExtendedToolTip (const QString& text)
|
|||
"<p>(left click to activate,"
|
||||
"<br>shift-left click to activate and keep panel open)";
|
||||
|
||||
case Type_Toggle:
|
||||
|
||||
tooltip += "<p>(left click to ";
|
||||
tooltip += isChecked() ? "disable" : "enable";
|
||||
tooltip += "<p>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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
204
apps/opencs/view/widget/scenetooltoggle.cpp
Normal file
204
apps/opencs/view/widget/scenetooltoggle.cpp
Normal file
|
@ -0,0 +1,204 @@
|
|||
|
||||
#include "scenetooltoggle.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QFrame>
|
||||
#include <QIcon>
|
||||
#include <QPainter>
|
||||
|
||||
#include "scenetoolbar.hpp"
|
||||
#include "pushbutton.hpp"
|
||||
|
||||
void CSVWidget::SceneToolToggle::adjustToolTip()
|
||||
{
|
||||
QString toolTip = mToolTip;
|
||||
|
||||
toolTip += "<p>Currently enabled: ";
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (std::map<PushButton *, ButtonDesc>::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 += "<p>(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<PushButton *, ButtonDesc>::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<PushButton *, ButtonDesc>::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<PushButton *, ButtonDesc>::iterator iter (mButtons.begin());
|
||||
iter!=mButtons.end(); ++iter)
|
||||
iter->first->setChecked (selection & iter->second.mId);
|
||||
|
||||
adjustToolTip();
|
||||
adjustIcon();
|
||||
}
|
||||
|
||||
void CSVWidget::SceneToolToggle::selected()
|
||||
{
|
||||
std::map<PushButton *, ButtonDesc>::const_iterator iter =
|
||||
mButtons.find (dynamic_cast<PushButton *> (sender()));
|
||||
|
||||
if (iter!=mButtons.end())
|
||||
{
|
||||
if (!iter->first->hasKeepOpen())
|
||||
mPanel->hide();
|
||||
|
||||
adjustToolTip();
|
||||
adjustIcon();
|
||||
|
||||
emit selectionChanged();
|
||||
}
|
||||
}
|
75
apps/opencs/view/widget/scenetooltoggle.hpp
Normal file
75
apps/opencs/view/widget/scenetooltoggle.hpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#ifndef CSV_WIDGET_SCENETOOL_TOGGLE_H
|
||||
#define CSV_WIDGET_SCENETOOL_TOGGLE_H
|
||||
|
||||
#include "scenetool.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
class QHBoxLayout;
|
||||
class QRect;
|
||||
|
||||
namespace CSVWidget
|
||||
{
|
||||
class SceneToolbar;
|
||||
class PushButton;
|
||||
|
||||
///< \brief Multi-Toggle tool
|
||||
class SceneToolToggle : public SceneTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
struct ButtonDesc
|
||||
{
|
||||
unsigned int mId;
|
||||
std::string mSmallIcon;
|
||||
QString mName;
|
||||
int mIndex;
|
||||
};
|
||||
|
||||
std::string mEmptyIcon;
|
||||
QWidget *mPanel;
|
||||
QHBoxLayout *mLayout;
|
||||
std::map<PushButton *, ButtonDesc> mButtons; // widget, id
|
||||
int mButtonSize;
|
||||
int mIconSize;
|
||||
QString mToolTip;
|
||||
PushButton *mFirst;
|
||||
|
||||
void adjustToolTip();
|
||||
|
||||
void adjustIcon();
|
||||
|
||||
QRect getIconBox (int index) const;
|
||||
|
||||
public:
|
||||
|
||||
SceneToolToggle (SceneToolbar *parent, const QString& toolTip,
|
||||
const std::string& emptyIcon);
|
||||
|
||||
virtual void showPanel (const QPoint& position);
|
||||
|
||||
/// \attention After the last button has been added, setSelection must be called at
|
||||
/// least once to finalise the layout.
|
||||
///
|
||||
/// \note The layout algorithm can not handle more than 9 buttons. To prevent this An
|
||||
/// attempt to add more will result in an exception being thrown.
|
||||
/// The small icons will be sized at (x-4)/3 (where x is the main icon size).
|
||||
void addButton (const std::string& icon, unsigned int id,
|
||||
const std::string& smallIcon, const QString& name, const QString& tooltip = "");
|
||||
|
||||
unsigned int getSelection() const;
|
||||
|
||||
/// \param or'ed button IDs. IDs that do not exist will be ignored.
|
||||
void setSelection (unsigned int selection);
|
||||
|
||||
signals:
|
||||
|
||||
void selectionChanged();
|
||||
|
||||
private slots:
|
||||
|
||||
void selected();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue