comparison mde/gui/widget/PopupMenu.d @ 131:9cff74f68b84

Major revisions to popup handling. Buttons can close menus now, plus some smaller impovements. Removed Widget module. Moved Widget.AWidget to AChildWidget.AChildWidget and Widget.AParentWidget to AParentWidget.AParentWidget. Removed ASingleParentWidget to improve code sharing. AChildWidget doesn't implement IParentWidget like AWidget did. New IPopupParentWidget extending IParentWidget for the WM and some widgets to handle popups. Cut old popup management code. New underMouse() function replacing highlight(); called on all widgets. Separate menu-popup and button widgets aren't needed for menus now. Functions returning content widgets have been moved to their own module. Cleaned up jobs.txt. Switched to 80 line length for Ddoc.
author Diggory Hardy <diggory.hardy@gmail.com>
date Wed, 21 Jan 2009 13:01:40 +0000
parents 5b37d0400732
children 9fd705793568
comparison
equal deleted inserted replaced
130:c5c38eaadb64 131:9cff74f68b84
11 See the GNU General Public License for more details. 11 See the GNU General Public License for more details.
12 12
13 You should have received a copy of the GNU General Public License 13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15 15
16 /************************************************************************************************* 16 /******************************************************************************
17 * Pop-up menus based on content structures. 17 * Pop-up menus based on content structures.
18 *************************************************************************************************/ 18 *****************************************************************************/
19 module mde.gui.widget.PopupMenu; 19 module mde.gui.widget.PopupMenu;
20 20
21 import mde.gui.widget.Widget; 21 import mde.gui.widget.AParentWidget;
22 import mde.gui.widget.TextWidget;
23 import mde.gui.widget.layout;
24 22
25 import mde.content.miscContent; 23 import mde.content.miscContent;
26 import mde.gui.exception; 24 import mde.gui.exception;
27 25
28 debug { 26 debug {
31 static this () { 29 static this () {
32 logger = Log.getLogger ("mde.gui.widget.PopupMenu"); 30 logger = Log.getLogger ("mde.gui.widget.PopupMenu");
33 } 31 }
34 } 32 }
35 33
36 /************************************************************************************************* 34 /******************************************************************************
37 * Widget which pops up a menu based on a content. 35 * Widget which pops up a menu based on a content.
38 *************************************************************************************************/ 36 *****************************************************************************/
39 class PopupMenuWidget : AParentSingleWidget 37 class PopupMenuWidget : APopupParentWidget
40 { 38 {
41 this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) { 39 this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) {
42 content = c; 40 content = c;
43 WDCMinCheck (data, 1,1, content); 41 WDCMinCheck (data, 1,1, content);
44 super (mgr, parent, id); 42 super (mgr, parent, id);
45 43
46 subWidget = mgr.makeWidget (this, data.strings[0], content); 44 popup = mgr.makeWidget (this, data.strings[0], content);
45 subWidgets = [popup];
47 46
48 adapter = mgr.renderer.getAdapter; 47 adapter = mgr.renderer.getAdapter;
49 adapter.text = content.toString (1); 48 adapter.text = content.toString (1);
50 adapter.getDimensions (mw, mh); 49 adapter.getDimensions (mw, mh);
51 w = mw; 50 w = mw;
52 h = mh; 51 h = mh;
53 } 52 }
54 53
55 override int clickEvent (wdabs, wdabs, ubyte b, bool state) { 54 override int clickEvent (wdabs, wdabs, ubyte b, bool state) {
56 if (b == 1 && state == true) { 55 if (b == 1 && state == true) {
57 // If active, the popup is closed by WidgetManager since the click isn't on the popup.
58 if (!pushed) { 56 if (!pushed) {
59 pushed = true; 57 parentIPPW.addChildIPPW (this);
60 mgr.addPopup (this, subWidget); // causes redraw 58 parentIPPW.menuActive = true;
61 mgr.addClickCallback (&openMenuCallback); // prevents first up-click from closing menu, if on self. 59 mgr.positionPopup (this, popup);
62 } 60 pushed = true;
61 } else {
62 // NOTE: perhaps shouldn't do anything when
63 // parentIPPW.parentIPPW.menuActive
64 // (this causes funny behaviour when clicking a submenu):
65 parentIPPW.removeChildIPPW (this);
66 }
63 } 67 }
64 return 0; 68 return 0;
65 } 69 }
66 70
67 override void popupClose () { 71 override void removedIPPW () {
72 super.removedIPPW;
68 pushed = false; 73 pushed = false;
69 } 74 }
70 override bool popupParentClick () { 75
71 pushed = false; 76 override void underMouse (bool state) {
72 return true; 77 if (state && !pushed && parentIPPW.menuActive) {
78 parentIPPW.addChildIPPW (this);
79 menuActive = true;
80 mgr.positionPopup (this, popup, 1); // causes redraw
81 pushed = true;
82 }
73 } 83 }
74 84
75 override void draw () { 85 override void draw () {
76 mgr.renderer.drawButton (x,y, w,h, pushed); 86 mgr.renderer.drawButton (x,y, w,h, pushed);
77 adapter.draw (x,y); 87 adapter.draw (x,y);
78 } 88 }
79 89
80 protected: 90 protected:
81 bool openMenuCallback (wdabs cx, wdabs cy, ubyte b, bool state) {
82 if (b == 1 && state == false) { // receive first up-click
83 mgr.removeCallbacks (cast(void*) this);
84 if (cx >= x && cx < x+w && cy >= y && cy < y+h)
85 return true; // up-click is on self; don't close the menu
86 }
87 return false;
88 }
89 bool pushed = false; 91 bool pushed = false;
90 IRenderer.TextAdapter adapter; 92 IRenderer.TextAdapter adapter;
91 IContent content; 93 IContent content;
92 } 94 }
93
94 /*************************************************************************************************
95 * Widget which pops up a sub-menu based on a content on mouse-over.
96 *************************************************************************************************/
97 class SubMenuWidget : PopupMenuWidget
98 {
99 this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) {
100 super (mgr, parent, id, data, c);
101 }
102
103 override int clickEvent (wdabs, wdabs, ubyte b, bool state) {
104 return 0;
105 }
106
107 override void highlight (bool state) {
108 if (state && !pushed) {
109 pushed = true;
110 mgr.addPopup (this, subWidget, 1); // causes redraw
111 }
112 }
113 }
114
115 /*************************************************************************************************
116 * A function which returns a ContentListWidget or MenuButtonContentWidget.
117 *************************************************************************************************/
118 IChildWidget flatMenuContent (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) {
119 if (c is null) throw new ContentException;
120 if (cast(IContentList) c)
121 return new ContentListWidget(mgr,parent,id,data,c);
122 if (cast(EventContent) c)
123 return new MenuButtonContentWidget(mgr,parent,id,data,c);
124 // generic uneditable option
125 return new DisplayContentWidget(mgr,parent,id,data,c);
126 }
127
128 /*************************************************************************************************
129 * A function which returns a SubMenuWidget or MenuButtonContentWidget.
130 *************************************************************************************************/
131 IChildWidget subMenuContent (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) {
132 if (c is null) throw new ContentException;
133 if (cast(IContentList) c)
134 return new SubMenuWidget(mgr,parent,id,data,c);
135 if (cast(EventContent) c)
136 return new MenuButtonContentWidget(mgr,parent,id,data,c);
137 // generic uneditable option
138 return new DisplayContentWidget(mgr,parent,id,data,c);
139 }
140
141 /*************************************************************************************************
142 * A menu content-button, like ButtonContentWidget, but which can be activated with the up-click.
143 *************************************************************************************************/
144 class MenuButtonContentWidget : ATextWidget
145 {
146 this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData, IContent c) {
147 content = cast(EventContent) c;
148 if (content is null) throw new ContentException (this);
149 adapter = mgr.renderer.getAdapter ();
150 super (mgr, parent, id);
151 }
152
153 override bool setup (uint n, uint flags) {
154 if (!(flags & 3)) return false; // string or renderer (and possibly font) changed
155 adapter.text = content.toString(1);
156 return super.setup (n, 3); // force redimensioning
157 }
158
159 override int clickEvent (wdabs, wdabs, ubyte b, bool state) {
160 if (b == 1) { // on up or down click
161 pushed = false;
162 mgr.requestRedraw;
163 content.endEvent;
164 }
165 return 0;
166 }
167
168 override void highlight (bool state) {
169 pushed = state;
170 }
171
172 override void draw () {
173 mgr.renderer.drawButton (x,y, w,h, pushed);
174 adapter.draw (x,y);
175 }
176
177 protected:
178 EventContent content;
179 bool pushed;
180 }