1 /** @file widget.h Base class for widgets. 2 * 3 * @authors Copyright © 2005-2017 Jaakko Keränen <jaakko.keranen@iki.fi> 4 * @authors Copyright © 2005-2014 Daniel Swanson <danij@dengine.net> 5 * 6 * @par License 7 * GPL: http://www.gnu.org/licenses/gpl.html 8 * 9 * <small>This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. This program is distributed in the hope that it 13 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15 * Public License for more details. You should have received a copy of the GNU 16 * General Public License along with this program; if not, write to the Free 17 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 * 02110-1301 USA</small> 19 */ 20 21 #ifndef LIBCOMMON_UI_WIDGET 22 #define LIBCOMMON_UI_WIDGET 23 24 #include "doomsday.h" 25 26 #include <QFlags> 27 #include <QVariant> 28 #include <de/Rectangle> 29 #include <de/String> 30 #include "common.h" 31 32 namespace common { 33 namespace menu { 34 35 class Page; 36 37 /** 38 * Base class from which all menu widgets must be derived. 39 * 40 * @ingroup menu 41 */ 42 class Widget 43 { 44 public: 45 /// Required Page is presently missing. @ingroup errors 46 DENG2_ERROR(MissingPageError); 47 48 enum Flag 49 { 50 Hidden = 0x1, 51 Disabled = 0x2, ///< Currently disabled (non-interactive). 52 Paused = 0x4, ///< Paused widgets do not tick. 53 54 Active = 0x10, ///< In the active state (meaning is widget specific). 55 Focused = 0x20, ///< Currently focused. 56 NoFocus = 0x40, ///< Can never receive focus. 57 DefaultFocus = 0x80, ///< Has focus by default. 58 PositionFixed = 0x100, ///< XY position is fixed and predefined; automatic layout does not apply. 59 LayoutOffset = 0x200, ///< Predefined XY position is applied to the dynamic layout origin. 60 61 LeftColumn = 0x400, ///< Widget is laid out to the page's left column. 62 RightColumn = 0x800, ///< Widget is laid out to the page's right column. 63 64 /// @todo We need a new dynamic id mechanism. 65 Id7 = 0x1000000, 66 Id6 = 0x2000000, 67 Id5 = 0x4000000, 68 Id4 = 0x8000000, 69 Id3 = 0x10000000, 70 Id2 = 0x20000000, 71 Id1 = 0x40000000, 72 Id0 = 0x80000000, 73 74 DefaultFlags = 0 75 }; 76 Q_DECLARE_FLAGS(Flags, Flag) 77 78 /** 79 * Logical Action identifiers. Associated with/to events which trigger user-definable 80 * callbacks according to widget-specific logic. 81 */ 82 enum Action 83 { 84 Modified, ///< The internal "modified" status was changed. 85 Deactivated, ///< Deactivated i.e., no longer active. 86 Activated, ///< Becomes "active". 87 Closed, ///< Normally means changed-state to be discarded. 88 FocusLost, ///< Loses selection "focus". 89 FocusGained, ///< Gains selection "focus". 90 }; 91 92 typedef void (*ActionCallback) (Widget &, Action); 93 typedef void (*OnTickCallback) (Widget &); 94 95 typedef int (*CommandResponder) (Widget &, menucommand_e); 96 97 public: 98 Widget(); 99 virtual ~Widget(); 100 DENG2_CAST_METHODS()101 DENG2_CAST_METHODS() 102 103 virtual void draw() const {} 104 105 /// Update the geometry for this widget. updateGeometry()106 virtual void updateGeometry() {} 107 108 /// Respond to the given (input) event @a ev. 109 /// @return @c true if the event is eaten. 110 virtual int handleEvent(event_t const &ev); 111 112 /// Respond to the given (input) event @a ev. 113 /// @return @c true if the event is eaten. 114 virtual int handleEvent_Privileged(event_t const &ev); 115 116 /// Respond to the given menu @a command. 117 /// @return @c true if the command was eaten. 118 virtual int handleCommand(menucommand_e command); 119 120 /// Configure a custom command responder to override the default mechanism. 121 Widget &setCommandResponder(CommandResponder newResponder); 122 123 /// Delegate handling of @a command to the relevant responder. 124 /// @return @c true if the command was eaten. 125 int cmdResponder(menucommand_e command); 126 127 /// Process time (the "tick") for this object. 128 virtual void tick(); 129 130 Widget &setOnTickCallback(OnTickCallback newCallback); 131 132 /** 133 * Returns @c true if a Page is presently attributed to the widget. 134 * @see page(), setPage() 135 */ 136 bool hasPage() const; 137 138 /** 139 * Change the Page attributed to the widget to @a newPage. Not that this will only 140 * affect the Widget > Page side of the relationship. 141 * 142 * @param newPage New Page to attribute. Use @c 0 to clear. Ownership unaffected. 143 * 144 * @see page(), hasPage() 145 */ 146 Widget &setPage(Page *newPage); 147 148 /** 149 * Returns a reference to the Page presently attributed to the widget. 150 * @see hasPage() 151 */ 152 Page &page() const; 153 154 /// Convenient method of returning a pointer to the presently attributed Page, if any. pagePtr()155 inline Page *pagePtr() const { return hasPage()? &page() : 0; } 156 157 /** 158 * Sets or clears one or more flags. 159 * 160 * @param flags Flags to modify. 161 * @param operation Operation to perform on the flags. 162 * 163 * @return Reference to this Widget. 164 */ 165 Widget &setFlags(Flags flagsToChange, de::FlagOp operation = de::SetFlags); 166 Flags flags() const; 167 setLeft()168 Widget &setLeft() { return setFlags(LeftColumn); } setRight()169 Widget &setRight() { return setFlags(RightColumn); } 170 isActive()171 inline bool isActive() const { return flags() & Active; } isFocused()172 inline bool isFocused() const { return flags() & Focused; } isHidden()173 inline bool isHidden() const { return flags() & Hidden; } isDisabled()174 inline bool isDisabled() const { return flags() & Disabled; } isPaused()175 inline bool isPaused() const { return flags() & Paused; } 176 177 /** 178 * Retrieve the current geometry of widget within the two-dimensioned 179 * coordinate space of the owning object. 180 * 181 * @return Rectangluar region of the parent space. 182 */ 183 de::Rectanglei &geometry(); 184 de::Rectanglei const &geometry() const; 185 186 /** 187 * Retreive the current fixed origin coordinates. 188 * 189 * @param ob MNObject-derived instance. 190 * @return Fixed origin. 191 */ 192 de::Vector2i fixedOrigin() const; fixedX()193 inline int fixedX() const { return fixedOrigin().x; } fixedY()194 inline int fixedY() const { return fixedOrigin().y; } 195 196 Widget &setFixedOrigin(de::Vector2i const &newOrigin); 197 Widget &setFixedX(int x); 198 Widget &setFixedY(int y); 199 200 Widget &setGroup(int newGroup); 201 int group() const; 202 203 Widget &setShortcut(int ddkey); 204 int shortcut(); 205 206 Widget &setColor(int newPageColor); 207 int color() const; 208 209 Widget &setFont(int newPageFont); 210 int font() const; 211 212 Widget &setHelpInfo(de::String newHelpInfo); 213 de::String const &helpInfo() const; 214 215 /** 216 * Returns @c true if a triggerable action is defined for the specified @a id. 217 */ 218 bool hasAction(Action id) const; 219 220 Widget &setAction(Action id, ActionCallback callback); 221 222 /** 223 * Trigger the ActionCallback associated with @a id, if any. 224 * @param id Unique identifier of the action. 225 */ 226 void execAction(Action id); 227 228 Widget &setUserValue(QVariant const &newValue); 229 QVariant const &userValue() const; 230 231 Widget &setUserValue2(QVariant const &newValue); 232 QVariant const &userValue2() const; 233 234 float scrollingFadeout() const; 235 float scrollingFadeout(int yTop, int yBottom) const; 236 de::Vector4f selectionFlashColor(const de::Vector4f &noFlashColor) const; 237 238 virtual void pageActivated(); 239 240 static de::String labelText(const de::String &text, const de::String &context = "Menu Label"); 241 242 private: 243 DENG2_PRIVATE(d) 244 }; 245 246 Q_DECLARE_OPERATORS_FOR_FLAGS(Widget::Flags) 247 248 } // namespace menu 249 } // namespace common 250 251 #endif // LIBCOMMON_UI_WIDGET 252