mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 21:56:45 +00:00 
			
		
		
		
	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