goal_gui.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "industry.h"
00014 #include "town.h"
00015 #include "window_gui.h"
00016 #include "strings_func.h"
00017 #include "date_func.h"
00018 #include "viewport_func.h"
00019 #include "gfx_func.h"
00020 #include "gui.h"
00021 #include "goal_base.h"
00022 #include "core/geometry_func.hpp"
00023 #include "company_func.h"
00024 #include "command_func.h"
00025 
00026 #include "widgets/goal_widget.h"
00027 
00028 #include "table/strings.h"
00029 
00030 struct GoalListWindow : Window {
00031   Scrollbar *vscroll;
00032 
00033   GoalListWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
00034   {
00035     this->CreateNestedTree(desc);
00036     this->vscroll = this->GetScrollbar(WID_GL_SCROLLBAR);
00037     this->FinishInitNested(desc, window_number);
00038     this->OnInvalidateData(0);
00039   }
00040 
00041   virtual void OnClick(Point pt, int widget, int click_count)
00042   {
00043     if (widget != WID_GL_PANEL) return;
00044 
00045     int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GL_PANEL, WD_FRAMERECT_TOP);
00046     int num = 0;
00047     const Goal *s;
00048     FOR_ALL_GOALS(s) {
00049       if (s->company == INVALID_COMPANY) {
00050         y--;
00051         if (y == 0) {
00052           this->HandleClick(s);
00053           return;
00054         }
00055         num++;
00056       }
00057     }
00058 
00059     if (num == 0) {
00060       y--; // "None"
00061       if (y < 0) return;
00062     }
00063 
00064     y -= 2; // "Company specific goals:"
00065     if (y < 0) return;
00066 
00067     FOR_ALL_GOALS(s) {
00068       if (s->company == _local_company) {
00069         y--;
00070         if (y == 0) {
00071           this->HandleClick(s);
00072           return;
00073         }
00074       }
00075     }
00076   }
00077 
00078   void HandleClick(const Goal *s)
00079   {
00080     /* determine dst coordinate for goal and try to scroll to it */
00081     TileIndex xy;
00082     switch (s->type) {
00083       case GT_NONE: return;
00084       case GT_COMPANY: return;
00085 
00086       case GT_TILE:
00087         if (!IsValidTile(s->dst)) return;
00088         xy = s->dst;
00089         break;
00090 
00091       case GT_INDUSTRY:
00092         if (!Industry::IsValidID(s->dst)) return;
00093         xy = Industry::Get(s->dst)->location.tile;
00094         break;
00095 
00096       case GT_TOWN:
00097         if (!Town::IsValidID(s->dst)) return;
00098         xy = Town::Get(s->dst)->xy;
00099         break;
00100 
00101       default: NOT_REACHED();
00102     }
00103 
00104     if (_ctrl_pressed) {
00105       ShowExtraViewPortWindow(xy);
00106     } else {
00107       ScrollMainWindowToTile(xy);
00108     }
00109   }
00110 
00115   uint CountLines()
00116   {
00117     /* Count number of (non) awarded goals */
00118     uint num_global = 0;
00119     uint num_company = 0;
00120     const Goal *s;
00121     FOR_ALL_GOALS(s) {
00122       if (s->company == INVALID_COMPANY) {
00123         num_global++;
00124       } else if (s->company == _local_company) {
00125         num_company++;
00126       }
00127     }
00128 
00129     /* Count the 'none' lines */
00130     if (num_global  == 0) num_global = 1;
00131     if (num_company == 0) num_company = 1;
00132 
00133     /* Global, company and an empty line before the accepted ones. */
00134     return 3 + num_global + num_company;
00135   }
00136 
00137   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00138   {
00139     if (widget != WID_GL_PANEL) return;
00140     Dimension d = maxdim(GetStringBoundingBox(STR_GOALS_GLOBAL_TITLE), GetStringBoundingBox(STR_GOALS_COMPANY_TITLE));
00141 
00142     resize->height = d.height;
00143 
00144     d.height *= 5;
00145     d.width += padding.width + WD_FRAMERECT_RIGHT + WD_FRAMERECT_LEFT;
00146     d.height += padding.height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
00147     *size = maxdim(*size, d);
00148   }
00149 
00150   virtual void DrawWidget(const Rect &r, int widget) const
00151   {
00152     if (widget != WID_GL_PANEL) return;
00153 
00154     YearMonthDay ymd;
00155     ConvertDateToYMD(_date, &ymd);
00156 
00157     int right = r.right - WD_FRAMERECT_RIGHT;
00158     int y = r.top + WD_FRAMERECT_TOP;
00159     int x = r.left + WD_FRAMERECT_LEFT;
00160 
00161     int pos = -this->vscroll->GetPosition();
00162     const int cap = this->vscroll->GetCapacity();
00163 
00164     /* Section for drawing the global goals */
00165     if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_GLOBAL_TITLE);
00166     pos++;
00167 
00168     uint num = 0;
00169     const Goal *s;
00170     FOR_ALL_GOALS(s) {
00171       if (s->company == INVALID_COMPANY) {
00172         if (IsInsideMM(pos, 0, cap)) {
00173           /* Display the goal */
00174           SetDParamStr(0, s->text);
00175           DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_TEXT);
00176         }
00177         pos++;
00178         num++;
00179       }
00180     }
00181 
00182     if (num == 0) {
00183       if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_NONE);
00184       pos++;
00185     }
00186 
00187     /* Section for drawing the company goals */
00188     pos++;
00189     if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_COMPANY_TITLE);
00190     pos++;
00191     num = 0;
00192 
00193     FOR_ALL_GOALS(s) {
00194       if (s->company == _local_company) {
00195         if (IsInsideMM(pos, 0, cap)) {
00196           /* Display the goal */
00197           SetDParamStr(0, s->text);
00198           DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_TEXT);
00199         }
00200         pos++;
00201         num++;
00202       }
00203     }
00204 
00205     if (num == 0) {
00206       if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_NONE);
00207       pos++;
00208     }
00209   }
00210 
00211   virtual void OnResize()
00212   {
00213     this->vscroll->SetCapacityFromWidget(this, WID_GL_PANEL);
00214   }
00215 
00221   virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
00222   {
00223     if (!gui_scope) return;
00224     this->vscroll->SetCount(this->CountLines());
00225   }
00226 };
00227 
00228 static const NWidgetPart _nested_goals_list_widgets[] = {
00229   NWidget(NWID_HORIZONTAL),
00230     NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
00231     NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GOALS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00232     NWidget(WWT_SHADEBOX, COLOUR_BROWN),
00233     NWidget(WWT_STICKYBOX, COLOUR_BROWN),
00234   EndContainer(),
00235   NWidget(NWID_HORIZONTAL),
00236     NWidget(WWT_PANEL, COLOUR_BROWN, WID_GL_PANEL), SetDataTip(0x0, STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER), SetResize(1, 1), SetScrollbar(WID_GL_SCROLLBAR), EndContainer(),
00237     NWidget(NWID_VERTICAL),
00238       NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_GL_SCROLLBAR),
00239       NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
00240     EndContainer(),
00241   EndContainer(),
00242 };
00243 
00244 static const WindowDesc _goals_list_desc(
00245   WDP_AUTO, 500, 127,
00246   WC_GOALS_LIST, WC_NONE,
00247   0,
00248   _nested_goals_list_widgets, lengthof(_nested_goals_list_widgets)
00249 );
00250 
00251 void ShowGoalsList()
00252 {
00253   AllocateWindowDescFront<GoalListWindow>(&_goals_list_desc, 0);
00254 }
00255 
00256 
00257 
00258 struct GoalQuestionWindow : Window {
00259   char *question;
00260   int buttons;
00261   int button[3];
00262 
00263   GoalQuestionWindow(const WindowDesc *desc, WindowNumber window_number, uint32 button_mask, const char *question) : Window()
00264   {
00265     this->question = strdup(question);
00266 
00267     /* Figure out which buttons we have to enable */
00268     int bit;
00269     int n = 0;
00270     FOR_EACH_SET_BIT(bit, button_mask) {
00271       if (bit >= GOAL_QUESTION_BUTTON_COUNT) break;
00272       this->button[n++] = bit;
00273       if (n == 3) break;
00274     }
00275     this->buttons = n;
00276     assert(this->buttons > 0 && this->buttons < 4);
00277 
00278     this->CreateNestedTree(desc);
00279     this->GetWidget<NWidgetStacked>(WID_GQ_BUTTONS)->SetDisplayedPlane(this->buttons - 1);
00280     this->FinishInitNested(desc, window_number);
00281   }
00282 
00283   ~GoalQuestionWindow()
00284   {
00285     free(this->question);
00286   }
00287 
00288   virtual void SetStringParameters(int widget) const
00289   {
00290     switch (widget) {
00291       case WID_GQ_BUTTON_1:
00292         SetDParam(0, STR_GOAL_QUESTION_BUTTON_CANCEL + this->button[0]);
00293         break;
00294 
00295       case WID_GQ_BUTTON_2:
00296         SetDParam(0, STR_GOAL_QUESTION_BUTTON_CANCEL + this->button[1]);
00297         break;
00298 
00299       case WID_GQ_BUTTON_3:
00300         SetDParam(0, STR_GOAL_QUESTION_BUTTON_CANCEL + this->button[2]);
00301         break;
00302     }
00303   }
00304 
00305   virtual void OnClick(Point pt, int widget, int click_count)
00306   {
00307     switch (widget) {
00308       case WID_GQ_BUTTON_1:
00309         DoCommandP(0, this->window_number, this->button[0], CMD_GOAL_QUESTION_ANSWER);
00310         delete this;
00311         break;
00312 
00313       case WID_GQ_BUTTON_2:
00314         DoCommandP(0, this->window_number, this->button[1], CMD_GOAL_QUESTION_ANSWER);
00315         delete this;
00316         break;
00317 
00318       case WID_GQ_BUTTON_3:
00319         DoCommandP(0, this->window_number, this->button[2], CMD_GOAL_QUESTION_ANSWER);
00320         delete this;
00321         break;
00322     }
00323   }
00324 
00325   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00326   {
00327     if (widget != WID_GQ_QUESTION) return;
00328 
00329     SetDParamStr(0, this->question);
00330     size->height = GetStringHeight(STR_JUST_RAW_STRING, size->width) + WD_PAR_VSEP_WIDE;
00331   }
00332 
00333   virtual void DrawWidget(const Rect &r, int widget) const
00334   {
00335     if (widget != WID_GQ_QUESTION) return;
00336 
00337     SetDParamStr(0, this->question);
00338     DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK, SA_TOP | SA_HOR_CENTER);
00339   }
00340 };
00341 
00342 static const NWidgetPart _nested_goal_question_widgets[] = {
00343   NWidget(NWID_HORIZONTAL),
00344     NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
00345     NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_GOAL_QUESTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00346   EndContainer(),
00347   NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
00348     NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GQ_QUESTION), SetMinimalSize(300, 0), SetPadding(8, 8, 8, 8), SetFill(1, 0),
00349     NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GQ_BUTTONS),
00350       NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(85, 10, 85),
00351         NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_GQ_BUTTON_1), SetDataTip(STR_BLACK_STRING, STR_NULL), SetFill(1, 0),
00352       EndContainer(),
00353       NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(65, 10, 65),
00354         NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_GQ_BUTTON_1), SetDataTip(STR_BLACK_STRING, STR_NULL), SetFill(1, 0),
00355         NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_GQ_BUTTON_2), SetDataTip(STR_BLACK_STRING, STR_NULL), SetFill(1, 0),
00356       EndContainer(),
00357       NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(25, 10, 25),
00358         NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_GQ_BUTTON_1), SetDataTip(STR_BLACK_STRING, STR_NULL), SetFill(1, 0),
00359         NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_GQ_BUTTON_2), SetDataTip(STR_BLACK_STRING, STR_NULL), SetFill(1, 0),
00360         NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_GQ_BUTTON_3), SetDataTip(STR_BLACK_STRING, STR_NULL), SetFill(1, 0),
00361       EndContainer(),
00362     EndContainer(),
00363     NWidget(NWID_SPACER), SetMinimalSize(0, 8),
00364   EndContainer(),
00365 };
00366 
00367 static const WindowDesc _goal_question_list_desc(
00368   WDP_CENTER, 0, 0,
00369   WC_GOAL_QUESTION, WC_NONE,
00370   WDF_CONSTRUCTION,
00371   _nested_goal_question_widgets, lengthof(_nested_goal_question_widgets)
00372 );
00373 
00374 
00375 void ShowGoalQuestion(uint16 id, uint32 button_mask, const char *question)
00376 {
00377   new GoalQuestionWindow(&_goal_question_list_desc, id, button_mask, question);
00378 }