1 // CoMET - The Crimson Fields Map Editing Tool
2 // Copyright (C) 2002-2007 Jens Granseuer
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
19 ////////////////////////////////////////////////////////////////////////
20 // eventwindow.cpp
21 ///////////////////////////////////////////////////////////////////////
22 
23 #include "eventwindow.h"
24 #include "extwindow.h"
25 #include "extwindow2.h"
26 #include "uiaux.h"
27 
28 extern const char *player2_labels[];
29 extern const char *dir_labels[];
30 extern const char *size_labels[];
31 extern const char *xp_labels[];
32 static const char *uselect_labels[] = { "Single Unit", "Unit Type", 0 };
33 
34 ////////////////////////////////////////////////////////////////////////
35 // NAME       : EdEventGenericWindow::EdEventGenericWindow
36 // DESCRIPTION: This window allows modification of the fields common to
37 //              all event types, and also offers links to event-specific
38 //              options.
39 // PARAMETERS : event   - event to edit
40 //              mission - current mission
41 //              view    - pointer to the window's view
42 // RETURNS    : -
43 ////////////////////////////////////////////////////////////////////////
44 
EdEventGenericWindow(Event & event,Mission & mission,View * view)45 EdEventGenericWindow::EdEventGenericWindow( Event &event,
46        Mission &mission, View *view ) :
47        Window(WIN_CENTER, view), event(event), mission(mission) {
48   // calculate dimensions
49   SetSize( MIN(sfont->Width() * 35 + 20, view->Width()),
50            MIN(sfont->Height() * 12 + 125, view->Height()) );
51 
52   unsigned short wdh = sfont->Height() + 8, wdx, wdy = 5;
53   Widget *wd;
54   char buf[48] = "";
55 
56   wd = new NumberWidget( 0, sfont->Width() * 2 + 10, wdy,
57        sfont->Width() * 6, wdh, event.ID(),
58        0, 32767, WIDGET_STR_CONST|WIDGET_ALIGN_LEFT, "ID", this );
59 
60   wdx = wd->LeftEdge() + wd->Width() + sfont->TextWidth("Player") + 10;
61 
62   wd = new CheckboxWidget( B_ID_DISABLED,
63        w - 5 - DEFAULT_CBW_SIZE, wdy + (wdh - DEFAULT_CBW_SIZE)/2,
64        DEFAULT_CBW_SIZE, DEFAULT_CBW_SIZE, event.Flags() & EFLAG_DISABLED,
65        WIDGET_STYLE_GFX|WIDGET_STYLE_NOBORDER|WIDGET_ALIGN_LEFT,
66        "_Disabled", this );
67   wd->SetHook( this );
68 
69   wd = new CycleWidget( B_ID_PLAYER, wdx, wdy,
70        wd->LeftEdge() - wdx - 15 - sfont->TextWidth("Disabled"), wdh,
71        0, "_Player", event.Player(), player2_labels, this );
72   wd->SetHook( this );
73 
74   wdy += wd->Height() + 5;
75   wd = new ButtonWidget( B_ID_TITLE, 5, wdy,
76        sfont->Width() * 9 + 10, wdh, 0, "Msg _Title", this );
77   wd->SetHook( this );
78 
79   wdx = wd->LeftEdge() + wd->Width() + 5;
80   e_title = new StringWidget( 0, wdx, wdy, w - wdx - 5, wdh,
81             (mission.GetMessage(event.Title()) ?
82              mission.GetMessage(event.Title()) : ""),
83             30, WIDGET_STR_CONST, NULL, this );
84 
85   wdy += wd->Height() + 5;
86   wd = new ButtonWidget( B_ID_MSG, 5, wdy, w - 10, wdh,
87        0, "Set Event _Message", this );
88   wd->SetHook( this );
89 
90   wdy += wd->Height() + 5;
91   e_msg = new TextScrollWidget( 0, 5, wdy, w - 10, sfont->Height() * 5,
92           (mission.GetMessage(event.Message()) ?
93            mission.GetMessage(event.Message()) : ""),
94           0, NULL, this );
95 
96   wdy += e_msg->Height() + 5;
97   wd = new ButtonWidget( B_ID_TRIGGER, 5, wdy,
98        sfont->Width() * 12 + 10, wdh, 0,
99        "Edit T_rigger", this );
100   wd->SetHook( this );
101 
102   wdy += wd->Height() + 5;
103   wd = new ButtonWidget( B_ID_EVENT, 5, wdy, wd->Width(), wdh,
104        0, "Edit _Event", this );
105   wd->SetHook( this );
106 
107   wdy += wd->Height() + 5;
108   wd = new ButtonWidget( B_ID_DEPEND, 5, wdy, wd->Width(), wdh,
109        0, "Depends o_n", this );
110   wd->SetHook( this );
111 
112   wdx = wd->LeftEdge() + wd->Width() + 5;
113   if ( event.Dependency() >= 0 ) {
114     Event *e = mission.GetEventByID( event.Dependency() );
115     if ( e ) sprintf( buf, "%s (%d)", e->Name(), e->ID() );
116   }
117   e_depends = new StringWidget( 0, wdx, wdy, w - wdx - 5, wdh,
118               buf, 47, WIDGET_STR_CONST, NULL, this );
119 
120   wdy += wd->Height() + 5;
121   wd = new ButtonWidget( B_ID_DISCARD, 5, wdy, wd->Width(), wdh,
122        0, "D_iscards", this );
123   wd->SetHook( this );
124 
125   buf[0] = '\0';
126   if ( event.Discard() >= 0 ) {
127     Event *e = mission.GetEventByID( event.Discard() );
128     if ( e ) sprintf( buf, "%s (%d)", e->Name(), e->ID() );
129   }
130   e_discards = new StringWidget( 0, wdx, wdy,
131                e_depends->Width(), wdh, buf, 47,
132                WIDGET_STR_CONST, NULL, this );
133 
134   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
135                     WIDGET_DEFAULT, "_OK", this );
136 
137   Draw();
138   Show();
139 }
140 
141 ////////////////////////////////////////////////////////////////////////
142 // NAME       : EdEventGenericWindow::Draw
143 // DESCRIPTION: Draw the window.
144 // PARAMETERS : -
145 // RETURNS    : -
146 ////////////////////////////////////////////////////////////////////////
147 
Draw(void)148 void EdEventGenericWindow::Draw( void ) {
149   Window::Draw();
150 
151   unsigned short lblx = sfont->Width() * 12 + 20,
152                  lbly = e_msg->TopEdge() + e_msg->Height() + 9;
153 
154   sfont->Write( ':', this, lblx, lbly );
155   sfont->Write( event.TriggerName(), this, lblx + sfont->Width() * 2, lbly );
156 
157   lbly += sfont->Height() + 13;
158   sfont->Write( ':', this, lblx, lbly );
159   sfont->Write( event.Name(), this, lblx + sfont->Width() * 2, lbly );
160 }
161 
162 ////////////////////////////////////////////////////////////////////////
163 // NAME       : EdEventGenericWindow::WidgetActivated
164 // DESCRIPTION: React to user actions.
165 // PARAMETERS : widget - activated widget
166 //              win    - window containing the button
167 // RETURNS    : GUI status
168 ////////////////////////////////////////////////////////////////////////
169 
WidgetActivated(Widget * widget,Window * win)170 GUI_Status EdEventGenericWindow::WidgetActivated( Widget *widget, Window *win ) {
171   TLWNode *n;
172 
173   switch ( widget->ID() ) {
174   case B_ID_TITLE:
175     TLWListBuilder::BuildMsgList( mission.GetMessages(), tlist );
176     new ListSelectWindow( "Select event title", tlist, event.Title(),
177                           true, this, B_ID_TITLE_OK, view );
178     break;
179 
180   case B_ID_TITLE_OK:
181     n = static_cast<ListSelectWindow *>(win)->Selected();
182     event.SetTitle( n ? n->ID() : -1 );
183     e_title->SetString( n ? n->Name() : NULL, true );
184     tlist.Clear();
185     break;
186 
187   case B_ID_MSG:
188     TLWListBuilder::BuildMsgList( mission.GetMessages(), tlist );
189     new ListSelectWindow( "Select event message", tlist, event.Message(),
190                           true, this, B_ID_MSG_OK, view );
191     break;
192 
193   case B_ID_MSG_OK:
194     n = static_cast<ListSelectWindow *>(win)->Selected();
195     event.SetMessage( n ? n->ID() : -1 );
196     e_msg->SetText( n ? mission.GetMessage(n->ID()) : NULL );
197     e_msg->Draw();
198     e_msg->Show();
199     tlist.Clear();
200     break;
201 
202   case B_ID_DEPEND:
203     TLWListBuilder::BuildEventList( mission.GetEvents(), tlist );
204     new ListSelectWindow( "Select event", tlist, event.Dependency(),
205                           true, this, B_ID_DEPEND_OK, view );
206     break;
207 
208   case B_ID_DEPEND_OK:
209     n = static_cast<ListSelectWindow *>(win)->Selected();
210     event.SetDependency( n ? n->ID() : -1 );
211     e_depends->SetString( n ? n->Name() : NULL );
212     tlist.Clear();
213     break;
214 
215   case B_ID_DISCARD:
216     TLWListBuilder::BuildEventList( mission.GetEvents(), tlist );
217     new ListSelectWindow( "Select event", tlist, event.Discard(),
218                           true, this, B_ID_DISCARD_OK, view );
219     break;
220 
221   case B_ID_DISCARD_OK:
222     n = static_cast<ListSelectWindow *>(win)->Selected();
223     event.SetDiscard( n ? n->ID() : -1 );
224     e_discards->SetString( n ? n->Name() : NULL );
225     tlist.Clear();
226     break;
227 
228   case B_ID_TRIGGER:
229     switch ( event.Trigger() ) {
230     case ETRIGGER_HAVE_BUILDING:
231       new EdTrigHaveShopWindow( event, mission, view ); break;
232     case ETRIGGER_HAVE_CRYSTALS:
233       new EdTrigHaveCrystalsWindow( event, mission, view ); break;
234     case ETRIGGER_HAVE_UNIT:
235       new EdTrigHaveUnitWindow( event, mission, view ); break;
236     case ETRIGGER_TIMER:
237       new EdTrigTimerWindow( event, view ); break;
238     case ETRIGGER_UNIT_DESTROYED:
239       new EdTrigUnitDestroyedWindow( event, mission, view ); break;
240     case ETRIGGER_UNIT_POSITION:
241       new EdTrigUnitPositionWindow( event, mission, view ); break;
242     case ETRIGGER_HANDICAP:
243       new EdTrigHandicapWindow( event, view ); break;
244     default:
245       new NoteWindow("Sorry", "Not yet implemented", 0, view);
246     }
247     break;
248 
249   case B_ID_EVENT:
250     switch ( event.Type() ) {
251     case EVENT_CONFIGURE:
252       new EdEventConfigureWindow( event, mission, view ); break;
253     case EVENT_CREATE_UNIT:
254       new EdEventCreateUnitWindow( event, mission, view ); break;
255     case EVENT_DESTROY_UNIT:
256       new EdEventDestroyUnitWindow( event, mission, view ); break;
257     case EVENT_MANIPULATE_EVENT:
258       new EdEventManipEventWindow( event, mission, view ); break;
259     case EVENT_MESSAGE:
260       new EdEventMessageWindow( event, mission, view ); break;
261     case EVENT_MINING:
262       new EdEventMiningWindow( event, mission, view ); break;
263     case EVENT_RESEARCH:
264       new EdEventResearchWindow( event, mission, view ); break;
265     case EVENT_SCORE:
266       new EdEventScoreWindow( event, mission, view ); break;
267     case EVENT_SET_HEX:
268       new EdEventSetHexWindow( event, mission, view ); break;
269     case EVENT_SET_TIMER:
270       new EdEventSetTimerWindow( event, mission, view ); break;
271     default:
272       new NoteWindow("Sorry", "Not yet implemented", 0, view);
273     }
274     break;
275   case B_ID_PLAYER:
276     event.SetPlayer( static_cast<CycleWidget *>(widget)->GetValue() );
277     break;
278   case B_ID_DISABLED:
279     event.ToggleFlags( EFLAG_DISABLED );
280   }
281 
282   return GUI_OK;
283 }
284 
285 ////////////////////////////////////////////////////////////////////////
286 // NAME       : EdEventConfigureWindow::EdEventConfigureWindow
287 // DESCRIPTION: This window allows configuration of a NEXT_MAP event.
288 // PARAMETERS : event   - event to edit
289 //              mission - current mission
290 //              view    - pointer to the window's view
291 // RETURNS    : -
292 ////////////////////////////////////////////////////////////////////////
293 
EdEventConfigureWindow(Event & event,Mission & mission,View * view)294 EdEventConfigureWindow::EdEventConfigureWindow( Event &event,
295                       Mission &mission, View *view ) :
296       Window(WIN_CENTER, view), event(event), mission(mission) {
297   static const char *setting_labels[] = {
298          "Briefing Player 1", "Briefing Player 2", "Next Map", 0 };
299 
300   SetSize( MIN(sfont->Width() * 20 + 15, view->Width()),
301            sfont->Height() * 3 + 40 );
302 
303   unsigned short wdh = sfont->Height() + 8, wdx;
304   Widget *wd;
305 
306   wdx = 10 + sfont->TextWidth( "Setting" );
307   wd = new CycleWidget( B_ID_SETTING, wdx, 5, w - 5 - wdx, wdh,
308        0, "_Setting", event.GetData(0), setting_labels, this );
309   wd->SetHook( this );
310 
311   e_msg_but = new ButtonWidget( B_ID_MSG,
312        5, wd->TopEdge() + wd->Height() + 5,
313        sfont->Width() * 7 + 10, wdh,
314        event.GetData(0) == 2 ? WIDGET_DISABLED : 0,
315        "_Message", this );
316   e_msg_but->SetHook( this );
317 
318   wdx = e_msg_but->LeftEdge() + e_msg_but->Width() + 5;
319   e_msg = new StringWidget( S_ID_VALUE, wdx, e_msg_but->TopEdge(),
320           w - wdx - 5, wdh, GetValueString(), 30,
321           event.GetData(0) == 2 ? 0 : WIDGET_STR_CONST,
322           NULL, this );
323   e_msg->SetHook( this );
324 
325   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
326                     WIDGET_DEFAULT, "_OK", this );
327   Draw();
328   Show();
329 }
330 
331 ////////////////////////////////////////////////////////////////////////
332 // NAME       : EdEventConfigureWindow::WidgetActivated
333 // DESCRIPTION: React to user actions.
334 // PARAMETERS : widget - activated widget
335 //              win    - window containing the widget
336 // RETURNS    : GUI status
337 ////////////////////////////////////////////////////////////////////////
338 
WidgetActivated(Widget * widget,Window * win)339 GUI_Status EdEventConfigureWindow::WidgetActivated( Widget *widget, Window *win ) {
340   switch( widget->ID() ) {
341   case B_ID_SETTING:
342     event.SetData( 0, static_cast<CycleWidget *>(widget)->GetValue() );
343     if ( event.GetData(0) == 2 ) {
344       e_msg_but->Disable();
345       e_msg->UnsetFlags( WIDGET_STR_CONST );
346     } else {
347       e_msg_but->Enable();
348       e_msg->SetFlags( WIDGET_STR_CONST );
349     }
350     e_msg->SetString( GetValueString() );
351     Draw();
352     Show();
353     break;
354   case B_ID_MSG:
355     TLWListBuilder::BuildMsgList( mission.GetMessages(), tlist );
356     new ListSelectWindow( "Select message", tlist,
357         event.GetData(1), false, this, B_ID_MSG_OK, view );
358     break;
359   case B_ID_MSG_OK: {
360     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
361     event.SetData( 1, n ? n->ID() : -1 );
362     e_msg->SetString( n ? n->Name() : "<None>" );
363     tlist.Clear(); }
364     break;
365   case S_ID_VALUE:
366     event.SetTmpBuf( e_msg->String() ? e_msg->String() : "" );
367     break;
368   }
369   return GUI_OK;
370 }
371 
372 ////////////////////////////////////////////////////////////////////////
373 // NAME       : EdEventConfigureWindow::GetValueString
374 // DESCRIPTION: Get the string representation of the "value" parameter
375 //              that should be shown to the user.
376 // PARAMETERS : -
377 // RETURNS    : display string
378 ////////////////////////////////////////////////////////////////////////
379 
GetValueString(void) const380 const char *EdEventConfigureWindow::GetValueString( void ) const {
381   const char *ret = NULL;
382 
383   switch (event.GetData(0) ) {
384   case 0:
385   case 1:
386     ret = mission.GetMessage(event.GetData(1));
387     break;
388   case 2:
389     if ( event.GetTmpBuf() != "" ) ret = event.GetTmpBuf().c_str();
390     break;
391   }
392   return ( ret == NULL ) ? "<None>" : ret;
393 }
394 
395 ////////////////////////////////////////////////////////////////////////
396 // NAME       : EdEventCreateUnitWindow::EdEventCreateUnitWindow
397 // DESCRIPTION: This window allows configuration of a CREATE_UNIT
398 //              event.
399 // PARAMETERS : event   - event to edit
400 //              mission - current mission
401 //              view    - pointer to the window's view
402 // RETURNS    : -
403 ////////////////////////////////////////////////////////////////////////
404 
EdEventCreateUnitWindow(Event & event,Mission & mission,View * view)405 EdEventCreateUnitWindow::EdEventCreateUnitWindow( Event &event,
406                          Mission &mission, View *view ) :
407       Window(WIN_CENTER, view), event(event), mission(mission) {
408   SetSize( MIN(sfont->Width() * 30 + 15, view->Width()),
409            sfont->Height() * 4 + 50 );
410 
411   Widget *wd;
412   unsigned short wdx, wdh = sfont->Height() + 8;
413   Point loc = mission.GetMap().Index2Hex( event.GetData(1) );
414 
415   wd = new ButtonWidget( B_ID_UNIT, 5, 5,
416        sfont->Width() * 4 + 10, wdh, 0, "_Unit", this );
417   wd->SetHook( this );
418 
419   wdx = wd->LeftEdge() + wd->Width() + 5;
420   e_unit = new StringWidget( 0, wdx, 5, w - wdx - 5, wdh,
421            mission.GetUnitSet().GetUnitInfo(event.GetData(0))->Name(),
422            30, WIDGET_STR_CONST, NULL, this );
423 
424   wdx = 10 + sfont->TextWidth( "X" );
425   wd = new NumberWidget( N_ID_XPOS, wdx, wd->TopEdge() + wdh + 5,
426        sfont->Width() * 4 + 10, wdh, loc.x, 0,
427        mission.GetMap().Width() - 1, WIDGET_ALIGN_LEFT, "_X", this );
428   wd->SetHook( this );
429 
430   wdx += wd->Width() + 10 + sfont->TextWidth( "Y" );
431   wd = new NumberWidget( N_ID_YPOS, wdx, wd->TopEdge(),
432        wd->Width(), wdh, loc.y, 0,
433        mission.GetMap().Height() - 1, WIDGET_ALIGN_LEFT, "_Y", this );
434   wd->SetHook( this );
435 
436   wdx += wd->Width() + 10 + sfont->TextWidth( "Direction" );
437   wd = new CycleWidget( B_ID_DIRECTION,
438        wdx, wd->TopEdge(), w - 5 - wdx, wdh,
439        0, "_Direction", event.GetData(2) & 0x07, dir_labels, this );
440   wd->SetHook( this );
441 
442   wdx = 10 + sfont->TextWidth("Squad Size");
443   wd = new CycleWidget( B_ID_SIZE, wdx, wd->TopEdge() + wd->Height() + 5,
444        w/2 - 5 - wdx, wdh, 0, "Squad _Size",
445        ((event.GetData(2) & 0x38) >> 3) - 1, size_labels, this );
446   wd->SetHook( this );
447 
448   wdx += wd->Width() + sfont->TextWidth("XP Level") + 10;
449   wd = new CycleWidget( B_ID_XP, wdx,
450        wd->TopEdge(), w - 5 - wdx, wdh, 0, "XP _Level",
451        (event.GetData(2) & 0x1C0) >> 6, xp_labels, this );
452   wd->SetHook( this );
453 
454   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
455                     WIDGET_DEFAULT, "_OK", this );
456 
457   Draw();
458   Show();
459 }
460 
461 ////////////////////////////////////////////////////////////////////////
462 // NAME       : EdEventCreateUnitWindow::WidgetActivated
463 // DESCRIPTION: React to user actions.
464 // PARAMETERS : widget - activated widget
465 //              win    - window containing the widget
466 // RETURNS    : GUI status
467 ////////////////////////////////////////////////////////////////////////
468 
WidgetActivated(Widget * widget,Window * win)469 GUI_Status EdEventCreateUnitWindow::WidgetActivated( Widget *widget, Window *win ) {
470   TLWNode *n;
471 
472   switch( widget->ID() ) {
473   case B_ID_UNIT:
474     TLWListBuilder::BuildUnitTypesList( mission.GetUnitSet(), tlist );
475     new ListSelectWindow( "Select unit", tlist,
476         event.GetData(0), false, this, B_ID_UNIT_OK, view );
477     break;
478   case B_ID_UNIT_OK:
479     n = static_cast<ListSelectWindow *>(win)->Selected();
480     event.SetData( 0, n ? n->ID() : -1 );
481     e_unit->SetString( n ? n->Name() : "Error" );
482     tlist.Clear();
483     break;
484   case N_ID_XPOS:
485   case N_ID_YPOS: {
486     Point loc = mission.GetMap().Index2Hex( event.GetData(1) );
487     if ( widget->ID() == N_ID_XPOS )
488       loc.x = static_cast<NumberWidget *>(widget)->Number();
489     else
490       loc.y = static_cast<NumberWidget *>(widget)->Number();
491     event.SetData( 1, mission.GetMap().Hex2Index(loc) );
492     break; }
493   case B_ID_DIRECTION:
494     event.SetData( 2, (event.GetData(2) & ~0x0007) |
495           static_cast<CycleWidget *>(widget)->GetValue() );
496     break;
497   case B_ID_SIZE:
498     event.SetData( 2, (event.GetData(2) & ~0x0038) |
499           ((static_cast<CycleWidget *>(widget)->GetValue() + 1) << 3) );
500     break;
501   case B_ID_XP:
502     event.SetData( 2, (event.GetData(2) & ~0x01C0) |
503           (static_cast<CycleWidget *>(widget)->GetValue() << 6) );
504     break;
505   }
506 
507   return GUI_OK;
508 }
509 
510 ////////////////////////////////////////////////////////////////////////
511 // NAME       : EdEventDestroyUnitWindow::EdEventDestroyUnitWindow
512 // DESCRIPTION: This window allows configuration of a DESTROY_UNIT
513 //              event.
514 // PARAMETERS : event   - event to edit
515 //              mission - current mission
516 //              view    - pointer to the window's view
517 // RETURNS    : -
518 ////////////////////////////////////////////////////////////////////////
519 
EdEventDestroyUnitWindow(Event & event,Mission & mission,View * view)520 EdEventDestroyUnitWindow::EdEventDestroyUnitWindow( Event &event,
521                       Mission &mission, View *view ) :
522       Window(WIN_CENTER, view), event(event), mission(mission) {
523   SetSize( MIN(sfont->Width() * 30 + 15, view->Width()),
524            sfont->Height() * 5 + 60 );
525 
526   Widget *wd;
527   unsigned short wdx, wdh = sfont->Height() + 8;
528   char buf[32] = "Any";
529   static const char *player_labels[] = { "Any", "One", "Two", 0 };
530   Point loc;
531 
532   wd = new ButtonWidget( B_ID_UNIT, 5, 5,
533        sfont->Width() * 4 + 10, wdh, 0, "_Unit", this );
534   wd->SetHook( this );
535 
536   Unit *u = mission.GetUnitByID( event.GetData(0) );
537   if ( u ) {
538     sprintf( buf, "%s (%d)", u->Name(), u->ID() );
539     loc = Point(0, 0);
540   } else {
541     loc = mission.GetMap().Index2Hex( event.GetData(2) );
542   }
543 
544   wdx = wd->LeftEdge() + wd->Width() + 5;
545   e_unit = new StringWidget( 0, wdx, 5, w - wdx - 5, wdh,
546            buf, 30, WIDGET_STR_CONST, NULL, this );
547 
548   wdx = 10 + sfont->TextWidth( "X" );
549   e_xpos = new NumberWidget( N_ID_XPOS, wdx, wd->TopEdge() + wdh + 5,
550            sfont->Width() * 4 + 10, wdh, loc.x, 0,
551            mission.GetMap().Width() - 1,
552            WIDGET_ALIGN_LEFT|(u ? WIDGET_DISABLED : 0), "_X", this );
553   e_xpos->SetHook( this );
554 
555   wdx += wd->Width() + 10 + sfont->TextWidth( "Y" );
556   e_ypos = new NumberWidget( N_ID_YPOS, wdx, e_xpos->TopEdge(),
557        e_xpos->Width(), wdh, loc.y, 0,
558        mission.GetMap().Height() - 1,
559        WIDGET_ALIGN_LEFT|(u ? WIDGET_DISABLED : 0), "_Y", this );
560   e_ypos->SetHook( this );
561 
562   wdx = sfont->Width() * 20 + 10;
563   wd = new CycleWidget( B_ID_PLAYER, wdx, e_ypos->TopEdge() + wdh + 10,
564        w - wdx - 5, wdh, 0, "Controlled by _Player",
565        event.GetData(1) + 1, player_labels, this );
566   wd->SetHook( this );
567 
568   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
569                     WIDGET_DEFAULT, "_OK", this );
570 
571   Draw();
572   Show();
573 }
574 
575 ////////////////////////////////////////////////////////////////////////
576 // NAME       : EdEventDestroyUnitWindow::WidgetActivated
577 // DESCRIPTION: React to user actions.
578 // PARAMETERS : widget - activated widget
579 //              win    - window containing the widget
580 // RETURNS    : GUI status
581 ////////////////////////////////////////////////////////////////////////
582 
WidgetActivated(Widget * widget,Window * win)583 GUI_Status EdEventDestroyUnitWindow::WidgetActivated( Widget *widget, Window *win ) {
584 
585   switch( widget->ID() ) {
586   case B_ID_UNIT:
587     TLWListBuilder::BuildUnitList( mission.GetUnits(), tlist );
588     new ListSelectWindow( "Select unit", tlist,
589         event.GetData(0), true, this, B_ID_UNIT_OK, view );
590     break;
591   case B_ID_UNIT_OK: {
592     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
593     if ( n ) {
594       event.SetData( 0, n->ID() );
595       event.SetData( 2, 0 );
596       e_unit->SetString( n->Name() );
597       e_xpos->SetNumber( 0 );
598       e_ypos->SetNumber( 0 );
599       e_xpos->Disable();
600       e_ypos->Disable();
601     } else {
602       event.SetData( 0, -1 );
603       e_unit->SetString( "Any" );
604       e_xpos->Enable();
605       e_ypos->Enable();
606     }
607     e_xpos->Draw();
608     e_ypos->Draw();
609     e_xpos->Show();
610     e_ypos->Show();
611     tlist.Clear();
612     break; }
613   case B_ID_PLAYER:
614     event.SetData( 1, static_cast<CycleWidget *>(widget)->GetValue() - 1 );
615     break;
616   case N_ID_XPOS:
617   case N_ID_YPOS: {
618     Point loc = mission.GetMap().Index2Hex( event.GetData(2) );
619     if ( widget->ID() == N_ID_XPOS )
620       loc.x = static_cast<NumberWidget *>(widget)->Number();
621     else
622       loc.y = static_cast<NumberWidget *>(widget)->Number();
623     event.SetData( 2, mission.GetMap().Hex2Index(loc) );
624     break; }
625   }
626 
627   return GUI_OK;
628 }
629 
630 ////////////////////////////////////////////////////////////////////////
631 // NAME       : EdEventManipEventWindow::EdEventManipEventWindow
632 // DESCRIPTION: This window allows configuration of a MANIPULATE_EVENT
633 //              event.
634 // PARAMETERS : event   - event to edit
635 //              mission - current mission
636 //              view    - pointer to the window's view
637 // RETURNS    : -
638 ////////////////////////////////////////////////////////////////////////
639 
EdEventManipEventWindow(Event & event,Mission & mission,View * view)640 EdEventManipEventWindow::EdEventManipEventWindow( Event &event,
641                          Mission &mission, View *view ) :
642       Window(WIN_CENTER, view), event(event), mission(mission) {
643   static const char *action_labels[] = { "Set flags",
644                                          "Clear flags",
645                                          "Toggle flags", 0 };
646 
647   SetSize( MIN(sfont->Width() * 25 + 15, view->Width()),
648            sfont->Height() * 4 + 50 );
649 
650   Widget *wd;
651   unsigned short wdx, wdy, wdh = sfont->Height() + 8;
652   char buf[48] = "Error";
653 
654   wd = new ButtonWidget( B_ID_EVENT, 5, 5,
655        sfont->Width() * 5 + 10, wdh, 0, "_Event", this );
656   wd->SetHook( this );
657 
658   Event *e = mission.GetEventByID( event.GetData(0) );
659   if ( e ) sprintf( buf, "%s (%d)", e->Name(), e->ID() );
660   wdx = wd->LeftEdge() + wd->Width() + 5;
661   e_event = new StringWidget( 0, wdx, 5, w - wdx - 5, wdh,
662             buf, 30, WIDGET_STR_CONST, NULL, this );
663 
664   wdx = sfont->Width() * 6 + 10;
665   wdy = wdh + 10;
666   wd = new CycleWidget( B_ID_ACTION, wdx, wdy,
667        w - wdx - 5, wdh, 0, "_Action",
668        event.GetData(2), action_labels, this );
669   wd->SetHook( this );
670 
671   wdx = w - 10 - DEFAULT_CBW_SIZE;
672   wdy += wdh + 5;
673   wd = new CheckboxWidget( B_ID_DISABLED, wdx, wdy,
674        DEFAULT_CBW_SIZE, DEFAULT_CBW_SIZE,
675        event.GetData(1) & EFLAG_DISABLED,
676        WIDGET_STYLE_GFX|WIDGET_STYLE_NOBORDER|WIDGET_ALIGN_LEFT,
677        "_Disabled", this );
678   wd->SetHook( this );
679 
680   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
681                     WIDGET_DEFAULT, "_OK", this );
682   Draw();
683   Show();
684 
685   TLWListBuilder::BuildEventList( mission.GetEvents(), tlist );
686 }
687 
688 ////////////////////////////////////////////////////////////////////////
689 // NAME       : EdEventManipEventWindow::WidgetActivated
690 // DESCRIPTION: React to user actions.
691 // PARAMETERS : widget - activated widget
692 //              win    - window containing the widget
693 // RETURNS    : GUI status
694 ////////////////////////////////////////////////////////////////////////
695 
WidgetActivated(Widget * widget,Window * win)696 GUI_Status EdEventManipEventWindow::WidgetActivated( Widget *widget, Window *win ) {
697 
698   switch( widget->ID() ) {
699   case B_ID_EVENT:
700     new ListSelectWindow( "Select event", tlist,
701         event.GetData(0), false, this, B_ID_EVENT_OK, view );
702     break;
703   case B_ID_EVENT_OK: {
704     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
705     event.SetData( 0, n ? n->ID() : -1 );
706     e_event->SetString( n ? n->Name() : "Error" );
707     break; }
708   case B_ID_ACTION:
709     event.SetData( 2, static_cast<CycleWidget *>(widget)->GetValue() );
710     break;
711   case B_ID_DISABLED:
712     event.SetData( 1, event.GetData(1)^EFLAG_DISABLED );
713   }
714 
715   return GUI_OK;
716 }
717 
718 ////////////////////////////////////////////////////////////////////////
719 // NAME       : EdEventMessageWindow::EdEventMessageWindow
720 // DESCRIPTION: This window allows configuration of a MESSAGE event.
721 // PARAMETERS : event   - event to edit
722 //              mission - current mission
723 //              view    - pointer to the window's view
724 // RETURNS    : -
725 ////////////////////////////////////////////////////////////////////////
726 
EdEventMessageWindow(Event & event,Mission & mission,View * view)727 EdEventMessageWindow::EdEventMessageWindow( Event &event, Mission &mission,
728                                           View *view ) :
729       Window(WIN_CENTER, view), event(event), mission(mission) {
730   SetSize( MIN(sfont->Width() * 15 + 15, view->Width()),
731            sfont->Height() * 2 + 25 );
732 
733   unsigned short wdx, wdh = sfont->Height() + 8;
734   Point loc = mission.GetMap().Index2Hex( event.GetData(0) );
735 
736   wdx = 10 + sfont->TextWidth( "X" );
737   e_xpos = new NumberWidget( 0,
738        wdx, 5, sfont->Width() * 4 + 10, wdh,
739        loc.x, -1, mission.GetMap().Width() - 1,
740        WIDGET_ALIGN_LEFT, "_X", this );
741 
742   wdx += e_xpos->Width() + 10 + sfont->TextWidth( "Y" );
743   e_ypos = new NumberWidget( 0,
744        wdx, e_xpos->TopEdge(), e_xpos->Width(), wdh,
745        loc.y, -1, mission.GetMap().Height() - 1,
746        WIDGET_ALIGN_LEFT, "_Y", this );
747 
748   ButtonWidget *wd = new ButtonWidget( GUI_CLOSE,
749                      1, h - wdh - 1, w - 2, wdh,
750                      WIDGET_DEFAULT, "_OK", this );
751   wd->SetHook( this );
752 
753   Draw();
754   Show();
755 }
756 
757 ////////////////////////////////////////////////////////////////////////
758 // NAME       : EdEventMessageWindow::WidgetActivated
759 // DESCRIPTION: React to user actions.
760 // PARAMETERS : widget - activated widget
761 //              win    - window containing the widget
762 // RETURNS    : GUI status
763 ////////////////////////////////////////////////////////////////////////
764 
WidgetActivated(Widget * widget,Window * win)765 GUI_Status EdEventMessageWindow::WidgetActivated( Widget *widget, Window *win ) {
766   Point loc( e_xpos->Number(), e_ypos->Number() );
767   short idx = ((loc.x >= 0) && (loc.y >= 0)) ? mission.GetMap().Hex2Index(loc) : -1;
768   event.SetData( 0, idx );
769   return GUI_CLOSE;
770 }
771 
772 ////////////////////////////////////////////////////////////////////////
773 // NAME       : EdEventMiningWindow::EdEventMiningWindow
774 // DESCRIPTION: This window allows configuration of a MINING event.
775 // PARAMETERS : event   - event to edit
776 //              mission - current mission
777 //              view    - pointer to the window's view
778 // RETURNS    : -
779 ////////////////////////////////////////////////////////////////////////
780 
EdEventMiningWindow(Event & event,Mission & mission,View * view)781 EdEventMiningWindow::EdEventMiningWindow( Event &event,
782                          Mission &mission, View *view ) :
783       Window(WIN_CENTER, view), event(event), mission(mission) {
784   static const char *action_labels[] = { "Set supplies",
785                                          "Modify supplies",
786                                          "Set production",
787                                          "Modify production", 0 };
788 
789   SetSize( MIN(sfont->Width() * 30 + 15, view->Width()),
790            sfont->Height() * 4 + 50 );
791 
792   Widget *wd;
793   unsigned short wdx, wdy, wdh = sfont->Height() + 8;
794 
795   wd = new ButtonWidget( B_ID_MINE, 5, 5,
796        sfont->Width() * 6, wdh, 0, "_Mine", this );
797   wd->SetHook( this );
798 
799   wdx = wd->LeftEdge() + wd->Width() + 5;
800   Building *b = mission.GetBuildingByID( event.GetData(0) );
801   e_mine = new StringWidget( 0, wdx, wd->TopEdge(),
802            w - wdx - 5, wdh, b ? b->Name() : "Error",
803            30, WIDGET_STR_CONST, NULL, this );
804 
805   wdy = wd->Height() + 10;
806   wd = new CycleWidget( B_ID_ACTION, wdx, wdy,
807        e_mine->Width(), wdh, 0, "_Action",
808        event.GetData(2), action_labels, this );
809   wd->SetHook( this );
810 
811   wdy += wdh + 5;
812   e_crystals = new NumberWidget( N_ID_CRYSTALS,
813        wdx, wdy, wd->Width(), wdh,
814        event.GetData(1), -1000, 10000,
815        WIDGET_ALIGN_LEFT, "Amou_nt", this );
816   e_crystals->SetHook( this );
817 
818   // this is kind of a hack: it's not (yet) possible to
819   // change the maximum string length after creation of
820   // the widget, so we assumed the maximum above and set
821   // the real values now
822   SetMiningRange( event.GetData(2) );
823 
824   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
825                     WIDGET_DEFAULT, "_OK", this );
826   Draw();
827   Show();
828 }
829 
830 ////////////////////////////////////////////////////////////////////////
831 // NAME       : EdEventMiningWindow::WidgetActivated
832 // DESCRIPTION: React to user actions.
833 // PARAMETERS : widget - activated widget
834 //              win    - window containing the widget
835 // RETURNS    : GUI status
836 ////////////////////////////////////////////////////////////////////////
837 
WidgetActivated(Widget * widget,Window * win)838 GUI_Status EdEventMiningWindow::WidgetActivated( Widget *widget, Window *win ) {
839   TLWNode *n;
840 
841   switch( widget->ID() ) {
842   case B_ID_MINE:
843     TLWListBuilder::BuildShopList( mission.GetBuildings(), tlist );
844     new ListSelectWindow( "Select mine", tlist,
845         event.GetData(0), false, this, B_ID_MINE_OK, view );
846     break;
847   case B_ID_MINE_OK:
848     n = static_cast<ListSelectWindow *>(win)->Selected();
849     event.SetData( 0, n ? n->ID() : -1 );
850     e_mine->SetString( n ? n->Name() : "Error" );
851     tlist.Clear();
852     break;
853   case B_ID_ACTION:
854     event.SetData( 2, static_cast<CycleWidget *>(widget)->GetValue() );
855     SetMiningRange( static_cast<CycleWidget *>(widget)->GetValue() );
856     // fall through in case range has changed the number
857   case N_ID_CRYSTALS:
858     event.SetData( 1, e_crystals->Number() );
859   }
860 
861   return GUI_OK;
862 }
863 
864 ////////////////////////////////////////////////////////////////////////
865 // NAME       : EdEventMiningWindow::SetMiningRange
866 // DESCRIPTION: The minimum and maximum numbers allowed in the "amount"
867 //              widget are subject of the "action" chosen. We set the
868 //              correct range here.
869 // PARAMETERS : action - action to set the range for
870 // RETURNS    : -
871 ////////////////////////////////////////////////////////////////////////
872 
SetMiningRange(short action) const873 void EdEventMiningWindow::SetMiningRange( short action ) const {
874   short min = 0, max = 0;
875   switch ( action ) {
876   case 0: max = 1000; break;              // set supplies
877   case 1: min = -1000; max = 1000; break; // modify supplies
878   case 2: max = 200; break;               // set production
879   case 3: min = -200; max = 200; break;   // modify production;
880   }
881   e_crystals->SetMin( min );
882   e_crystals->SetMax( max );
883 }
884 
885 ////////////////////////////////////////////////////////////////////////
886 // NAME       : EdEventResearchWindow::EdEventResearchWindow
887 // DESCRIPTION: This window allows configuration of a RESEARCH event.
888 // PARAMETERS : event   - event to edit
889 //              mission - current mission
890 //              view    - pointer to the window's view
891 // RETURNS    : -
892 ////////////////////////////////////////////////////////////////////////
893 
EdEventResearchWindow(Event & event,Mission & mission,View * view)894 EdEventResearchWindow::EdEventResearchWindow( Event &event,
895                        Mission &mission, View *view ) :
896       Window(WIN_CENTER, view), event(event), mission(mission) {
897   SetSize( MIN(sfont->Width() * 25, view->Width()),
898            sfont->Height() * 4 + 55 );
899 
900   static const char *action_labels[] = { "Allow", "Disallow", 0 };
901   Widget *wd;
902   unsigned short wdx, wdh = sfont->Height() + 8;
903 
904   wdx = sfont->TextWidth("Action") + 10;
905   wd = new CycleWidget( B_ID_ACTION, wdx, 5, w - wdx - 5, wdh,
906        0, "_Action", event.GetData(2), action_labels, this );
907   wd->SetHook( this );
908 
909   wd = new ButtonWidget( B_ID_SHOP, 5, wd->TopEdge() + wdh + 5,
910        sfont->Width() * 4 + 10, wdh, 0, "_Shop", this );
911   wd->SetHook( this );
912 
913   Building *b = mission.GetBuildingByID( event.GetData(0) );
914   wdx = wd->LeftEdge() + wd->Width() + 5;
915   e_shop = new StringWidget( 0, wdx, wd->TopEdge(), w - wdx - 5, wdh,
916            b ? b->Name() : "Error", 30, WIDGET_STR_CONST,
917            NULL, this );
918 
919   wd = new ButtonWidget( B_ID_UNIT, 5, wd->TopEdge() + wdh + 5,
920        wd->Width(), wdh, 0, "_Unit", this );
921   wd->SetHook( this );
922 
923   e_unit = new StringWidget( 0, wdx, wd->TopEdge(),
924            e_shop->Width(), wdh,
925            mission.GetUnitSet().GetUnitInfo(event.GetData(1))->Name(),
926            30, WIDGET_STR_CONST, NULL, this );
927 
928   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
929                     WIDGET_DEFAULT, "_OK", this );
930   Draw();
931   Show();
932 }
933 
934 ////////////////////////////////////////////////////////////////////////
935 // NAME       : EdEventResearchWindow::WidgetActivated
936 // DESCRIPTION: React to user actions.
937 // PARAMETERS : widget - activated widget
938 //              win    - window containing the widget
939 // RETURNS    : GUI status
940 ////////////////////////////////////////////////////////////////////////
941 
WidgetActivated(Widget * widget,Window * win)942 GUI_Status EdEventResearchWindow::WidgetActivated( Widget *widget, Window *win ) {
943   TLWNode *n;
944 
945   switch( widget->ID() ) {
946   case B_ID_UNIT:
947     TLWListBuilder::BuildUnitTypesList( mission.GetUnitSet(), tlist );
948     new ListSelectWindow( "Select researched unit", tlist,
949         event.GetData(1), false, this, B_ID_UNIT_OK, view );
950     break;
951   case B_ID_UNIT_OK:
952     n = static_cast<ListSelectWindow *>(win)->Selected();
953     event.SetData( 1, n ? n->ID() : -1 );
954     e_unit->SetString( n ? n->Name() : "Error" );
955     tlist.Clear();
956     break;
957   case B_ID_SHOP:
958     TLWListBuilder::BuildShopList( mission.GetBuildings(), tlist );
959     new ListSelectWindow( "Select factory", tlist,
960         event.GetData(0), false, this, B_ID_SHOP_OK, view );
961     break;
962   case B_ID_SHOP_OK:
963     n = static_cast<ListSelectWindow *>(win)->Selected();
964     event.SetData( 0, n ? n->ID() : -1 );
965     e_shop->SetString( n ? n->Name() : "Error" );
966     tlist.Clear();
967     break;
968   case B_ID_ACTION:
969     event.SetData( 2, static_cast<CycleWidget *>(widget)->GetValue() );
970     break;
971   }
972 
973   return GUI_OK;
974 }
975 
976 ////////////////////////////////////////////////////////////////////////
977 // NAME       : EdEventScoreWindow::EdEventScoreWindow
978 // DESCRIPTION: This window allows configuration of a SCORE event.
979 // PARAMETERS : event   - event to edit
980 //              mission - current mission
981 //              view    - pointer to the window's view
982 // RETURNS    : -
983 ////////////////////////////////////////////////////////////////////////
984 
EdEventScoreWindow(Event & event,Mission & mission,View * view)985 EdEventScoreWindow::EdEventScoreWindow( Event &event, Mission &mission, View *view ) :
986       Window(WIN_CENTER, view), event(event), mission(mission) {
987   SetSize( MIN(sfont->Width() * 20 + 15, view->Width()),
988            sfont->Height() * 4 + 50 );
989 
990   unsigned short wdx = sfont->Width() * 5 + 10;
991   Widget *wd = new NumberWidget( N_ID_SCORE, wdx, 5,
992                w - wdx - 5, sfont->Height() + 8,
993                event.GetData(0), 1, 100,
994                WIDGET_ALIGN_LEFT, "_Score", this );
995   wd->SetHook( this );
996 
997   wd = new ButtonWidget( B_ID_TITLE, 5, wd->TopEdge() + wd->Height() + 5,
998                     sfont->Width() * 10, wd->Height(), 0, "Lose _Title", this );
999   wd->SetHook( this );
1000 
1001   wdx = wd->LeftEdge() + wd->Width() + 5;
1002   const char *str = mission.GetMessage(event.GetData(2));
1003   other_title = new StringWidget( 0, wdx, wd->TopEdge(), w - wdx - 5, wd->Height(),
1004            (str || event.GetData(2) == -1) ? str : "Error", 30, WIDGET_STR_CONST,
1005            NULL, this );
1006 
1007   wd = new ButtonWidget( B_ID_MSG, 5, wd->TopEdge() + wd->Height() + 5,
1008                          wd->Width(), wd->Height(), 0, "Lose _Msg", this );
1009   wd->SetHook( this );
1010 
1011   str = mission.GetMessage(event.GetData(1));
1012   other_msg = new StringWidget( 0, wdx, wd->TopEdge(), other_title->Width(), wd->Height(),
1013            (str || event.GetData(1) == -1) ? str : "Error", 30, WIDGET_STR_CONST,
1014            NULL, this );
1015 
1016   new ButtonWidget( GUI_CLOSE, 1, h - wd->Height() - 1, w - 2, wd->Height(),
1017                     WIDGET_DEFAULT, "_OK", this );
1018   Draw();
1019   Show();
1020 
1021   TLWListBuilder::BuildMsgList( mission.GetMessages(), msglist );
1022 }
1023 
1024 ////////////////////////////////////////////////////////////////////////
1025 // NAME       : EdEventScoreWindow::WidgetActivated
1026 // DESCRIPTION: React to user actions.
1027 // PARAMETERS : widget - activated widget
1028 //              win    - window containing the widget
1029 // RETURNS    : GUI status
1030 ////////////////////////////////////////////////////////////////////////
1031 
WidgetActivated(Widget * widget,Window * win)1032 GUI_Status EdEventScoreWindow::WidgetActivated( Widget *widget, Window *win ) {
1033   TLWNode *n;
1034 
1035   switch ( widget->ID() ) {
1036   case N_ID_SCORE:
1037     event.SetData( 0, static_cast<NumberWidget *>(widget)->Number() );
1038     break;
1039   case B_ID_MSG:
1040     new ListSelectWindow( "Select lose message", msglist, event.GetData(1),
1041                           true, this, B_ID_MSG_OK, view );
1042     break;
1043   case B_ID_MSG_OK:
1044     n = static_cast<ListSelectWindow *>(win)->Selected();
1045     event.SetData( 1, n ? n->ID() : -1 );
1046     other_msg->SetString( n ? mission.GetMessage(n->ID()) : NULL );
1047     break;
1048   case B_ID_TITLE:
1049     new ListSelectWindow( "Select lose title", msglist, event.GetData(2),
1050                           true, this, B_ID_TITLE_OK, view );
1051     break;
1052   case B_ID_TITLE_OK:
1053     n = static_cast<ListSelectWindow *>(win)->Selected();
1054     event.SetData( 2, n ? n->ID() : -1 );
1055     other_title->SetString( n ? mission.GetMessage(n->ID()) : NULL );
1056   }
1057 
1058   return GUI_OK;
1059 }
1060 
1061 ////////////////////////////////////////////////////////////////////////
1062 // NAME       : EdEventSetHexWindow::EdEventSetHexWindow
1063 // DESCRIPTION: This window allows configuration of a SET_HEX event.
1064 // PARAMETERS : event   - event to edit
1065 //              mission - current mission
1066 //              view    - pointer to the window's view
1067 // RETURNS    : -
1068 ////////////////////////////////////////////////////////////////////////
1069 
EdEventSetHexWindow(Event & event,Mission & mission,View * view)1070 EdEventSetHexWindow::EdEventSetHexWindow( Event &event, Mission &mission,
1071                                           View *view ) :
1072       Window(WIN_CENTER, view), event(event), mission(mission) {
1073   const TerrainSet &set = mission.GetTerrainSet();
1074 
1075   SetSize( MIN(sfont->Width() * 15 + 15, view->Width()),
1076            sfont->Height() * 2 + set.TileHeight() + 30 );
1077 
1078   tilepos = Rect( (w - set.TileWidth()) / 2, 5,
1079                   set.TileWidth(), set.TileHeight() );
1080 
1081   Widget *wd;
1082   unsigned short wdx, wdh = sfont->Height() + 8;
1083   Point loc = mission.GetMap().Index2Hex( event.GetData(1) );
1084 
1085   wd = new ButtonWidget( B_ID_TILE_PREV,
1086        tilepos.x - sfont->Width() - 10, 5,
1087        sfont->Width() + 10, tilepos.h, 0, "_<", this );
1088   wd->SetHook( this );
1089 
1090   wd = new ButtonWidget( B_ID_TILE_NEXT, tilepos.x + tilepos.w, 5,
1091        wd->Width(), tilepos.h, 0, "_>", this );
1092   wd->SetHook( this );
1093 
1094   wdx = 10 + sfont->TextWidth( "X" );
1095   wd = new NumberWidget( N_ID_XPOS, wdx, wd->TopEdge() + wd->Height() + 5,
1096        sfont->Width() * 4 + 10, wdh, loc.x, 0,
1097        mission.GetMap().Width() - 1, WIDGET_ALIGN_LEFT, "_X", this );
1098   wd->SetHook( this );
1099 
1100   wdx += wd->Width() + 10 + sfont->TextWidth( "Y" );
1101   wd = new NumberWidget( N_ID_YPOS, wdx, wd->TopEdge(),
1102        wd->Width(), wdh, loc.y, 0,
1103        mission.GetMap().Height() - 1, WIDGET_ALIGN_LEFT, "_Y", this );
1104   wd->SetHook( this );
1105 
1106   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1107                     WIDGET_DEFAULT, "_OK", this );
1108 
1109   Draw();
1110   Show();
1111 }
1112 
1113 ////////////////////////////////////////////////////////////////////////
1114 // NAME       : EdEventSetHexWindow::Draw
1115 // DESCRIPTION: Draw the window.
1116 // PARAMETERS : -
1117 // RETURNS    : -
1118 ////////////////////////////////////////////////////////////////////////
1119 
Draw(void)1120 void EdEventSetHexWindow::Draw( void ) {
1121   Window::Draw();
1122   DrawTerrain( event.GetData(0), false );
1123 }
1124 
1125 ////////////////////////////////////////////////////////////////////////
1126 // NAME       : EdEventSetHexWindow::WidgetActivated
1127 // DESCRIPTION: React to user actions.
1128 // PARAMETERS : widget - activated widget
1129 //              win    - window containing the widget
1130 // RETURNS    : GUI status
1131 ////////////////////////////////////////////////////////////////////////
1132 
WidgetActivated(Widget * widget,Window * win)1133 GUI_Status EdEventSetHexWindow::WidgetActivated( Widget *widget, Window *win ) {
1134   unsigned short num;
1135 
1136   switch( widget->ID() ) {
1137   case B_ID_TILE_PREV:
1138     num = event.GetData( 0 );
1139     if ( num > 0 ) --num;
1140     else num = mission.GetTerrainSet().NumTiles() - 1;
1141     event.SetData( 0, num );
1142     DrawTerrain( num, true );
1143     Show( tilepos );
1144     break;
1145   case B_ID_TILE_NEXT:
1146     num = event.GetData( 0 );
1147     if ( ++num == mission.GetTerrainSet().NumTiles() ) num = 0;
1148     event.SetData( 0, num );
1149     DrawTerrain( num, true );
1150     Show( tilepos );
1151     break;
1152   case N_ID_XPOS:
1153   case N_ID_YPOS: {
1154     Point loc = mission.GetMap().Index2Hex( event.GetData(1) );
1155     if ( widget->ID() == N_ID_XPOS )
1156       loc.x = static_cast<NumberWidget *>(widget)->Number();
1157     else
1158       loc.y = static_cast<NumberWidget *>(widget)->Number();
1159     event.SetData( 1, mission.GetMap().Hex2Index(loc) );
1160     break; }
1161   }
1162 
1163   return GUI_OK;
1164 }
1165 
1166 ////////////////////////////////////////////////////////////////////////
1167 // NAME       : EdEventSetHexWindow::DrawTerrain
1168 // DESCRIPTION: Draw a terrain image to the window surface.
1169 // PARAMETERS : terrain - terrain identifier
1170 //              update  - whether to update the display
1171 // RETURNS    : -
1172 ////////////////////////////////////////////////////////////////////////
1173 
DrawTerrain(unsigned short terrain,bool update)1174 void EdEventSetHexWindow::DrawTerrain( unsigned short terrain, bool update ) {
1175   const TerrainSet &set = mission.GetTerrainSet();
1176   const TerrainType *tt = set.GetTerrainInfo( terrain );
1177 
1178   if ( tt ) {
1179     set.DrawTile( tt->tt_image, this, tilepos.x, tilepos.y, tilepos );
1180 
1181     if ( update ) Show( tilepos );
1182   }
1183 }
1184 
1185 ////////////////////////////////////////////////////////////////////////
1186 // NAME       : EdEventSetTimerWindow::EdEventSetTimerWindow
1187 // DESCRIPTION: This window allows configuration of a SET_TIMER event.
1188 // PARAMETERS : event   - event to edit
1189 //              mission - current mission
1190 //              view    - pointer to the window's view
1191 // RETURNS    : -
1192 ////////////////////////////////////////////////////////////////////////
1193 
EdEventSetTimerWindow(Event & event,Mission & mission,View * view)1194 EdEventSetTimerWindow::EdEventSetTimerWindow( Event &event,
1195                          Mission &mission, View *view ) :
1196       Window(WIN_CENTER, view), event(event), mission(mission) {
1197   static const char *offset_labels[] = { "None (absolute)",
1198                                          "Execution time",
1199                                          "Trigger configuration", 0 };
1200 
1201   SetSize( MIN(sfont->Width() * 25 + 15, view->Width()),
1202            sfont->Height() * 4 + 50 );
1203 
1204   Widget *wd;
1205   unsigned short wdx, wdy, wdh = sfont->Height() + 8;
1206   char buf[48] = "Error";
1207 
1208   wd = new ButtonWidget( B_ID_EVENT, 5, 5,
1209        sfont->Width() * 5 + 10, wdh, 0, "_Event", this );
1210   wd->SetHook( this );
1211 
1212   Event *e = mission.GetEventByID( event.GetData(0) );
1213   if ( e ) sprintf( buf, "%s (%d)", e->Name(), e->ID() );
1214   wdx = wd->LeftEdge() + wd->Width() + 5;
1215   e_event = new StringWidget( 0, wdx, 5, w - wdx - 5, wdh,
1216             buf, 30, WIDGET_STR_CONST, NULL, this );
1217 
1218   wdy = wdh + 10;
1219   wd = new CycleWidget( B_ID_OFFSET, e_event->LeftEdge(), wdy,
1220        w - e_event->LeftEdge() - 5, wdh, 0, "O_ffset",
1221        event.GetData(2), offset_labels, this );
1222   wd->SetHook( this );
1223 
1224   wdx = sfont->TextWidth("Time") + 10;
1225   wdy += wdh + 5;
1226   wd = new NumberWidget( N_ID_TIME,
1227        wdx, wdy, sfont->Width() * 5, wdh,
1228        event.GetData(1), 0, 100,
1229        WIDGET_ALIGN_LEFT, "_Time", this );
1230   wd->SetHook( this );
1231 
1232   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1233                     WIDGET_DEFAULT, "_OK", this );
1234   Draw();
1235   Show();
1236 
1237   TLWListBuilder::BuildEventList( mission.GetEvents(), tlist );
1238 }
1239 
1240 ////////////////////////////////////////////////////////////////////////
1241 // NAME       : EdEventSetTimerWindow::WidgetActivated
1242 // DESCRIPTION: React to user actions.
1243 // PARAMETERS : widget - activated widget
1244 //              win    - window containing the widget
1245 // RETURNS    : GUI status
1246 ////////////////////////////////////////////////////////////////////////
1247 
WidgetActivated(Widget * widget,Window * win)1248 GUI_Status EdEventSetTimerWindow::WidgetActivated( Widget *widget, Window *win ) {
1249 
1250   switch( widget->ID() ) {
1251   case B_ID_EVENT:
1252     new ListSelectWindow( "Select event", tlist,
1253         event.GetData(0), false, this, B_ID_EVENT_OK, view );
1254     break;
1255   case B_ID_EVENT_OK: {
1256     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
1257     if ( n ) {
1258       Event *e = static_cast<Event *>( n->UserData() );
1259       if ( e->Trigger() != ETRIGGER_TIMER ) {
1260         n = NULL;
1261         new NoteWindow( "Error", "Selected event has no 'Timer' trigger.",
1262             0, view );
1263       }
1264     }
1265     event.SetData( 0, n ? n->ID() : -1 );
1266     e_event->SetString( n ? n->Name() : "Error" );
1267     break; }
1268   case B_ID_OFFSET:
1269     event.SetData( 2, static_cast<CycleWidget *>(widget)->GetValue() );
1270     break;
1271   case N_ID_TIME:
1272     event.SetData( 1, static_cast<NumberWidget *>(widget)->Number() );
1273     break;
1274   }
1275 
1276   return GUI_OK;
1277 }
1278 
1279 
1280 ////////////////////////////////////////////////////////////////////////
1281 // NAME       : EdTrigHaveCrystalsWindow::EdTrigHaveCrystalsWindow
1282 // DESCRIPTION: This window allows configuration of a HAVE_CRYSTALS
1283 //              trigger.
1284 // PARAMETERS : event   - event to edit
1285 //              mission - current mission
1286 //              view    - pointer to the window's view
1287 // RETURNS    : -
1288 ////////////////////////////////////////////////////////////////////////
1289 
EdTrigHaveCrystalsWindow(Event & event,Mission & mission,View * view)1290 EdTrigHaveCrystalsWindow::EdTrigHaveCrystalsWindow( Event &event,
1291                       Mission &mission, View *view ) :
1292       Window(WIN_CENTER, view), event(event), mission(mission) {
1293   SetSize( MIN(sfont->Width() * 30 + 15, view->Width()),
1294            sfont->Height() * 4 + 50 );
1295 
1296   Widget *wd;
1297   unsigned short wdx, wdh = sfont->Height() + 8;
1298   static const char *moreless_labels[] = { ">=", "<", 0 };
1299 
1300   wd = new ButtonWidget( B_ID_SHOP, 5, 5,
1301        sfont->Width() * 4 + 10, wdh, 0, "_Shop", this );
1302   wd->SetHook( this );
1303 
1304   Building *b = mission.GetBuildingByID( event.GetTData(2) );
1305   wdx = wd->LeftEdge() + wd->Width() + 5;
1306   t_shop = new StringWidget( 0, wdx, 5, w - wdx - 5, wdh,
1307            b ? b->Name() : "All", 30, WIDGET_STR_CONST,
1308            NULL, this );
1309 
1310   wdx = sfont->TextWidth("Player") + 10;
1311   wd = new CycleWidget( B_ID_PLAYER, wdx, wd->Height() + 10,
1312        sfont->Width() * 3 + 20, wdh, 0, "_Player",
1313        event.GetTData(1), player2_labels, this );
1314   wd->SetHook( this );
1315 
1316   wdx = w - 5 - sfont->Width() * 4 - 20;
1317   wd = new CycleWidget( B_ID_MOREORLESS, wdx, wd->TopEdge(),
1318        sfont->Width() * 4 + 20, wdh, 0, NULL,
1319        event.GetTData(0) < 0 ? 1 : 0, moreless_labels, this );
1320   wd->SetHook( this );
1321 
1322   wdx = wd->LeftEdge() - 5 - sfont->Width() * 6;
1323   wd = new NumberWidget( N_ID_CRYSTALS, wdx, wd->TopEdge(),
1324        sfont->Width() * 6, wdh, ABS(event.GetTData(0)),
1325        1, 5000, WIDGET_ALIGN_LEFT, "_Crystals", this );
1326   wd->SetHook( this );
1327 
1328   t_transports = new CheckboxWidget( B_ID_TRANSPORTS,
1329        5, wd->TopEdge() + wd->Height() + 5,
1330        DEFAULT_CBW_SIZE, DEFAULT_CBW_SIZE,
1331        event.GetTData(2) == -2,
1332        WIDGET_STYLE_GFX|WIDGET_STYLE_NOBORDER|WIDGET_ALIGN_RIGHT|
1333        (event.GetTData(2) >= 0 ? WIDGET_DISABLED : 0),
1334        "_Include Transports", this );
1335   t_transports->SetHook( this );
1336 
1337   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1338                     WIDGET_DEFAULT, "_OK", this );
1339 
1340   Draw();
1341   Show();
1342 }
1343 
1344 ////////////////////////////////////////////////////////////////////////
1345 // NAME       : EdTrigHaveCrystalsWindow::WidgetActivated
1346 // DESCRIPTION: React to user actions.
1347 // PARAMETERS : widget - activated widget
1348 //              win    - window containing the widget
1349 // RETURNS    : GUI status
1350 ////////////////////////////////////////////////////////////////////////
1351 
WidgetActivated(Widget * widget,Window * win)1352 GUI_Status EdTrigHaveCrystalsWindow::WidgetActivated( Widget *widget, Window *win ) {
1353 
1354   switch( widget->ID() ) {
1355   case B_ID_SHOP:
1356     TLWListBuilder::BuildShopList( mission.GetBuildings(), tlist );
1357     new ListSelectWindow( "Select shop", tlist,
1358         event.GetTData(2), true, this, B_ID_SHOP_OK, view );
1359     break;
1360   case B_ID_SHOP_OK: {
1361     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
1362     event.SetTData( 2, n ? n->ID() : -1 );
1363     t_shop->SetString( n ? n->Name() : "All" );
1364     tlist.Clear();
1365 
1366     if ( !n ) {
1367       t_transports->Enable();
1368       if ( t_transports->Clicked() ) event.SetTData( 2, -2 );
1369     } else t_transports->Disable();
1370     t_transports->Draw();
1371     Show();
1372     break; }
1373   case B_ID_PLAYER:
1374     event.SetTData( 1, static_cast<CycleWidget *>(widget)->GetValue() );
1375     break;
1376   case N_ID_CRYSTALS:
1377     event.SetTData( 0, SIGN(event.GetTData(0)) * static_cast<NumberWidget *>(widget)->Number() );
1378     break;
1379   case B_ID_MOREORLESS:
1380     event.SetTData( 0, event.GetTData( 0 ) * -1 );
1381     break;
1382   case B_ID_TRANSPORTS:
1383     event.SetTData( 2, widget->Clicked() ? -2 : -1 );
1384   }
1385 
1386   return GUI_OK;
1387 }
1388 
1389 ////////////////////////////////////////////////////////////////////////
1390 // NAME       : EdTrigHaveShopWindow::EdTrigHaveShopWindow
1391 // DESCRIPTION: This window allows configuration of a HAVE_BUILDING
1392 //              trigger.
1393 // PARAMETERS : event   - event to edit
1394 //              mission - current mission
1395 //              view    - pointer to the window's view
1396 // RETURNS    : -
1397 ////////////////////////////////////////////////////////////////////////
1398 
EdTrigHaveShopWindow(Event & event,Mission & mission,View * view)1399 EdTrigHaveShopWindow::EdTrigHaveShopWindow( Event &event,
1400                       Mission &mission, View *view ) :
1401       Window(WIN_CENTER, view), event(event), mission(mission) {
1402   SetSize( MIN(sfont->Width() * 30 + 15, view->Width()),
1403            sfont->Height() * 4 + 50 );
1404 
1405   Widget *wd;
1406   unsigned short wdx, wdh = sfont->Height() + 8;
1407 
1408   wd = new ButtonWidget( B_ID_SHOP, 5, 5,
1409        sfont->Width() * 4 + 10, wdh, 0, "_Shop", this );
1410   wd->SetHook( this );
1411 
1412   Building *b = mission.GetBuildingByID( event.GetTData(0) );
1413   wdx = wd->LeftEdge() + wd->Width() + 5;
1414   t_shop = new StringWidget( 0, wdx, 5, w - wdx - 5, wdh,
1415            b ? b->Name() : "Error", 30, WIDGET_STR_CONST,
1416            NULL, this );
1417 
1418   wdx = sfont->Width() * 20 + 10;
1419   wd = new CycleWidget( B_ID_PLAYER, wdx, wd->Height() + 10,
1420        w - wdx - 5, wdh, 0, "Controlled by _Player",
1421        event.GetTData(1), player2_labels, this );
1422   wd->SetHook( this );
1423 
1424   wd = new NumberWidget( N_ID_TIMER,
1425        sfont->Width() * 7 + 10, wd->TopEdge() + wd->Height() + 5,
1426        sfont->Width() * 6, wdh, event.GetTData(2),
1427        -1, 999, WIDGET_ALIGN_LEFT, "At _Time", this );
1428   wd->SetHook( this );
1429 
1430   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1431                     WIDGET_DEFAULT, "_OK", this );
1432 
1433   Draw();
1434   Show();
1435 }
1436 
1437 ////////////////////////////////////////////////////////////////////////
1438 // NAME       : EdTrigHaveShopWindow::WidgetActivated
1439 // DESCRIPTION: React to user actions.
1440 // PARAMETERS : widget - activated widget
1441 //              win    - window containing the widget
1442 // RETURNS    : GUI status
1443 ////////////////////////////////////////////////////////////////////////
1444 
WidgetActivated(Widget * widget,Window * win)1445 GUI_Status EdTrigHaveShopWindow::WidgetActivated( Widget *widget, Window *win ) {
1446 
1447   switch( widget->ID() ) {
1448   case B_ID_SHOP:
1449     TLWListBuilder::BuildShopList( mission.GetBuildings(), tlist );
1450     new ListSelectWindow( "Select shop", tlist,
1451         event.GetTData(0), false, this, B_ID_SHOP_OK, view );
1452     break;
1453   case B_ID_SHOP_OK: {
1454     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
1455     event.SetTData( 0, n ? n->ID() : -1 );
1456     t_shop->SetString( n ? n->Name() : "Error" );
1457     tlist.Clear();
1458     break; }
1459   case B_ID_PLAYER:
1460     event.SetTData( 1, static_cast<CycleWidget *>(widget)->GetValue() );
1461     break;
1462   case N_ID_TIMER:
1463     event.SetTData( 2, static_cast<NumberWidget *>(widget)->Number() );
1464   }
1465 
1466   return GUI_OK;
1467 }
1468 
1469 ////////////////////////////////////////////////////////////////////////
1470 // NAME       : EdTrigHaveUnitWindow::EdTrigHaveUnitWindow
1471 // DESCRIPTION: This window allows configuration of a HAVE_UNIT trigger.
1472 // PARAMETERS : event   - event to edit
1473 //              mission - current mission
1474 //              view    - pointer to the window's view
1475 // RETURNS    : -
1476 ////////////////////////////////////////////////////////////////////////
1477 
EdTrigHaveUnitWindow(Event & event,Mission & mission,View * view)1478 EdTrigHaveUnitWindow::EdTrigHaveUnitWindow( Event &event,
1479                       Mission &mission, View *view ) :
1480       Window(WIN_CENTER, view), event(event), mission(mission) {
1481   SetSize( MIN(sfont->Width() * 30 + 15, view->Width()),
1482            sfont->Height() * 4 + 50 );
1483 
1484   Widget *wd;
1485   unsigned short wdx, wdh = sfont->Height() + 8;
1486   char buf[32] = "Error";
1487 
1488   wd = new ButtonWidget( B_ID_UNIT, 5, 5,
1489        sfont->Width() * 4 + 10, wdh, 0, "_Unit", this );
1490   wd->SetHook( this );
1491 
1492   Unit *u = mission.GetUnitByID( event.GetTData(0) );
1493   if ( u ) sprintf( buf, "%s (%d)", u->Name(), u->ID() );
1494 
1495   wdx = wd->LeftEdge() + wd->Width() + 5;
1496   t_unit = new StringWidget( 0, wdx, 5, w - wdx - 5, wdh,
1497            buf, 30, WIDGET_STR_CONST, NULL, this );
1498 
1499   wdx = sfont->Width() * 20 + 10;
1500   wd = new CycleWidget( B_ID_PLAYER, wdx, wd->Height() + 10,
1501        w - wdx - 5, wdh, 0, "Controlled by _Player",
1502        event.GetTData(1), player2_labels, this );
1503   wd->SetHook( this );
1504 
1505   wd = new NumberWidget( N_ID_TIMER,
1506        sfont->Width() * 8 + 10, wd->TopEdge() + wd->Height() + 5,
1507        sfont->Width() * 6, wdh, event.GetTData(2),
1508        -1, 999, WIDGET_ALIGN_LEFT, "At _Time", this );
1509   wd->SetHook( this );
1510 
1511   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1512                     WIDGET_DEFAULT, "_OK", this );
1513 
1514   Draw();
1515   Show();
1516 }
1517 
1518 ////////////////////////////////////////////////////////////////////////
1519 // NAME       : EdTrigHaveUnitWindow::WidgetActivated
1520 // DESCRIPTION: React to user actions.
1521 // PARAMETERS : widget - activated widget
1522 //              win    - window containing the widget
1523 // RETURNS    : GUI status
1524 ////////////////////////////////////////////////////////////////////////
1525 
WidgetActivated(Widget * widget,Window * win)1526 GUI_Status EdTrigHaveUnitWindow::WidgetActivated( Widget *widget, Window *win ) {
1527 
1528   switch( widget->ID() ) {
1529   case B_ID_UNIT:
1530     TLWListBuilder::BuildUnitList( mission.GetUnits(), tlist );
1531     new ListSelectWindow( "Select unit", tlist,
1532         event.GetTData(0), false, this, B_ID_UNIT_OK, view );
1533     break;
1534   case B_ID_UNIT_OK: {
1535     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
1536     event.SetTData( 0, n ? n->ID() : -1 );
1537     t_unit->SetString( n ? n->Name() : "Error" );
1538     tlist.Clear();
1539     break; }
1540   case B_ID_PLAYER:
1541     event.SetTData( 1, static_cast<CycleWidget *>(widget)->GetValue() );
1542     break;
1543   case N_ID_TIMER:
1544     event.SetTData( 2, static_cast<NumberWidget *>(widget)->Number() );
1545   }
1546 
1547   return GUI_OK;
1548 }
1549 
1550 ////////////////////////////////////////////////////////////////////////
1551 // NAME       : EdTrigTimerWindow::EdTrigTimerWindow
1552 // DESCRIPTION: This window allows configuration of a TIMER trigger.
1553 // PARAMETERS : event - event to edit
1554 //              view  - pointer to the window's view
1555 // RETURNS    : -
1556 ////////////////////////////////////////////////////////////////////////
1557 
EdTrigTimerWindow(Event & event,View * view)1558 EdTrigTimerWindow::EdTrigTimerWindow( Event &event, View *view ) :
1559                   Window(WIN_CENTER, view), event(event) {
1560   SetSize( MIN(sfont->Width() * 21 + 15, view->Width()),
1561            sfont->Height() * 2 + 30 );
1562 
1563   unsigned short wdx = sfont->Width() * 15 + 10,
1564                  wdh = sfont->Height() + 8;
1565   Widget *wd = new NumberWidget( 0, wdx, 5, w - wdx - 5, wdh,
1566        event.GetTData(0), 0, 999, WIDGET_ALIGN_LEFT,
1567        "Execute at _time", this );
1568   wd->SetHook( this );
1569 
1570   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1571                     WIDGET_DEFAULT, "_OK", this );
1572   Draw();
1573   Show();
1574 }
1575 
1576 ////////////////////////////////////////////////////////////////////////
1577 // NAME       : EdTrigTimerWindow::WidgetActivated
1578 // DESCRIPTION: React to user actions.
1579 // PARAMETERS : widget - activated widget
1580 //              win    - window containing the widget
1581 // RETURNS    : GUI status
1582 ////////////////////////////////////////////////////////////////////////
1583 
WidgetActivated(Widget * widget,Window * win)1584 GUI_Status EdTrigTimerWindow::WidgetActivated( Widget *widget, Window *win ) {
1585   event.SetTData( 0, static_cast<NumberWidget *>(widget)->Number() );
1586   return GUI_OK;
1587 }
1588 
1589 ////////////////////////////////////////////////////////////////////////
1590 // NAME       : EdTrigUnitDestroyedWindow::EdTrigUnitDestroyedWindow
1591 // DESCRIPTION: This window allows configuration of a UNIT_DESTROYED
1592 //              trigger.
1593 // PARAMETERS : event   - event to edit
1594 //              mission - current mission
1595 //              view    - pointer to the window's view
1596 // RETURNS    : -
1597 ////////////////////////////////////////////////////////////////////////
1598 
EdTrigUnitDestroyedWindow(Event & event,Mission & mission,View * view)1599 EdTrigUnitDestroyedWindow::EdTrigUnitDestroyedWindow( Event &event,
1600                            Mission &mission, View *view ) :
1601       Window(WIN_CENTER, view), event(event), mission(mission) {
1602   SetSize( MIN(sfont->Width() * 30 + 15, view->Width()),
1603            sfont->Height() * 4 + 50 );
1604 
1605   Widget *wd;
1606   unsigned short wdx, wdh = sfont->Height() + 8;
1607   char buf[32] = "All";
1608 
1609   wdx = 10 + sfont->TextWidth("Select");
1610   t_uselect = new CycleWidget( B_ID_USELECT, wdx, 5, w/2 - wdx - 5, wdh,
1611               0, "_Select", (event.GetTData(0) >= -1) ? 0 : 1,
1612               uselect_labels, this );
1613   t_uselect->SetHook( this );
1614 
1615   wd = new ButtonWidget( B_ID_UNIT,
1616        5, t_uselect->TopEdge() + wdh + 5,
1617        sfont->Width() * 4 + 10, wdh, 0, "_Unit", this );
1618   wd->SetHook( this );
1619 
1620   if ( event.GetTData(0) >= 0 ) {
1621     Unit *u = mission.GetUnitByID( event.GetTData(0) );
1622     if ( u ) sprintf( buf, "%s (%d)", u->Name(), u->ID() );
1623   } else if ( event.GetTData(0) < -1 ) {
1624     strcpy( buf, mission.GetUnitSet().GetUnitInfo(-event.GetTData(0) - 2)->Name() );
1625   }
1626   wdx = wd->LeftEdge() + wd->Width() + 5;
1627   t_unit = new StringWidget( 0, wdx, wd->TopEdge(), w - wdx - 5, wdh,
1628            buf, 30, WIDGET_STR_CONST, NULL, this );
1629 
1630   wdx = sfont->Width() * 20 + 10;
1631   t_player = new CycleWidget( B_ID_PLAYER,
1632              wdx, wd->TopEdge() + wd->Height() + 5,
1633              w - wdx - 5, wdh,
1634              (event.GetTData(0) >= 0) ? WIDGET_DISABLED : 0,
1635              "Controlled by _Player", event.GetTData(1),
1636              player2_labels, this );
1637   t_player->SetHook( this );
1638 
1639   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1640                     WIDGET_DEFAULT, "_OK", this );
1641   Draw();
1642   Show();
1643 }
1644 
1645 ////////////////////////////////////////////////////////////////////////
1646 // NAME       : EdTrigUnitDestroyedWindow::WidgetActivated
1647 // DESCRIPTION: React to user actions.
1648 // PARAMETERS : widget - activated widget
1649 //              win    - window containing the widget
1650 // RETURNS    : GUI status
1651 ////////////////////////////////////////////////////////////////////////
1652 
WidgetActivated(Widget * widget,Window * win)1653 GUI_Status EdTrigUnitDestroyedWindow::WidgetActivated( Widget *widget, Window *win ) {
1654 
1655   switch( widget->ID() ) {
1656   case B_ID_UNIT:
1657     if ( t_uselect->GetValue() == 0 ) {
1658       TLWListBuilder::BuildUnitList( mission.GetUnits(), tlist );
1659       new ListSelectWindow( "Select target unit", tlist,
1660           event.GetTData(0), true, this, B_ID_UNIT_OK, view );
1661     } else {
1662       TLWListBuilder::BuildUnitTypesList( mission.GetUnitSet(), tlist );
1663       new ListSelectWindow( "Select unit type", tlist,
1664           -event.GetTData(0) - 2, true, this, B_ID_UNIT_OK, view );
1665     }
1666     break;
1667   case B_ID_UNIT_OK: {
1668     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
1669     if ( t_uselect->GetValue() == 0 ) {
1670       event.SetTData( 0, n ? n->ID() : -1 );
1671       if ( n ) {
1672         event.SetTData( 1, static_cast<Unit *>(n->UserData())->Owner() );
1673         t_player->Disable();
1674       } else {
1675         event.SetTData( 1, event.Player()^1 );
1676         t_player->Enable();
1677         t_player->SetValue( event.GetTData(1) );
1678       }
1679     } else {
1680       event.SetTData( 0, n ? -n->ID() - 2 : -1);
1681     }
1682     t_unit->SetString( n ? n->Name() : "All", true );
1683 
1684     Draw();
1685     Show();
1686     tlist.Clear();
1687     break; }
1688   case B_ID_USELECT:
1689     if ( t_uselect->GetValue() == 0 ) {
1690       event.SetTData( 0, -1 );
1691       t_unit->SetString( "All", true );
1692     } else if ( event.GetTData(0) != -1 ) {
1693       Unit *u = mission.GetUnitByID( event.GetTData(0) );
1694       if ( u ) {
1695         event.SetTData( 0, -u->Type()->ID() - 2 );
1696         t_unit->SetString( u->Name(), true );
1697       } else {
1698         event.SetTData( 0, -1 );
1699         t_unit->SetString( "All", true );
1700       }
1701     }
1702     t_player->Enable();
1703     t_player->SetValue( event.GetTData(1) );
1704     break;
1705   case B_ID_PLAYER:
1706     event.SetTData( 1, static_cast<CycleWidget *>(widget)->GetValue() );
1707   }
1708 
1709   return GUI_OK;
1710 }
1711 
1712 ////////////////////////////////////////////////////////////////////////
1713 // NAME       : EdTrigUnitPositionWindow::EdTrigUnitPositionWindow
1714 // DESCRIPTION: This window allows configuration of a UNIT_POSITION
1715 //              trigger.
1716 // PARAMETERS : event   - event to edit
1717 //              mission - current mission
1718 //              view    - pointer to the window's view
1719 // RETURNS    : -
1720 ////////////////////////////////////////////////////////////////////////
1721 
EdTrigUnitPositionWindow(Event & event,Mission & mission,View * view)1722 EdTrigUnitPositionWindow::EdTrigUnitPositionWindow( Event &event,
1723                            Mission &mission, View *view ) :
1724       Window(WIN_CENTER, view), event(event), mission(mission) {
1725   SetSize( MIN(sfont->Width() * 30 + 15, view->Width()),
1726            sfont->Height() * 4 + 50 );
1727 
1728   Widget *wd;
1729   unsigned short wdx, wdh = sfont->Height() + 8;
1730   char buf[32] = "Any";
1731   Point loc = mission.GetMap().Index2Hex( event.GetTData(1) );
1732 
1733   wdx = 10 + sfont->TextWidth("Select");
1734   t_uselect = new CycleWidget( B_ID_USELECT, wdx, 5, w/2 - wdx - 5, wdh,
1735               0, "_Select", (event.GetTData(0) >= -1) ? 0 : 1,
1736               uselect_labels, this );
1737   t_uselect->SetHook( this );
1738 
1739   wdx = w/2 + 10 + sfont->TextWidth("Player");
1740   wd = new CycleWidget( B_ID_PLAYER, wdx, t_uselect->TopEdge(),
1741            w - wdx - 5, wdh, 0, "_Player", event.GetTData(2),
1742            player2_labels, this );
1743   wd->SetHook( this );
1744 
1745   wd = new ButtonWidget( B_ID_UNIT, 5, t_uselect->TopEdge() + wdh + 5,
1746        sfont->Width() * 4 + 10, wdh, 0, "_Unit", this );
1747   wd->SetHook( this );
1748 
1749   if ( event.GetTData(0) >= 0 ) {
1750     Unit *u = mission.GetUnitByID( event.GetTData(0) );
1751     if ( u ) sprintf( buf, "%s (%d)", u->Name(), u->ID() );
1752   } else if ( event.GetTData(0) < -1 ) {
1753     strcpy( buf, mission.GetUnitSet().GetUnitInfo(-event.GetTData(0) - 2)->Name() );
1754   }
1755 
1756   wdx = wd->LeftEdge() + wd->Width() + 5;
1757   t_unit = new StringWidget( 0, wdx, wd->TopEdge(), w - wdx - 5, wdh,
1758            buf, 30, WIDGET_STR_CONST, NULL, this );
1759 
1760   wdx = sfont->Width() * 10 + 10;
1761   wd = new NumberWidget( N_ID_POSX,
1762        wdx, wd->TopEdge() + wd->Height() + 5,
1763        (w - wdx - sfont->Width() - 15) / 2, wdh,
1764        loc.x, 0, mission.GetMap().Width() - 1,
1765        WIDGET_ALIGN_LEFT, "Position _X", this );
1766   wd->SetHook( this );
1767 
1768   wdx += wd->Width() + sfont->Width() + 10;
1769   wd = new NumberWidget( N_ID_POSY,
1770        wdx, wd->TopEdge(), w - wdx - 5, wdh,
1771        loc.y, 0, mission.GetMap().Height() - 1,
1772        WIDGET_ALIGN_LEFT, "_Y", this );
1773   wd->SetHook( this );
1774 
1775   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1776                     WIDGET_DEFAULT, "_OK", this );
1777   Draw();
1778   Show();
1779 }
1780 
1781 ////////////////////////////////////////////////////////////////////////
1782 // NAME       : EdTrigUnitPositionWindow::WidgetActivated
1783 // DESCRIPTION: React to user actions.
1784 // PARAMETERS : widget - activated widget
1785 //              win    - window containing the widget
1786 // RETURNS    : GUI status
1787 ////////////////////////////////////////////////////////////////////////
1788 
WidgetActivated(Widget * widget,Window * win)1789 GUI_Status EdTrigUnitPositionWindow::WidgetActivated( Widget *widget, Window *win ) {
1790   switch( widget->ID() ) {
1791   case B_ID_UNIT:
1792     if ( t_uselect->GetValue() == 0 ) {
1793       TLWListBuilder::BuildUnitList( mission.GetUnits(), tlist );
1794       new ListSelectWindow( "Select unit", tlist,
1795           event.GetTData(0), true, this, B_ID_UNIT_OK, view );
1796     } else {
1797       TLWListBuilder::BuildUnitTypesList( mission.GetUnitSet(), tlist );
1798       new ListSelectWindow( "Select unit type", tlist,
1799           -event.GetTData(0) - 2, true, this, B_ID_UNIT_OK, view );
1800     }
1801     break;
1802   case B_ID_UNIT_OK: {
1803     TLWNode *n = static_cast<ListSelectWindow *>(win)->Selected();
1804     if ( t_uselect->GetValue() == 0 )
1805       event.SetTData( 0, n ? n->ID() : -1 );
1806     else
1807       event.SetTData( 0, n ? -n->ID() - 2 : -1);
1808     t_unit->SetString( n ? n->Name() : "Any", true );
1809     tlist.Clear();
1810     break; }
1811   case N_ID_POSX:
1812   case N_ID_POSY: {
1813     Point loc = mission.GetMap().Index2Hex( event.GetTData(1) );
1814     if ( widget->ID() == N_ID_POSX )
1815       loc.x = static_cast<NumberWidget *>(widget)->Number();
1816     else
1817       loc.y = static_cast<NumberWidget *>(widget)->Number();
1818     event.SetTData( 1, mission.GetMap().Hex2Index(loc) );
1819     break; }
1820   case B_ID_USELECT:
1821     if ( t_uselect->GetValue() == 0 ) {
1822       event.SetTData( 0, -1 );
1823       t_unit->SetString( "Any", true );
1824     } else if ( event.GetTData(0) != -1 ) {
1825       Unit *u = mission.GetUnitByID( event.GetTData(0) );
1826       if ( u ) {
1827         event.SetTData( 0, -u->Type()->ID() - 2 );
1828         t_unit->SetString( u->Name(), true );
1829       } else {
1830         event.SetTData( 0, -1 );
1831         t_unit->SetString( "Any", true );
1832       }
1833     }
1834     break;
1835   case B_ID_PLAYER:
1836     event.SetTData( 2,
1837           static_cast<CycleWidget *>(widget)->GetValue() );
1838     break;
1839   }
1840 
1841   return GUI_OK;
1842 }
1843 
1844 ////////////////////////////////////////////////////////////////////////
1845 // NAME       : EdTrigHandicapWindow::EdTrigHandicapWindow
1846 // DESCRIPTION: This window allows configuration of a HANDICAP trigger.
1847 // PARAMETERS : event - event to edit
1848 //              view  - pointer to the window's view
1849 // RETURNS    : -
1850 ////////////////////////////////////////////////////////////////////////
1851 
EdTrigHandicapWindow(Event & event,View * view)1852 EdTrigHandicapWindow::EdTrigHandicapWindow( Event &event, View *view ) :
1853                   Window(WIN_CENTER, view), event(event) {
1854   SetSize( MIN(sfont->Width() * 20 + DEFAULT_CBW_SIZE + 15, view->Width()),
1855            sfont->Height() * 4 + 40 );
1856 
1857   Widget *wd = new CheckboxWidget( HANDICAP_NONE, 5, 5,
1858                DEFAULT_CBW_SIZE, DEFAULT_CBW_SIZE,
1859                event.GetTData(0) & HANDICAP_NONE,
1860                WIDGET_STYLE_GFX|WIDGET_STYLE_NOBORDER|WIDGET_ALIGN_RIGHT,
1861                "_No handicap", this );
1862   wd->SetHook( this );
1863 
1864   wd = new CheckboxWidget( HANDICAP_P1, 5, wd->TopEdge() + wd->Height() + 5,
1865        DEFAULT_CBW_SIZE, DEFAULT_CBW_SIZE,
1866        (event.GetTData(0) & HANDICAP_P1) != 0,
1867        WIDGET_STYLE_GFX|WIDGET_STYLE_NOBORDER|WIDGET_ALIGN_RIGHT,
1868        "Player _1 handicapped", this );
1869   wd->SetHook( this );
1870 
1871   wd = new CheckboxWidget( HANDICAP_P2, 5, wd->TopEdge() + wd->Height() + 5,
1872        DEFAULT_CBW_SIZE, DEFAULT_CBW_SIZE,
1873        (event.GetTData(0) & HANDICAP_P2) != 0,
1874        WIDGET_STYLE_GFX|WIDGET_STYLE_NOBORDER|WIDGET_ALIGN_RIGHT,
1875        "Player _2 handicapped", this );
1876   wd->SetHook( this );
1877 
1878   unsigned short wdh = sfont->Height() + 8;
1879   new ButtonWidget( GUI_CLOSE, 1, h - wdh - 1, w - 2, wdh,
1880                     WIDGET_DEFAULT, "_OK", this );
1881   Draw();
1882   Show();
1883 }
1884 
1885 ////////////////////////////////////////////////////////////////////////
1886 // NAME       : EdTrigHandicapWindow::WidgetActivated
1887 // DESCRIPTION: React to user actions.
1888 // PARAMETERS : widget - activated widget
1889 //              win    - window containing the widget
1890 // RETURNS    : GUI status
1891 ////////////////////////////////////////////////////////////////////////
1892 
WidgetActivated(Widget * widget,Window * win)1893 GUI_Status EdTrigHandicapWindow::WidgetActivated( Widget *widget, Window *win ) {
1894   short handicap = event.GetTData( 0 );
1895   event.SetTData( 0, handicap ^ widget->ID() );
1896   return GUI_OK;
1897 }
1898 
1899