comparison mde/gui/widget/AParentWidget.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
children 9fd705793568
comparison
equal deleted inserted replaced
130:c5c38eaadb64 131:9cff74f68b84
1 /* LICENSE BLOCK
2 Part of mde: a Modular D game-oriented Engine
3 Copyright © 2007-2008 Diggory Hardy
4
5 This program is free software: you can redistribute it and/or modify it under the terms
6 of the GNU General Public License as published by the Free Software Foundation, either
7 version 2 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 See the GNU General Public License for more details.
12
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/>. */
15
16 /******************************************************************************
17 * This module contains base widget classes for parent widgets.
18 *
19 * Abstract widget classes have an 'A' prepended to the name, similar to the
20 * 'I' convention for interfaces.
21 *****************************************************************************/
22 module mde.gui.widget.AParentWidget;
23
24 public import mde.gui.widget.AChildWidget;
25 import mde.gui.exception;
26
27 debug {
28 import tango.util.log.Log : Log, Logger;
29 private Logger logger;
30 static this () {
31 logger = Log.getLogger ("mde.gui.widget.AParentWidget");
32 }
33 }
34
35 /******************************************************************************
36 * Abstract base widget classes to facilitate parent widgets.
37 *
38 * To improve code sharing, there's no separate version for parents taking a
39 * single subwidget.
40 *
41 * Parent widgets probably need to overload these functions (from AChildWidget):
42 * setup, saveChanges, setPosition, getWidget, draw, setWidth and setHeight.
43 *****************************************************************************/
44 abstract class AParentWidget : AChildWidget, IParentWidget
45 {
46 protected this (IWidgetManager mgr, IParentWidget parent, widgetID id) {
47 super (mgr, parent, id);
48 }
49
50 override bool setup (uint n, uint flags) {
51 debug (mdeWidgets) logger.trace ("AParentWidget.setup");
52 bool c = false;
53 foreach (w; subWidgets) {
54 debug assert (w, "AParentWidget: w is null");
55 c |= w.setup (n,flags);
56 }
57 return c;
58 }
59
60 override bool saveChanges () {
61 bool c = false;
62 foreach (w; subWidgets)
63 c |= w.saveChanges;
64 return c;
65 }
66
67 size_t getWidgetIndex (IChildWidget widg) {
68 foreach (i,w; subWidgets)
69 if (w is widg)
70 return i;
71
72 throw new GuiException ("getWidgetIndex: widget not found (code error)");
73 }
74
75 // Don't override; use the WIDGET_TYPE.SAFE_RECURSION flag for safe widgets.
76 //NOTE: should be override (compiler bug)
77 final void recursionCheck (widgetID a) {
78 debug assert (id !is null && parent !is null, "recursionCheck called before parent and id set");
79 if (a is id)
80 throw new GuiException ("Infite recursion of "~a);
81 parent.recursionCheck (a);
82 }
83
84 IPopupParentWidget getParentIPPW () {
85 return parent.getParentIPPW;
86 }
87
88 // Most parent widgets need to implement these, although not all
89 void minWChange (IChildWidget widget, wdim mw) {}
90 void minHChange (IChildWidget widget, wdim mh) {}
91
92 debug override void logWidgetSize () {
93 super.logWidgetSize;
94 foreach (widg; subWidgets)
95 widg.logWidgetSize;
96 }
97
98 protected:
99 IChildWidget[] subWidgets;
100 }
101
102
103 /******************************************************************************
104 * Base code for implementing IPopupParentWidget.
105 *
106 * The current intention is that an IPPW (excluding the widget manager) may
107 * only have one popup; this class follows this intention.
108 *****************************************************************************/
109 abstract class APopupParentWidget : AParentWidget, IPopupParentWidget
110 {
111 protected this (IWidgetManager mgr, IParentWidget parent, widgetID id) {
112 super (mgr, parent, id);
113
114 parentIPPW = parent.getParentIPPW;
115 }
116
117 override IPopupParentWidget getParentIPPW () {
118 return this;
119 }
120
121 override void addChildIPPW (IPopupParentWidget ippw) {
122 if (childIPPW)
123 childIPPW.removedIPPW;
124 childIPPW = ippw;
125 mgr.requestRedraw;
126 }
127 override bool removeChildIPPW (IPopupParentWidget ippw) {
128 if (childIPPW !is ippw) return false;
129 childIPPW.removedIPPW;
130 childIPPW = null;
131 mgr.requestRedraw;
132 mAIPPW = false;
133 return true;
134 }
135
136 // If this function is overriden, you MUST still call it (super.removedIPPW)!
137 // Or invariant will throw assert errors.
138 override void removedIPPW () {
139 if (childIPPW) {
140 childIPPW.removedIPPW;
141 childIPPW = null;
142 }
143 mAIPPW = false;
144 }
145
146 override void menuActive (bool mA) {
147 mAIPPW = mA;
148 if (childIPPW)
149 childIPPW.menuActive = mA;
150 }
151 override bool menuActive () {
152 return mAIPPW;
153 }
154
155 override void menuDone () { // default actions, for popup menus:
156 parentIPPW.removeChildIPPW (this); // remove self
157 parentIPPW.menuDone; // and propegate
158 }
159
160 override IChildWidget getPopupWidget (wdabs cx, wdabs cy, bool closePopup) {
161 IChildWidget ret;
162 if (childIPPW) {
163 ret = childIPPW.getPopupWidget (cx, cy, closePopup);
164 if (closePopup && ret is null) {
165 menuActive = false;
166 removeChildIPPW (childIPPW);
167 }
168 }
169 if (ret is null) {
170 if (popup.onSelf (cx, cy))
171 ret = popup.getWidget (cx, cy);
172 else if (onSelf (cx, cy))
173 ret = getWidget (cx, cy);
174 }
175 return ret;
176 }
177
178 override void drawPopup () {
179 popup.draw;
180 if (childIPPW)
181 childIPPW.drawPopup;
182 }
183
184 debug invariant () {
185 // True as long as removedIPPW gets called:
186 if (!parentIPPW.isChild (this)) {
187 assert (childIPPW is null, "APPW: childIPPW");
188 assert (mAIPPW is false, "APPW: mAIPPW");
189 }
190 }
191
192 protected:
193 // How to activate a popup:
194 /+void activatePopup (IChildWidget widget) {
195 parentIPPW.addChildIPPW (this);
196 popup = widget;
197 mgr.positionPopup (this, popup);
198 }+/
199
200 debug override bool isChild (IPopupParentWidget ippw) {
201 return ippw is childIPPW;
202 }
203
204 IPopupParentWidget parentIPPW;
205 IPopupParentWidget childIPPW;
206 IChildWidget popup;
207 bool mAIPPW;
208 }