# statusbar_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: statusbar_gui.cpp 15424 2009-02-09 01:22:29Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "settings_type.h"
    00008 #include "date_func.h"
    00009 #include "gfx_func.h"
    00010 #include "news_func.h"
    00011 #include "company_func.h"
    00012 #include "string_func.h"
    00013 #include "strings_func.h"
    00014 #include "company_base.h"
    00015 #include "tilehighlight_func.h"
    00016 #include "news_gui.h"
    00017 #include "company_gui.h"
    00018 #include "window_gui.h"
    00019 #include "variables.h"
    00020 #include "window_func.h"
    00021 #include "statusbar_gui.h"
    00022
    00023 #include "table/strings.h"
    00024 #include "table/sprites.h"
    00025
    00026 static bool DrawScrollingStatusText(const NewsItem *ni, int pos, int width)
    00027 {
    00028   CopyInDParam(0, ni->params, lengthof(ni->params));
    00029   StringID str = ni->string_id;
    00030
    00031   char buf[512];
    00032   GetString(buf, str, lastof(buf));
    00033   const char *s = buf;
    00034
    00035   char buffer[256];
    00036   char *d = buffer;
    00037   const char *last = lastof(buffer);
    00038
    00039   for (;;) {
    00040     WChar c = Utf8Consume(&s);
    00041     if (c == 0) {
    00042       break;
    00043     } else if (c == 0x0D) {
    00044       if (d + 4 >= last) break;
    00045       d[0] = d[1] = d[2] = d[3] = ' ';
    00046       d += 4;
    00047     } else if (IsPrintable(c)) {
    00048       if (d + Utf8CharLen(c) >= last) break;
    00049       d += Utf8Encode(d, c);
    00050     }
    00051   }
    00052   *d = '\0';
    00053
    00054   DrawPixelInfo tmp_dpi;
    00055   if (!FillDrawPixelInfo(&tmp_dpi, 141, 1, width, 11)) return true;
    00056
    00057   DrawPixelInfo *old_dpi = _cur_dpi;
    00058   _cur_dpi = &tmp_dpi;
    00059
    00060   int x = DoDrawString(buffer, pos, 0, TC_LIGHT_BLUE);
    00061   _cur_dpi = old_dpi;
    00062
    00063   return x > 0;
    00064 }
    00065
    00066 struct StatusBarWindow : Window {
    00067   bool saving;
    00068   int ticker_scroll;
    00069   int reminder_timeout;
    00070
    00071   enum {
    00072     TICKER_START   =   360,
    00073     TICKER_STOP    = -1280,
    00074     REMINDER_START =    91,
    00075     REMINDER_STOP  =     0,
    00076     COUNTER_STEP   =     2,
    00077   };
    00078
    00079   enum StatusbarWidget {
    00080     SBW_LEFT,
    00081     SBW_MIDDLE,
    00082     SBW_RIGHT,
    00083   };
    00084
    00085   StatusBarWindow(const WindowDesc *desc) : Window(desc)
    00086   {
    00087     CLRBITS(this->flags4, WF_WHITE_BORDER_MASK);
    00088     this->ticker_scroll    =   TICKER_STOP;
    00089     this->reminder_timeout = REMINDER_STOP;
    00090
    00091     this->FindWindowPlacementAndResize(desc);
    00092   }
    00093
    00094   virtual void OnPaint()
    00095   {
    00096     const Company *c = (_local_company == COMPANY_SPECTATOR) ? NULL : GetCompany(_local_company);
    00097
    00098     this->DrawWidgets();
    00099     SetDParam(0, _date);
    00100     DrawStringCentered(70, 1, (_pause_game || _settings_client.gui.status_long_date) ? STR_00AF : STR_00AE, TC_FROMSTRING);
    00101
    00102     if (c != NULL) {
    00103       /* Draw company money */
    00104       SetDParam(0, c->money);
    00105       DrawStringCentered(this->widget[SBW_RIGHT].left + 70, 1, STR_0004, TC_FROMSTRING);
    00106     }
    00107
    00108     /* Draw status bar */
    00109     if (this->saving) { // true when saving is active
    00110       DrawStringCenteredTruncated(this->widget[SBW_MIDDLE].left + 1, this->widget[SBW_MIDDLE].right - 1, 1, STR_SAVING_GAME, TC_FROMSTRING);
    00111     } else if (_do_autosave) {
    00112       DrawStringCenteredTruncated(this->widget[SBW_MIDDLE].left + 1, this->widget[SBW_MIDDLE].right - 1, 1, STR_032F_AUTOSAVE, TC_FROMSTRING);
    00113     } else if (_pause_game) {
    00114       DrawStringCenteredTruncated(this->widget[SBW_MIDDLE].left + 1, this->widget[SBW_MIDDLE].right - 1, 1, STR_0319_PAUSED, TC_FROMSTRING);
    00115     } else if (this->ticker_scroll > TICKER_STOP && FindWindowById(WC_NEWS_WINDOW, 0) == NULL && _statusbar_news_item.string_id != 0) {
    00116       /* Draw the scrolling news text */
    00117       if (!DrawScrollingStatusText(&_statusbar_news_item, this->ticker_scroll, this->widget[SBW_MIDDLE].right - this->widget[SBW_MIDDLE].left - 2)) {
    00118         this->ticker_scroll = TICKER_STOP;
    00119         if (c != NULL) {
    00120           /* This is the default text */
    00121           SetDParam(0, c->index);
    00122           DrawStringCenteredTruncated(this->widget[SBW_MIDDLE].left + 1, this->widget[SBW_MIDDLE].right - 1, 1, STR_02BA, TC_FROMSTRING);
    00123         }
    00124       }
    00125     } else {
    00126       if (c != NULL) {
    00127         /* This is the default text */
    00128         SetDParam(0, c->index);
    00129         DrawStringCenteredTruncated(this->widget[SBW_MIDDLE].left + 1, this->widget[SBW_MIDDLE].right - 1, 1, STR_02BA, TC_FROMSTRING);
    00130       }
    00131     }
    00132
    00133     if (this->reminder_timeout > 0) DrawSprite(SPR_BLOT, PALETTE_TO_RED, this->widget[SBW_MIDDLE].right - 11, 2);
    00134   }
    00135
    00136   virtual void OnInvalidateData(int data)
    00137   {
    00138     switch (data) {
    00139       default: NOT_REACHED();
    00140       case SBI_SAVELOAD_START:  this->saving = true;  break;
    00141       case SBI_SAVELOAD_FINISH: this->saving = false; break;
    00142       case SBI_SHOW_TICKER:     this->ticker_scroll    =   TICKER_START; break;
    00143       case SBI_SHOW_REMINDER:   this->reminder_timeout = REMINDER_START; break;
    00144       case SBI_NEWS_DELETED:
    00145         this->ticker_scroll    =   TICKER_STOP; // reset ticker ...
    00146         this->reminder_timeout = REMINDER_STOP; // ... and reminder
    00147         break;
    00148     }
    00149   }
    00150
    00151   virtual void OnClick(Point pt, int widget)
    00152   {
    00153     switch (widget) {
    00154       case SBW_MIDDLE: ShowLastNewsMessage(); break;
    00155       case SBW_RIGHT:  if (_local_company != COMPANY_SPECTATOR) ShowCompanyFinances(_local_company); break;
    00156       default: ResetObjectToPlace();
    00157     }
    00158   }
    00159
    00160   virtual void OnTick()
    00161   {
    00162     if (_pause_game) return;
    00163
    00164     if (this->ticker_scroll > TICKER_STOP) { // Scrolling text
    00165       this->ticker_scroll -= COUNTER_STEP;
    00166       this->InvalidateWidget(SBW_MIDDLE);
    00167     }
    00168
    00169     if (this->reminder_timeout > REMINDER_STOP) { // Red blot to show there are new unread newsmessages
    00170       this->reminder_timeout -= COUNTER_STEP;
    00171     } else if (this->reminder_timeout < REMINDER_STOP) {
    00172       this->reminder_timeout = REMINDER_STOP;
    00173       this->InvalidateWidget(SBW_MIDDLE);
    00174     }
    00175   }
    00176 };
    00177
    00178 static const Widget _main_status_widgets[] = {
    00179 {      WWT_PANEL,   RESIZE_NONE,   COLOUR_GREY,     0,   139,     0,    11, 0x0, STR_NULL},
    00180 {    WWT_PUSHBTN,   RESIZE_RIGHT,  COLOUR_GREY,   140,   179,     0,    11, 0x0, STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS},
    00181 {    WWT_PUSHBTN,   RESIZE_LR,     COLOUR_GREY,   180,   319,     0,    11, 0x0, STR_NULL},
    00182 {   WIDGETS_END},
    00183 };
    00184
    00185 static WindowDesc _main_status_desc = {
    00186   WDP_CENTER, 0, 320, 12, 640, 12,
    00187   WC_STATUS_BAR, WC_NONE,
    00188   WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_NO_FOCUS,
    00189   _main_status_widgets,
    00190 };
    00191
    00195 bool IsNewsTickerShown()
    00196 {
    00197   const StatusBarWindow *w = dynamic_cast<StatusBarWindow*>(FindWindowById(WC_STATUS_BAR, 0));
    00198   return w != NULL && w->ticker_scroll > StatusBarWindow::TICKER_STOP;
    00199 }
    00200
    00201 void ShowStatusBar()
    00202 {
    00203   _main_status_desc.top = _screen.height - 12;
    00204   new StatusBarWindow(&_main_status_desc);
    00205 }