town_gui.cpp

Go to the documentation of this file.
00001 /* $Id: town_gui.cpp 15425 2009-02-09 02:09:47Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "town.h"
00008 #include "viewport_func.h"
00009 #include "gfx_func.h"
00010 #include "gui.h"
00011 #include "window_gui.h"
00012 #include "textbuf_gui.h"
00013 #include "command_func.h"
00014 #include "company_func.h"
00015 #include "company_base.h"
00016 #include "company_gui.h"
00017 #include "network/network.h"
00018 #include "variables.h"
00019 #include "strings_func.h"
00020 #include "sound_func.h"
00021 #include "economy_func.h"
00022 #include "tilehighlight_func.h"
00023 #include "sortlist_type.h"
00024 #include "road_cmd.h"
00025 
00026 #include "table/sprites.h"
00027 #include "table/strings.h"
00028 
00029 typedef GUIList<const Town*> GUITownList;
00030 
00031 static const Widget _town_authority_widgets[] = {
00032 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_BROWN,     0,    10,     0,    13, STR_00C5,                 STR_018B_CLOSE_WINDOW},              // TWA_CLOSEBOX
00033 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_BROWN,    11,   316,     0,    13, STR_2022_LOCAL_AUTHORITY, STR_018C_WINDOW_TITLE_DRAG_THIS},    // TWA_CAPTION
00034 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_BROWN,     0,   316,    14,   105, 0x0,                      STR_NULL},                           // TWA_RATING_INFO
00035 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_BROWN,     0,   304,   106,   157, 0x0,                      STR_2043_LIST_OF_THINGS_TO_DO_AT},   // TWA_COMMAND_LIST
00036 {  WWT_SCROLLBAR,   RESIZE_NONE,  COLOUR_BROWN,   305,   316,   106,   157, 0x0,                      STR_0190_SCROLL_BAR_SCROLLS_LIST},   // TWA_SCROLLBAR
00037 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_BROWN,     0,   316,   158,   209, 0x0,                      STR_NULL},                           // TWA_ACTION_INFO
00038 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_BROWN,     0,   316,   210,   221, STR_2042_DO_IT,           STR_2044_CARRY_OUT_THE_HIGHLIGHTED}, // TWA_EXECUTE
00039 {   WIDGETS_END},
00040 };
00041 
00042 extern const byte _town_action_costs[8];
00043 
00044 struct TownAuthorityWindow : Window {
00045 private:
00046   Town *town;
00047   int sel_index;
00048 
00049   enum TownAuthorityWidget {
00050     TWA_CLOSEBOX = 0,
00051     TWA_CAPTION,
00052     TWA_RATING_INFO,
00053     TWA_COMMAND_LIST,
00054     TWA_SCROLLBAR,
00055     TWA_ACTION_INFO,
00056     TWA_EXECUTE,
00057   };
00058 
00068   static int GetNthSetBit(uint32 bits, int n)
00069   {
00070     if (n >= 0) {
00071       uint i;
00072       FOR_EACH_SET_BIT(i, bits) {
00073         n--;
00074         if (n < 0) return i;
00075       }
00076     }
00077     return -1;
00078   }
00079 
00080 public:
00081   TownAuthorityWindow(const WindowDesc *desc, WindowNumber window_number) :
00082       Window(desc, window_number), sel_index(-1)
00083   {
00084     this->town = GetTown(this->window_number);
00085     this->vscroll.cap = 5;
00086 
00087     this->FindWindowPlacementAndResize(desc);
00088   }
00089 
00090   virtual void OnPaint()
00091   {
00092     int numact;
00093     uint buttons = GetMaskOfTownActions(&numact, _local_company, this->town);
00094 
00095     SetVScrollCount(this, numact + 1);
00096 
00097     if (this->sel_index != -1 && !HasBit(buttons, this->sel_index)) {
00098       this->sel_index = -1;
00099     }
00100 
00101     this->SetWidgetDisabledState(6, this->sel_index == -1);
00102 
00103     SetDParam(0, this->window_number);
00104     this->DrawWidgets();
00105 
00106     int y = this->widget[TWA_RATING_INFO].top + 1;
00107 
00108     DrawString(2, y, STR_2023_TRANSPORT_COMPANY_RATINGS, TC_FROMSTRING);
00109     y += 10;
00110 
00111     /* Draw list of companies */
00112     const Company *c;
00113     FOR_ALL_COMPANIES(c) {
00114       if ((HasBit(this->town->have_ratings, c->index) || this->town->exclusivity == c->index)) {
00115         DrawCompanyIcon(c->index, 2, y);
00116 
00117         SetDParam(0, c->index);
00118         SetDParam(1, c->index);
00119 
00120         int r = this->town->ratings[c->index];
00121         StringID str;
00122         (str = STR_3035_APPALLING, r <= RATING_APPALLING) || // Apalling
00123         (str++,                    r <= RATING_VERYPOOR)  || // Very Poor
00124         (str++,                    r <= RATING_POOR)      || // Poor
00125         (str++,                    r <= RATING_MEDIOCRE)  || // Mediocore
00126         (str++,                    r <= RATING_GOOD)      || // Good
00127         (str++,                    r <= RATING_VERYGOOD)  || // Very Good
00128         (str++,                    r <= RATING_EXCELLENT) || // Excellent
00129         (str++,                    true);                    // Outstanding
00130 
00131         SetDParam(2, str);
00132         if (this->town->exclusivity == c->index) { // red icon for company with exclusive rights
00133           DrawSprite(SPR_BLOT, PALETTE_TO_RED, 18, y);
00134         }
00135 
00136         DrawString(28, y, STR_2024, TC_FROMSTRING);
00137         y += 10;
00138       }
00139     }
00140 
00141     if (y > this->widget[TWA_RATING_INFO].bottom) {
00142       /* If the company list is too big to fit, mark ourself dirty and draw again. */
00143       ResizeWindowForWidget(this, TWA_RATING_INFO, 0, y - this->widget[TWA_RATING_INFO].bottom);
00144       this->SetDirty();
00145       return;
00146     }
00147 
00148     y = this->widget[TWA_COMMAND_LIST].top + 1;
00149     int pos = this->vscroll.pos;
00150 
00151     if (--pos < 0) {
00152       DrawString(2, y, STR_2045_ACTIONS_AVAILABLE, TC_FROMSTRING);
00153       y += 10;
00154     }
00155 
00156     for (int i = 0; buttons; i++, buttons >>= 1) {
00157       if (pos <= -5) break; 
00158 
00159       if ((buttons & 1) && --pos < 0) {
00160         DrawString(3, y, STR_2046_SMALL_ADVERTISING_CAMPAIGN + i, TC_ORANGE);
00161         y += 10;
00162       }
00163     }
00164 
00165     if (this->sel_index != -1) {
00166       SetDParam(1, (_price.build_industry >> 8) * _town_action_costs[this->sel_index]);
00167       SetDParam(0, STR_2046_SMALL_ADVERTISING_CAMPAIGN + this->sel_index);
00168       DrawStringMultiLine(2, this->widget[TWA_ACTION_INFO].top + 1, STR_204D_INITIATE_A_SMALL_LOCAL + this->sel_index, 313);
00169     }
00170   }
00171 
00172   virtual void OnDoubleClick(Point pt, int widget) { HandleClick(pt, widget, true); }
00173   virtual void OnClick(Point pt, int widget) { HandleClick(pt, widget, false); }
00174 
00175   void HandleClick(Point pt, int widget, bool double_click)
00176   {
00177     switch (widget) {
00178       case TWA_COMMAND_LIST: {
00179         int y = (pt.y - this->widget[TWA_COMMAND_LIST].top - 1) / 10;
00180 
00181         if (!IsInsideMM(y, 0, 5)) return;
00182 
00183         y = GetNthSetBit(GetMaskOfTownActions(NULL, _local_company, this->town), y + this->vscroll.pos - 1);
00184         if (y >= 0) {
00185           this->sel_index = y;
00186           this->SetDirty();
00187         }
00188         /* Fall through to clicking in case we are double-clicked */
00189         if (!double_click || y < 0) break;
00190       }
00191 
00192       case TWA_EXECUTE:
00193         DoCommandP(this->town->xy, this->window_number, this->sel_index, CMD_DO_TOWN_ACTION | CMD_MSG(STR_00B4_CAN_T_DO_THIS));
00194         break;
00195     }
00196   }
00197 
00198   virtual void OnHundredthTick()
00199   {
00200     this->SetDirty();
00201   }
00202 };
00203 
00204 static const WindowDesc _town_authority_desc = {
00205   WDP_AUTO, WDP_AUTO, 317, 222, 317, 222,
00206   WC_TOWN_AUTHORITY, WC_NONE,
00207   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00208   _town_authority_widgets,
00209 };
00210 
00211 static void ShowTownAuthorityWindow(uint town)
00212 {
00213   AllocateWindowDescFront<TownAuthorityWindow>(&_town_authority_desc, town);
00214 }
00215 
00216 struct TownViewWindow : Window {
00217 private:
00218   Town *town;
00219 
00220   enum TownViewWidget {
00221     TVW_CAPTION = 1,
00222     TVW_STICKY,
00223     TVW_VIEWPORTPANEL,
00224     TVW_INFOPANEL = 5,
00225     TVW_CENTERVIEW,
00226     TVW_SHOWAUTORITY,
00227     TVW_CHANGENAME,
00228     TVW_EXPAND,
00229     TVW_DELETE,
00230   };
00231 
00232 public:
00233   TownViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
00234   {
00235     this->town = GetTown(this->window_number);
00236     bool ingame = _game_mode != GM_EDITOR;
00237 
00238     this->flags4 |= WF_DISABLE_VP_SCROLL;
00239     InitializeWindowViewport(this, 3, 17, 254, 86, this->town->xy, ZOOM_LVL_TOWN);
00240 
00241     if (this->town->larger_town) this->widget[TVW_CAPTION].data = STR_CITY;
00242     this->SetWidgetHiddenState(TVW_DELETE, ingame);  // hide delete button on game mode
00243     this->SetWidgetHiddenState(TVW_EXPAND, ingame);  // hide expand button on game mode
00244     this->SetWidgetHiddenState(TVW_SHOWAUTORITY, !ingame); // hide autority button on editor mode
00245 
00246     if (ingame) {
00247       /* resize caption bar */
00248       this->widget[TVW_CAPTION].right = this->widget[TVW_STICKY].left -1;
00249       /* move the rename from top on scenario to bottom in game */
00250       this->widget[TVW_CHANGENAME].top = this->widget[TVW_EXPAND].top;
00251       this->widget[TVW_CHANGENAME].bottom = this->widget[TVW_EXPAND].bottom;
00252       this->widget[TVW_CHANGENAME].right = this->widget[TVW_STICKY].right;
00253     }
00254 
00255     /* Space required for showing noise level information */
00256     if (_settings_game.economy.station_noise_level) {
00257       ResizeWindowForWidget(this, TVW_INFOPANEL, 0, 10);
00258     }
00259 
00260     this->FindWindowPlacementAndResize(desc);
00261   }
00262 
00263   virtual void OnPaint()
00264   {
00265     /* disable renaming town in network games if you are not the server */
00266     this->SetWidgetDisabledState(TVW_CHANGENAME, _networking && !_network_server);
00267 
00268     SetDParam(0, this->town->index);
00269     this->DrawWidgets();
00270 
00271     SetDParam(0, this->town->population);
00272     SetDParam(1, this->town->num_houses);
00273     DrawString(2, 107, STR_2006_POPULATION, TC_FROMSTRING);
00274 
00275     SetDParam(0, this->town->act_pass);
00276     SetDParam(1, this->town->max_pass);
00277     DrawString(2, 117, STR_200D_PASSENGERS_LAST_MONTH_MAX, TC_FROMSTRING);
00278 
00279     SetDParam(0, this->town->act_mail);
00280     SetDParam(1, this->town->max_mail);
00281     DrawString(2, 127, STR_200E_MAIL_LAST_MONTH_MAX, TC_FROMSTRING);
00282 
00283     this->DrawViewport();
00284 
00285     /* only show the town noise, if the noise option is activated. */
00286     if (_settings_game.economy.station_noise_level) {
00287       SetDParam(0, this->town->noise_reached);
00288       SetDParam(1, this->town->MaxTownNoise());
00289       DrawString(2, 137, STR_NOISE_IN_TOWN, TC_FROMSTRING);
00290     }
00291   }
00292 
00293   virtual void OnClick(Point pt, int widget)
00294   {
00295     switch (widget) {
00296       case TVW_CENTERVIEW: /* scroll to location */
00297         if (_ctrl_pressed) {
00298           ShowExtraViewPortWindow(this->town->xy);
00299         } else {
00300           ScrollMainWindowToTile(this->town->xy);
00301         }
00302         break;
00303 
00304       case TVW_SHOWAUTORITY: /* town authority */
00305         ShowTownAuthorityWindow(this->window_number);
00306         break;
00307 
00308       case TVW_CHANGENAME: /* rename */
00309         SetDParam(0, this->window_number);
00310         ShowQueryString(STR_TOWN, STR_2007_RENAME_TOWN, MAX_LENGTH_TOWN_NAME_BYTES, MAX_LENGTH_TOWN_NAME_PIXELS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT);
00311         break;
00312 
00313       case TVW_EXPAND: /* expand town - only available on Scenario editor */
00314         ExpandTown(this->town);
00315         break;
00316 
00317       case TVW_DELETE: /* delete town - only available on Scenario editor */
00318         delete this->town;
00319         break;
00320     }
00321   }
00322 
00323   virtual void OnInvalidateData(int data = 0)
00324   {
00325     /* Called when setting station noise have changed, in order to resize the window */
00326     this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
00327 
00328     if (_settings_game.economy.station_noise_level) { // adjust depending
00329       if (this->height == 150) { // window is smaller, needs to be bigger
00330         ResizeWindowForWidget(this, TVW_INFOPANEL, 0, 10);
00331       }
00332     } else {
00333       if (this->height != 150) { // window is bigger, needs to be smaller
00334         ResizeWindowForWidget(this, TVW_INFOPANEL, 0, -10);
00335       }
00336     }
00337   }
00338 
00339   virtual void OnQueryTextFinished(char *str)
00340   {
00341     if (str == NULL) return;
00342 
00343     DoCommandP(0, this->window_number, 0, CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN), NULL, str);
00344   }
00345 };
00346 
00347 
00348 static const Widget _town_view_widgets[] = {
00349 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_BROWN,     0,    10,     0,    13, STR_00C5,                 STR_018B_CLOSE_WINDOW},
00350 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_BROWN,    11,   172,     0,    13, STR_2005,                 STR_018C_WINDOW_TITLE_DRAG_THIS},
00351 {  WWT_STICKYBOX,   RESIZE_NONE,  COLOUR_BROWN,   248,   259,     0,    13, 0x0,                      STR_STICKY_BUTTON},
00352 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_BROWN,     0,   259,    14,   105, 0x0,                      STR_NULL},
00353 {      WWT_INSET,   RESIZE_NONE,  COLOUR_BROWN,     2,   257,    16,   103, 0x0,                      STR_NULL},
00354 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_BROWN,     0,   259,   106,   137, 0x0,                      STR_NULL},
00355 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_BROWN,     0,    85,   138,   149, STR_00E4_LOCATION,        STR_200B_CENTER_THE_MAIN_VIEW_ON},
00356 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_BROWN,    86,   171,   138,   149, STR_2020_LOCAL_AUTHORITY, STR_2021_SHOW_INFORMATION_ON_LOCAL},
00357 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_BROWN,   172,   247,     0,    13, STR_0130_RENAME,          STR_200C_CHANGE_TOWN_NAME},
00358 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_BROWN,    86,   171,   138,   149, STR_023C_EXPAND,          STR_023B_INCREASE_SIZE_OF_TOWN},
00359 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_BROWN,   172,   259,   138,   149, STR_0290_DELETE,          STR_0291_DELETE_THIS_TOWN_COMPLETELY},
00360 {   WIDGETS_END},
00361 };
00362 
00363 static const WindowDesc _town_view_desc = {
00364   WDP_AUTO, WDP_AUTO, 260, 150, 260, 150,
00365   WC_TOWN_VIEW, WC_NONE,
00366   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
00367   _town_view_widgets,
00368 };
00369 
00370 void ShowTownViewWindow(TownID town)
00371 {
00372   AllocateWindowDescFront<TownViewWindow>(&_town_view_desc, town);
00373 }
00374 
00375 static const Widget _town_directory_widgets[] = {
00376 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_BROWN,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
00377 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_BROWN,    11,   195,     0,    13, STR_2000_TOWNS,         STR_018C_WINDOW_TITLE_DRAG_THIS},
00378 {  WWT_STICKYBOX,   RESIZE_NONE,  COLOUR_BROWN,   196,   207,     0,    13, 0x0,                    STR_STICKY_BUTTON},
00379 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_BROWN,     0,    98,    14,    25, STR_SORT_BY_NAME,       STR_SORT_ORDER_TIP},
00380 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_BROWN,    99,   195,    14,    25, STR_SORT_BY_POPULATION, STR_SORT_ORDER_TIP},
00381 {      WWT_PANEL, RESIZE_BOTTOM,  COLOUR_BROWN,     0,   195,    26,   189, 0x0,                    STR_200A_TOWN_NAMES_CLICK_ON_NAME},
00382 {  WWT_SCROLLBAR, RESIZE_BOTTOM,  COLOUR_BROWN,   196,   207,    14,   189, 0x0,                    STR_0190_SCROLL_BAR_SCROLLS_LIST},
00383 {      WWT_PANEL,     RESIZE_TB,  COLOUR_BROWN,     0,   195,   190,   201, 0x0,                    STR_NULL},
00384 {  WWT_RESIZEBOX,     RESIZE_TB,  COLOUR_BROWN,   196,   207,   190,   201, 0x0,                    STR_RESIZE_BUTTON},
00385 {   WIDGETS_END},
00386 };
00387 
00388 
00389 struct TownDirectoryWindow : public Window {
00390 private:
00391   enum TownDirectoryWidget {
00392     TDW_SORTNAME = 3,
00393     TDW_SORTPOPULATION,
00394     TDW_CENTERTOWN,
00395   };
00396 
00397   /* Runtime saved values */
00398   static Listing last_sorting;
00399   static const Town *last_town;
00400 
00401   /* Constants for sorting towns */
00402   static GUITownList::SortFunction * const sorter_funcs[];
00403 
00404   GUITownList towns;
00405 
00406   void BuildTownList()
00407   {
00408     if (!this->towns.NeedRebuild()) return;
00409 
00410     this->towns.Clear();
00411 
00412     const Town *t;
00413     FOR_ALL_TOWNS(t) {
00414       *this->towns.Append() = t;
00415     }
00416 
00417     this->towns.Compact();
00418     this->towns.RebuildDone();
00419   }
00420 
00421   void SortTownList()
00422   {
00423     last_town = NULL;
00424     this->towns.Sort();
00425   }
00426 
00428   static int CDECL TownNameSorter(const Town * const *a, const Town * const *b)
00429   {
00430     static char buf_cache[64];
00431     const Town *ta = *a;
00432     const Town *tb = *b;
00433     char buf[64];
00434 
00435     SetDParam(0, ta->index);
00436     GetString(buf, STR_TOWN, lastof(buf));
00437 
00438     /* If 'b' is the same town as in the last round, use the cached value
00439      * We do this to speed stuff up ('b' is called with the same value a lot of
00440      * times after eachother) */
00441     if (tb != last_town) {
00442       last_town = tb;
00443       SetDParam(0, tb->index);
00444       GetString(buf_cache, STR_TOWN, lastof(buf_cache));
00445     }
00446 
00447     return strcmp(buf, buf_cache);
00448   }
00449 
00451   static int CDECL TownPopulationSorter(const Town * const *a, const Town * const *b)
00452   {
00453     return (*a)->population - (*b)->population;
00454   }
00455 
00456 public:
00457   TownDirectoryWindow(const WindowDesc *desc) : Window(desc, 0)
00458   {
00459     this->vscroll.cap = 16;
00460     this->resize.step_height = 10;
00461     this->resize.height = this->height - 10 * 6; // minimum of 10 items in the list, each item 10 high
00462 
00463     this->towns.SetListing(this->last_sorting);
00464     this->towns.SetSortFuncs(this->sorter_funcs);
00465     this->towns.ForceRebuild();
00466 
00467     this->FindWindowPlacementAndResize(desc);
00468   }
00469 
00470   ~TownDirectoryWindow()
00471   {
00472     this->last_sorting = this->towns.GetListing();
00473   }
00474 
00475   virtual void OnPaint()
00476   {
00477     this->BuildTownList();
00478     this->SortTownList();
00479 
00480     SetVScrollCount(this, this->towns.Length());
00481 
00482     this->DrawWidgets();
00483     this->DrawSortButtonState(this->towns.SortType() == 0 ? TDW_SORTNAME : TDW_SORTPOPULATION, this->towns.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
00484 
00485     {
00486       int n = 0;
00487       uint16 i = this->vscroll.pos;
00488       int y = 28;
00489 
00490       while (i < this->towns.Length()) {
00491         const Town *t = this->towns[i];
00492 
00493         assert(t->xy != INVALID_TILE);
00494 
00495         SetDParam(0, t->index);
00496         SetDParam(1, t->population);
00497         DrawString(2, y, STR_2057, TC_FROMSTRING);
00498 
00499         y += 10;
00500         i++;
00501         if (++n == this->vscroll.cap) break; // max number of towns in 1 window
00502       }
00503 
00504       SetDParam(0, GetWorldPopulation());
00505       DrawString(3, this->height - 12 + 2, STR_TOWN_POPULATION, TC_FROMSTRING);
00506     }
00507   }
00508 
00509   virtual void OnClick(Point pt, int widget)
00510   {
00511     switch (widget) {
00512       case TDW_SORTNAME: /* Sort by Name ascending/descending */
00513         if (this->towns.SortType() == 0) {
00514           this->towns.ToggleSortOrder();
00515         } else {
00516           this->towns.SetSortType(0);
00517         }
00518         this->SetDirty();
00519         break;
00520 
00521       case TDW_SORTPOPULATION: /* Sort by Population ascending/descending */
00522         if (this->towns.SortType() == 1) {
00523           this->towns.ToggleSortOrder();
00524         } else {
00525           this->towns.SetSortType(1);
00526         }
00527         this->SetDirty();
00528         break;
00529 
00530       case TDW_CENTERTOWN: { /* Click on Town Matrix */
00531         uint16 id_v = (pt.y - 28) / 10;
00532 
00533         if (id_v >= this->vscroll.cap) return; // click out of bounds
00534 
00535         id_v += this->vscroll.pos;
00536 
00537         if (id_v >= this->towns.Length()) return; // click out of town bounds
00538 
00539         const Town *t = this->towns[id_v];
00540         assert(t->xy != INVALID_TILE);
00541         if (_ctrl_pressed) {
00542           ShowExtraViewPortWindow(t->xy);
00543         } else {
00544           ScrollMainWindowToTile(t->xy);
00545         }
00546         break;
00547       }
00548     }
00549   }
00550 
00551   virtual void OnHundredthTick()
00552   {
00553     this->SetDirty();
00554   }
00555 
00556   virtual void OnResize(Point new_size, Point delta)
00557   {
00558     this->vscroll.cap += delta.y / 10;
00559   }
00560 
00561   virtual void OnInvalidateData(int data)
00562   {
00563     if (data == 0) {
00564       this->towns.ForceRebuild();
00565     } else {
00566       this->towns.ForceResort();
00567     }
00568   }
00569 };
00570 
00571 Listing TownDirectoryWindow::last_sorting = {false, 0};
00572 const Town *TownDirectoryWindow::last_town = NULL;
00573 
00574 /* Available town directory sorting functions */
00575 GUITownList::SortFunction * const TownDirectoryWindow::sorter_funcs[] = {
00576   &TownNameSorter,
00577   &TownPopulationSorter,
00578 };
00579 
00580 static const WindowDesc _town_directory_desc = {
00581   WDP_AUTO, WDP_AUTO, 208, 202, 208, 202,
00582   WC_TOWN_DIRECTORY, WC_NONE,
00583   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
00584   _town_directory_widgets,
00585 };
00586 
00587 void ShowTownDirectory()
00588 {
00589   if (BringWindowToFrontById(WC_TOWN_DIRECTORY, 0)) return;
00590   new TownDirectoryWindow(&_town_directory_desc);
00591 }
00592 
00593 void CcBuildTown(bool success, TileIndex tile, uint32 p1, uint32 p2)
00594 {
00595   if (success) {
00596     SndPlayTileFx(SND_1F_SPLAT, tile);
00597     if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
00598   }
00599 }
00600 
00601 static const Widget _scen_edit_town_gen_widgets[] = {
00602 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_DARK_GREEN,    0,    10,     0,    13, STR_00C5,                 STR_018B_CLOSE_WINDOW},
00603 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_DARK_GREEN,   11,   147,     0,    13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
00604 {  WWT_STICKYBOX,   RESIZE_NONE,  COLOUR_DARK_GREEN,  148,   159,     0,    13, 0x0,                      STR_STICKY_BUTTON},
00605 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_DARK_GREEN,    0,   159,    14,   161, 0x0,                      STR_NULL},
00606 
00607 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,   157,    16,    27, STR_0234_NEW_TOWN,        STR_0235_CONSTRUCT_NEW_TOWN},
00608 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,   157,    29,    40, STR_023D_RANDOM_TOWN,     STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION},
00609 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,   157,    42,    53, STR_MANY_RANDOM_TOWNS,    STR_RANDOM_TOWNS_TIP},
00610 
00611 {      WWT_LABEL,   RESIZE_NONE,  COLOUR_DARK_GREEN,    0,   147,    54,    67, STR_02A5_TOWN_SIZE,          STR_NULL},
00612 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,    79,    68,    79, STR_02A1_SMALL,              STR_02A4_SELECT_TOWN_SIZE},
00613 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,         80,   157,    68,    79, STR_02A2_MEDIUM,             STR_02A4_SELECT_TOWN_SIZE},
00614 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,    79,    81,    92, STR_02A3_LARGE,              STR_02A4_SELECT_TOWN_SIZE},
00615 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,         80,   157,    81,    92, STR_SELECT_TOWN_SIZE_RANDOM, STR_02A4_SELECT_TOWN_SIZE},
00616 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,   157,    96,   107, STR_SCENARIO_EDITOR_CITY,    STR_SCENARIO_EDITOR_CITY_TOOLTIP},
00617 
00618 {      WWT_LABEL,   RESIZE_NONE,  COLOUR_DARK_GREEN,    0,   147,   108,   121, STR_TOWN_ROAD_LAYOUT,           STR_NULL},
00619 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,    79,   122,   133, STR_SELECT_LAYOUT_ORIGINAL,     STR_SELECT_TOWN_ROAD_LAYOUT},
00620 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,         80,   157,   122,   133, STR_SELECT_LAYOUT_BETTER_ROADS, STR_SELECT_TOWN_ROAD_LAYOUT},
00621 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,    79,   135,   146, STR_SELECT_LAYOUT_2X2_GRID,     STR_SELECT_TOWN_ROAD_LAYOUT},
00622 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,         80,   157,   135,   146, STR_SELECT_LAYOUT_3X3_GRID,     STR_SELECT_TOWN_ROAD_LAYOUT},
00623 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,          2,   157,   148,   159, STR_SELECT_LAYOUT_RANDOM,       STR_SELECT_TOWN_ROAD_LAYOUT},
00624 
00625 {   WIDGETS_END},
00626 };
00627 
00628 struct ScenarioEditorTownGenerationWindow : Window
00629 {
00630 private:
00631   enum TownScenarioEditorWidget {
00632     TSEW_NEWTOWN = 4,
00633     TSEW_RANDOMTOWN,
00634     TSEW_MANYRANDOMTOWNS,
00635     TSEW_TOWNSIZE,
00636     TSEW_SIZE_SMALL,
00637     TSEW_SIZE_MEDIUM,
00638     TSEW_SIZE_LARGE,
00639     TSEW_SIZE_RANDOM,
00640     TSEW_CITY,
00641     TSEW_TOWNLAYOUT,
00642     TSEW_LAYOUT_ORIGINAL,
00643     TSEW_LAYOUT_BETTER,
00644     TSEW_LAYOUT_GRID2,
00645     TSEW_LAYOUT_GRID3,
00646     TSEW_LAYOUT_RANDOM,
00647   };
00648 
00649   static TownSize town_size;
00650   static bool city;
00651   static TownLayout town_layout;
00652 
00653 public:
00654   ScenarioEditorTownGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
00655   {
00656     this->FindWindowPlacementAndResize(desc);
00657     town_layout = _settings_game.economy.town_layout;
00658     city = false;
00659     this->UpdateButtons();
00660   }
00661 
00662   void UpdateButtons()
00663   {
00664     for (int i = TSEW_SIZE_SMALL; i <= TSEW_SIZE_RANDOM; i++) {
00665       this->SetWidgetLoweredState(i, i == TSEW_SIZE_SMALL + town_size);
00666     }
00667 
00668     this->SetWidgetLoweredState(TSEW_CITY, city);
00669 
00670     for (int i = TSEW_LAYOUT_ORIGINAL; i <= TSEW_LAYOUT_RANDOM; i++) {
00671       this->SetWidgetLoweredState(i, i == TSEW_LAYOUT_ORIGINAL + town_layout);
00672     }
00673 
00674     this->SetDirty();
00675   }
00676 
00677   virtual void OnPaint()
00678   {
00679     this->DrawWidgets();
00680   }
00681 
00682   virtual void OnClick(Point pt, int widget)
00683   {
00684     switch (widget) {
00685       case TSEW_NEWTOWN:
00686         HandlePlacePushButton(this, TSEW_NEWTOWN, SPR_CURSOR_TOWN, VHM_RECT, PlaceProc_Town);
00687         break;
00688 
00689       case TSEW_RANDOMTOWN: {
00690         this->HandleButtonClick(TSEW_RANDOMTOWN);
00691         _generating_world = true;
00692         UpdateNearestTownForRoadTiles(true);
00693         const Town *t = CreateRandomTown(20, town_size, city, town_layout);
00694         UpdateNearestTownForRoadTiles(false);
00695         _generating_world = false;
00696 
00697         if (t == NULL) {
00698           ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
00699         } else {
00700           ScrollMainWindowToTile(t->xy);
00701         }
00702       } break;
00703 
00704       case TSEW_MANYRANDOMTOWNS:
00705         this->HandleButtonClick(TSEW_MANYRANDOMTOWNS);
00706 
00707         _generating_world = true;
00708         UpdateNearestTownForRoadTiles(true);
00709         if (!GenerateTowns(town_layout)) {
00710           ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
00711         }
00712         UpdateNearestTownForRoadTiles(false);
00713         _generating_world = false;
00714         break;
00715 
00716       case TSEW_SIZE_SMALL: case TSEW_SIZE_MEDIUM: case TSEW_SIZE_LARGE: case TSEW_SIZE_RANDOM:
00717         town_size = (TownSize)(widget - TSEW_SIZE_SMALL);
00718         this->UpdateButtons();
00719         break;
00720 
00721       case TSEW_CITY:
00722         city ^= true;
00723         this->SetWidgetLoweredState(TSEW_CITY, city);
00724         this->SetDirty();
00725         break;
00726 
00727       case TSEW_LAYOUT_ORIGINAL: case TSEW_LAYOUT_BETTER: case TSEW_LAYOUT_GRID2:
00728       case TSEW_LAYOUT_GRID3: case TSEW_LAYOUT_RANDOM:
00729         town_layout = (TownLayout)(widget - TSEW_LAYOUT_ORIGINAL);
00730         this->UpdateButtons();
00731         break;
00732     }
00733   }
00734 
00735   virtual void OnTimeout()
00736   {
00737     this->RaiseWidget(TSEW_RANDOMTOWN);
00738     this->RaiseWidget(TSEW_MANYRANDOMTOWNS);
00739     this->SetDirty();
00740   }
00741 
00742   virtual void OnPlaceObject(Point pt, TileIndex tile)
00743   {
00744     _place_proc(tile);
00745   }
00746 
00747   virtual void OnPlaceObjectAbort()
00748   {
00749     this->RaiseButtons();
00750     this->UpdateButtons();
00751   }
00752 
00753   static void PlaceProc_Town(TileIndex tile)
00754   {
00755     DoCommandP(tile, town_size | city << 2 | town_layout << 3, 0, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE), CcBuildTown);
00756   }
00757 };
00758 
00759 TownSize ScenarioEditorTownGenerationWindow::town_size = TS_MEDIUM; // select medium-sized towns per default
00760 bool ScenarioEditorTownGenerationWindow::city;
00761 TownLayout ScenarioEditorTownGenerationWindow::town_layout;
00762 
00763 static const WindowDesc _scen_edit_town_gen_desc = {
00764   WDP_AUTO, WDP_AUTO, 160, 162, 160, 162,
00765   WC_SCEN_TOWN_GEN, WC_NONE,
00766   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
00767   _scen_edit_town_gen_widgets,
00768 };
00769 
00770 void ShowBuildTownWindow()
00771 {
00772   if (_game_mode != GM_EDITOR && !IsValidCompanyID(_local_company)) return;
00773   AllocateWindowDescFront<ScenarioEditorTownGenerationWindow>(&_scen_edit_town_gen_desc, 0);
00774 }

Generated on Mon Feb 16 23:12:12 2009 for openttd by  doxygen 1.5.6