1167 WP(w, querystr_d).wnd_num = window_number; |
1167 WP(w, querystr_d).wnd_num = window_number; |
1168 WP(w, querystr_d).afilter = afilter; |
1168 WP(w, querystr_d).afilter = afilter; |
1169 InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, realmaxlen, maxwidth); |
1169 InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, realmaxlen, maxwidth); |
1170 } |
1170 } |
1171 |
1171 |
|
1172 |
|
1173 enum QueryWidgets { |
|
1174 QUERY_WIDGET_CAPTION = 1, |
|
1175 QUERY_WIDGET_NO = 3, |
|
1176 QUERY_WIDGET_YES |
|
1177 }; |
|
1178 |
|
1179 |
|
1180 typedef struct query_d { |
|
1181 StringID message; ///< message shown for query window |
|
1182 uint32 params[20]; ///< local copy of _decode_parameters |
|
1183 void (*proc)(Window*, bool); ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise |
|
1184 bool calledback; ///< has callback been executed already (internal usage for WE_DESTROY event) |
|
1185 } query_d; |
|
1186 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(query_d)); |
|
1187 |
|
1188 |
1172 static void QueryWndProc(Window *w, WindowEvent *e) |
1189 static void QueryWndProc(Window *w, WindowEvent *e) |
1173 { |
1190 { |
|
1191 query_d *q = &WP(w, query_d); |
|
1192 |
1174 switch (e->event) { |
1193 switch (e->event) { |
1175 case WE_PAINT: |
1194 case WE_PAINT: |
1176 SetDParam(0, WP(w, query_d).caption); |
1195 COPY_IN_DPARAM(0, q->params, lengthof(q->params)); |
1177 DrawWindowWidgets(w); |
1196 DrawWindowWidgets(w); |
1178 |
1197 COPY_IN_DPARAM(0, q->params, lengthof(q->params)); |
1179 DrawStringMultiCenter(90, 38, WP(w, query_d).message, 178); |
1198 |
1180 break; |
1199 DrawStringMultiCenter(w->width / 2, (w->height / 2) - 10, q->message, w->width); |
1181 |
1200 break; |
1182 case WE_CLICK: |
1201 |
1183 switch (e->we.click.widget) { |
1202 case WE_CLICK: |
1184 case 3: |
1203 switch (e->we.click.widget) { |
1185 case 4: |
1204 case QUERY_WIDGET_YES: |
1186 WP(w, query_d).calledback = true; |
1205 q->calledback = true; |
1187 if (WP(w, query_d).ok_cancel_callback != NULL) WP(w, query_d).ok_cancel_callback(e->we.click.widget == 4); |
1206 if (q->proc != NULL) q->proc(w->parent, true); |
1188 DeleteWindow(w); |
1207 /* Fallthrough */ |
1189 break; |
1208 case QUERY_WIDGET_NO: |
1190 } |
1209 DeleteWindow(w); |
1191 break; |
1210 break; |
1192 |
1211 } |
1193 case WE_MOUSELOOP: |
1212 break; |
1194 if (!FindWindowById(WP(w, query_d).wnd_class, WP(w, query_d).wnd_num)) DeleteWindow(w); |
1213 |
1195 break; |
1214 case WE_KEYPRESS: /* ESC closes the window, Enter confirms the action */ |
1196 |
1215 switch (e->we.keypress.keycode) { |
1197 case WE_DESTROY: |
1216 case WKC_RETURN: |
1198 if (!WP(w, query_d).calledback && WP(w, query_d).ok_cancel_callback != NULL) WP(w, query_d).ok_cancel_callback(false); |
1217 case WKC_NUM_ENTER: |
1199 break; |
1218 q->calledback = true; |
1200 } |
1219 if (q->proc != NULL) q->proc(w->parent, true); |
1201 } |
1220 /* Fallthrough */ |
|
1221 case WKC_ESC: |
|
1222 e->we.keypress.cont = false; |
|
1223 DeleteWindow(w); |
|
1224 break; |
|
1225 } |
|
1226 break; |
|
1227 |
|
1228 case WE_DESTROY: /* Call callback function (if any) on window close if not yet called */ |
|
1229 if (!q->calledback && q->proc != NULL) q->proc(w->parent, false); |
|
1230 break; |
|
1231 } |
|
1232 } |
|
1233 |
1202 |
1234 |
1203 static const Widget _query_widgets[] = { |
1235 static const Widget _query_widgets[] = { |
1204 { WWT_CLOSEBOX, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
1236 { WWT_CLOSEBOX, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
1205 { WWT_CAPTION, RESIZE_NONE, 4, 11, 179, 0, 13, STR_012D, STR_NULL}, |
1237 { WWT_CAPTION, RESIZE_NONE, 4, 11, 209, 0, 13, STR_NULL, STR_NULL}, |
1206 { WWT_PANEL, RESIZE_NONE, 4, 0, 179, 14, 91, 0x0, STR_NULL}, |
1238 { WWT_PANEL, RESIZE_NONE, 4, 0, 209, 14, 81, 0x0, /*OVERRIDE*/STR_NULL}, |
1207 { WWT_TEXTBTN, RESIZE_NONE, 12, 25, 84, 72, 83, STR_012E_CANCEL, STR_NULL}, |
1239 {WWT_PUSHTXTBTN, RESIZE_NONE, 3, 20, 90, 62, 73, STR_00C9_NO, STR_NULL}, |
1208 { WWT_TEXTBTN, RESIZE_NONE, 12, 95, 154, 72, 83, STR_012F_OK, STR_NULL}, |
1240 {WWT_PUSHTXTBTN, RESIZE_NONE, 3, 120, 190, 62, 73, STR_00C8_YES, STR_NULL}, |
1209 { WIDGETS_END }, |
1241 { WIDGETS_END }, |
1210 }; |
1242 }; |
1211 |
1243 |
1212 static const WindowDesc _query_desc = { |
1244 static const WindowDesc _query_desc = { |
1213 WDP_CENTER, WDP_CENTER, 180, 92, |
1245 WDP_CENTER, WDP_CENTER, 210, 82, |
1214 WC_OK_CANCEL_QUERY, 0, |
1246 WC_CONFIRM_POPUP_QUERY, 0, |
1215 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, |
1247 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_DEF_WIDGET | WDF_MODAL, |
1216 _query_widgets, |
1248 _query_widgets, |
1217 QueryWndProc |
1249 QueryWndProc |
1218 }; |
1250 }; |
1219 |
1251 |
1220 void ShowQuery(StringID caption, StringID message, void (*ok_cancel_callback)(bool ok_clicked), WindowClass window_class, WindowNumber window_number) |
1252 /** Show a modal confirmation window with standard 'yes' and 'no' buttons |
1221 { |
1253 * The window is aligned to the centre of its parent. |
1222 Window *w; |
1254 * NOTE: You cannot use BindCString as parameter for this window! |
1223 |
1255 * @param caption string shown as window caption |
1224 DeleteWindowById(WC_OK_CANCEL_QUERY, 0); |
1256 * @param message string that will be shown for the window |
1225 |
1257 * @param parent pointer to parent window, if this pointer is NULL the parent becomes |
1226 w = AllocateWindowDesc(&_query_desc); |
1258 * the main window WC_MAIN_WINDOW |
1227 |
1259 * @param x,y coordinates to show the window at |
1228 WP(w, query_d).caption = caption; |
1260 * @param yes_no_callback callback function called when window is closed through any button */ |
1229 WP(w, query_d).message = message; |
1261 void ShowQuery(StringID caption, StringID message, Window *parent, void (*callback)(Window*, bool)) |
1230 WP(w, query_d).wnd_class = window_class; |
1262 { |
1231 WP(w, query_d).wnd_num = window_number; |
1263 Window *w = AllocateWindowDesc(&_query_desc); |
1232 WP(w, query_d).ok_cancel_callback = ok_cancel_callback; |
1264 if (w == NULL) return; |
1233 WP(w, query_d).calledback = false; |
1265 |
|
1266 if (parent == NULL) parent = FindWindowById(WC_MAIN_WINDOW, 0); |
|
1267 w->parent = parent; |
|
1268 w->left = parent->left + (parent->width / 2) - (w->width / 2); |
|
1269 w->top = parent->top + (parent->height / 2) - (w->height / 2); |
|
1270 |
|
1271 /* Create a backup of the variadic arguments to strings because it will be |
|
1272 * overridden pretty often. We will copy these back for drawing */ |
|
1273 COPY_OUT_DPARAM(WP(w, query_d).params, 0, lengthof(WP(w, query_d).params)); |
|
1274 w->widget[QUERY_WIDGET_CAPTION].data = caption; |
|
1275 WP(w, query_d).message = message; |
|
1276 WP(w, query_d).proc = callback; |
|
1277 WP(w, query_d).calledback = false; |
1234 } |
1278 } |
1235 |
1279 |
1236 |
1280 |
1237 static const Widget _load_dialog_widgets[] = { |
1281 static const Widget _load_dialog_widgets[] = { |
1238 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
1282 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |