# watch_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: watch_gui.cpp  17678 2009-10-07 20:54:05  muxy $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "watch_gui.h"
    00007 #include "widget_type.h"
    00008 #include "gfx_type.h"
    00009 #include "gfx_func.h"
    00010 #include "company_base.h"
    00011 #include "company_gui.h"
    00012 #include "viewport_func.h"
    00013 #include "window_func.h"
    00014 #include "strings_func.h"
    00015 #include "zoom_func.h"
    00016 #include "map_func.h"
    00017
    00018 #include "network/network.h"
    00019 #include "network/network_func.h"
    00020 #include "network/network_base.h"
    00021
    00022 #include "table/sprites.h"
    00023 #include "table/strings.h"
    00024
    00030 static NWidgetBase *MakeCompanyButtons(int *biggest_index)
    00031 {
    00032   NWidgetHorizontal *widget_container_horiz = NULL;         // Storage for all cols.
    00033   NWidgetVertical *widget_container_company = NULL;         // Storage for company Col.
    00034   NWidgetVertical *widget_container_hasclient = NULL;       // Storage for Has Client Blot.
    00035   NWidgetVertical *widget_container_activity = NULL;        // Storage for Activity Blot.
    00036   //NWidgetVertical *widget_container_action1 = NULL;         // Storage for Action 1
    00037
    00038   widget_container_horiz = new NWidgetHorizontal();
    00039   widget_container_company = new NWidgetVertical();
    00040   widget_container_hasclient  = new NWidgetVertical();
    00041   widget_container_activity = new NWidgetVertical();
    00042   //widget_container_action1 = new NWidgetVertical();
    00043
    00044   Dimension company_sprite_size = GetSpriteSize(SPR_COMPANY_ICON);
    00045   company_sprite_size.width  += WD_MATRIX_LEFT + WD_MATRIX_RIGHT;
    00046   company_sprite_size.height += WD_MATRIX_TOP + WD_MATRIX_BOTTOM + 1; // 1 for the 'offset' of being pressed
    00047
    00048   Dimension blot_sprite_size = GetSpriteSize(SPR_BLOT);
    00049   blot_sprite_size.width  += WD_MATRIX_LEFT + WD_MATRIX_RIGHT;
    00050   blot_sprite_size.height += WD_MATRIX_TOP + WD_MATRIX_BOTTOM + 1; // 1 for the 'offset' of being pressed
    00051
    00052
    00053   for (int company_num = COMPANY_FIRST; company_num < MAX_COMPANIES; company_num++) {
    00054
    00055     /* Manage Company Buttons */
    00056     NWidgetBackground *company_panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, EWW_PB_COMPANY_FIRST + company_num);
    00057     company_panel->SetMinimalSize(company_sprite_size.width, company_sprite_size.height);
    00058     company_panel->SetResize(0, 0);
    00059     company_panel->SetFill(1, 0);
    00060     company_panel->SetDataTip(0x0, STR_WATCH_CLICK_TO_WATCH_COMPANY);
    00061     widget_container_company->Add(company_panel);
    00062
    00063     /* Manage Has Client Blot */
    00064     NWidgetBackground *hasclient_panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, EWW_HAS_CLIENT_FIRST + company_num);
    00065     company_panel->SetMinimalSize(blot_sprite_size.width, blot_sprite_size.height);
    00066     company_panel->SetResize(0, 0);
    00067     company_panel->SetFill(1, 0);
    00068     widget_container_hasclient->Add(hasclient_panel);
    00069
    00070     /* Manage Activit Blot */
    00071     /*
    00072     NWidgetBackground *activity_panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, EWW_ACTIVITY_FIRST + company_num);
    00073     company_panel->SetMinimalSize(blot_sprite_size.width, blot_sprite_size.height);
    00074     company_panel->SetResize(0, 0);
    00075     company_panel->SetFill(1, 0);
    00076     widget_container_activity->Add(activity_panel);
    00077     */
    00078
    00079     /* Button Action1 */
    00080     /*
    00081     NWidgetBackground *action1_panel =  new NWidgetBackground(WWT_PANEL, COLOUR_GREY, EWW_PB_ACTION1_FIRST + company_num);
    00082     company_panel->SetResize(0, 0);
    00083     company_panel->SetFill(1, 0);
    00084     widget_container_action1->Add(action1_panel);
    00085     */
    00086   }
    00087
    00088   /* Add the verticals widgets to the horizontal container */
    00089   widget_container_horiz->Add(widget_container_company);
    00090   widget_container_horiz->Add(widget_container_hasclient);
    00091   /* widget_container_horiz->Add(widget_container_activity); */
    00092   //widget_container_horiz->Add(widget_container_action1);
    00093
    00094   /* return the horizontal widget container */
    00095   return widget_container_horiz;
    00096 }
    00097
    00098
    00104 static const NWidgetPart _nested_watch_company_widgets[] = {
    00105   /* Title Bar with close box, title, shade and stick boxes */
    00106   NWidget(NWID_HORIZONTAL),
    00107     NWidget(WWT_CLOSEBOX, COLOUR_GREY),
    00108     NWidget(WWT_CAPTION, COLOUR_GREY, EWW_CAPTION), SetDataTip(STR_WATCH_WINDOW_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00109     NWidget(WWT_SHADEBOX, COLOUR_GREY),
    00110     NWidget(WWT_STICKYBOX, COLOUR_GREY),
    00111   EndContainer(),
    00112   NWidget(NWID_HORIZONTAL),
    00113     NWidget(NWID_VERTICAL),
    00114       NWidgetFunction(MakeCompanyButtons),
    00115       /* Buton Zoom Out, In, Scrollto */
    00116       NWidget(NWID_HORIZONTAL),
    00117         NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, EWW_ZOOMOUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
    00118         NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, EWW_ZOOMIN),  SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
    00119         NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, EWW_CENTER),  SetDataTip(SPR_CENTRE_VIEW_VEHICLE, STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT),
    00120         NWidget(WWT_PANEL, COLOUR_GREY, EWW_NEW_WINDOW),   SetDataTip(0, STR_WATCH_CLICK_NEW_WINDOW), EndContainer(),
    00121       EndContainer(),
    00122       /* Background panel for resize purpose */
    00123       NWidget(WWT_PANEL, COLOUR_GREY), SetResize(0, 1), EndContainer(),
    00124     EndContainer(),
    00125     /* Watch Pannel */
    00126     NWidget(WWT_PANEL, COLOUR_GREY),
    00127       NWidget(NWID_VIEWPORT, INVALID_COLOUR, EWW_WATCH), SetPadding(2, 2, 2, 2), SetResize(1, 1), SetFill(1, 1),
    00128     EndContainer(),
    00129   EndContainer(),
    00130   /* Status Bar with resize buton */
    00131   NWidget(NWID_HORIZONTAL),
    00132     NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
    00133     NWidget(WWT_RESIZEBOX, COLOUR_GREY),
    00134   EndContainer(),
    00135 };
    00136
    00140 static const WindowDesc _watch_company_desc(
    00141   WDP_AUTO, 300, 257,
    00142   WC_WATCH_COMPANY, WC_NONE,
    00143   WDF_UNCLICK_BUTTONS,
    00144   _nested_watch_company_widgets, lengthof(_nested_watch_company_widgets)
    00145 );
    00146
    00147 //static int WatchCompany::button1_state[MAX_COMPANIES];
    00148
    00154 WatchCompany::WatchCompany(const WindowDesc *desc, int window_number, CompanyID company_to_watch = INVALID_COMPANY) : Window()
    00155 {
    00156   this->watched_company = company_to_watch;
    00157
    00158   this->InitNested(desc, window_number);
    00159   this->owner = this->watched_company;
    00160
    00161   /* Reset activity and client count for all companies */
    00162   for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
    00163     this->company_activity[i] = 0;
    00164     this->company_count_client[i] = 0;
    00165   }
    00166
    00167   GetString(this->company_name, STR_JUST_NOTHING, lastof(this->company_name));
    00168
    00169   /* Init the viewport area */
    00170   NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(EWW_WATCH);
    00171   nvp->InitializeViewport(this, 0, ZOOM_LVL_NORMAL);
    00172
    00173   Point pt;
    00174   /* the main window with the main view */
    00175   const Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
    00176
    00177   /* center on same place as main window (zoom is maximum, no adjustment needed) */
    00178   pt.x = w->viewport->scrollpos_x + w->viewport->virtual_width / 2;
    00179   pt.y = w->viewport->scrollpos_y + w->viewport->virtual_height / 2;
    00180
    00181   this->viewport->scrollpos_x = pt.x - this->viewport->virtual_width / 2;
    00182   this->viewport->scrollpos_y = pt.y - this->viewport->virtual_height / 2;
    00183   this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x;
    00184   this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y;
    00185
    00186   if (this->watched_company != INVALID_COMPANY) {
    00187     Company *c = Company::Get( this->watched_company);
    00188     this->ScrollToTile(c->last_build_coordinate);
    00189   }
    00190   this->InvalidateData();
    00191 }
    00192
    00193 void WatchCompany::SetStringParameters(int widget) const
    00194 {
    00195   switch (widget) {
    00196     case EWW_CAPTION:
    00197       SetDParamStr(0, this->company_name);
    00198       break;
    00199   }
    00200 }
    00201
    00202 /*
    00203 void WatchCompany::OnPaint()
    00204 {
    00205   this->DrawWidgets();
    00206 }
    00207 */
    00208
    00209 void WatchCompany::DrawWidget(const Rect &r, int widget) const
    00210 {
    00211   /* draw the widget */
    00212   /* Company Button */
    00213   if (IsInsideMM(widget, EWW_PB_COMPANY_FIRST, EWW_PB_COMPANY_LAST + 1)) {
    00214     if (this->IsWidgetDisabled(widget)) return;
    00215     if ( Company::IsValidID( widget - EWW_PB_COMPANY_FIRST ) ) {
    00216         CompanyID cid = (CompanyID)(widget - (EWW_PB_COMPANY_FIRST));
    00217         int offset = (cid == this->watched_company) ? 1 : 0;
    00218         Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON);
    00219         DrawCompanyIcon(cid, (r.left + r.right - sprite_size.width) / 2 + offset, (r.top + r.bottom - sprite_size.height) / 2 + offset);
    00220     }
    00221     return;
    00222   }
    00223   /* Has Client Blot */
    00224   if (IsInsideMM( widget, EWW_HAS_CLIENT_FIRST, EWW_HAS_CLIENT_LAST + 1)) {
    00225     if (Company::IsValidID( widget-EWW_HAS_CLIENT_FIRST)) {
    00226       /* Draw the Blot only if Company Exists */
    00227       Dimension sprite_size = GetSpriteSize(SPR_BLOT);
    00228 #ifdef ENABLE_NETWORK
    00229       if (!_networking) { // Local game, draw the Blot
    00230         DrawSprite(SPR_BLOT, Company::IsValidAiID(widget-EWW_HAS_CLIENT_FIRST)?PALETTE_TO_ORANGE:PALETTE_TO_GREEN, (r.left + r.right - sprite_size.width) / 2, (r.top + r.bottom - sprite_size.height) / 2);
    00231       } else { // Network game, draw the blot according to company client count
    00232         DrawSprite(SPR_BLOT, this->company_count_client[widget-EWW_HAS_CLIENT_FIRST]>0?(company_activity[widget-EWW_HAS_CLIENT_FIRST]>0?PALETTE_TO_RED:PALETTE_TO_GREEN):PALETTE_TO_GREY, (r.left + r.right - sprite_size.width) / 2, (r.top + r.bottom - sprite_size.height) / 2);
    00233       }
    00234 #else
    00235       DrawSprite(SPR_BLOT, Company::IsValidAiID(widget-EWW_HAS_CLIENT_FIRST)?PALETTE_TO_ORANGE:PALETTE_TO_GREEN, (r.left + r.right - sprite_size.width) / 2, (r.top + r.bottom - sprite_size.height) / 2);
    00236 #endif
    00237     }
    00238   }
    00239   /* Activity Blot */
    00240   /*
    00241   if (IsInsideMM( widget, EWW_ACTIVITY_FIRST, EWW_ACTIVITY_LAST + 1)) {
    00242     if (Company::IsValidID(widget-EWW_ACTIVITY_FIRST)) {
    00243       // Draw the Blot only if Company Exists
    00244       Dimension sprite_size = GetSpriteSize(SPR_BLOT);
    00245       DrawSprite(SPR_BLOT, company_activity[widget-EWW_ACTIVITY_FIRST]>0?PALETTE_TO_RED:PALETTE_TO_GREY, (r.left + r.right - sprite_size.width) / 2, (r.top + r.bottom - sprite_size.height) / 2);
    00246     }
    00247   }
    00248   */
    00249 }
    00250
    00251 void WatchCompany::OnResize()
    00252 {
    00253   if (this->viewport != NULL) {
    00254     NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(EWW_WATCH);
    00255     nvp->UpdateViewportCoordinates(this);
    00256   }
    00257 }
    00258
    00259 void WatchCompany::OnScroll(Point delta)
    00260 {
    00261   const ViewPort *vp = IsPtInWindowViewport(this, _cursor.pos.x, _cursor.pos.y);
    00262   if (vp == NULL) return;
    00263
    00264   this->viewport->scrollpos_x += ScaleByZoom(delta.x, vp->zoom);
    00265   this->viewport->scrollpos_y += ScaleByZoom(delta.y, vp->zoom);
    00266   this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x;
    00267   this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y;
    00268 }
    00269
    00270 void WatchCompany::OnMouseWheel(int wheel)
    00271 {
    00272   ZoomInOrOutToCursorWindow(wheel < 0, this);
    00273 }
    00274
    00275 void WatchCompany::OnClick(Point pt, int widget, int click_count)
    00276 {
    00277   if (IsInsideMM(widget, EWW_PB_COMPANY_FIRST, EWW_PB_COMPANY_LAST + 1)) {
    00278     /* Click on Company Button */
    00279     if (!this->IsWidgetDisabled(widget)) {
    00280       if (this->watched_company != INVALID_COMPANY) {
    00281         /* Raise the watched company button  */
    00282         this->RaiseWidget(this->watched_company + EWW_PB_COMPANY_FIRST);
    00283       }
    00284       if (this->watched_company == (CompanyID)(widget - EWW_PB_COMPANY_FIRST)) {
    00285         /* Stop watching watched_company */
    00286         this->watched_company = INVALID_COMPANY;
    00287         GetString(this->company_name, STR_JUST_NOTHING, lastof(this->company_name));
    00288       } else {
    00289         /* Lower the new watched company button */
    00290         this->watched_company = (CompanyID)(widget - EWW_PB_COMPANY_FIRST);
    00291         this->LowerWidget(this->watched_company + EWW_PB_COMPANY_FIRST);
    00292         Company *c = Company::Get( this->watched_company);
    00293         SetDParam(0, c->index);
    00294         GetString(this->company_name, STR_COMPANY_NAME, lastof(this->company_name));
    00295
    00296         this->ScrollToTile( c->last_build_coordinate);
    00297       }
    00298       this->owner = this->watched_company;
    00299       this->SetDirty();
    00300     }
    00301   } else if ( IsInsideMM(widget, EWW_PB_ACTION1_FIRST, EWW_PB_ACTION1_LAST + 1)) {
    00302     if (!this->IsWidgetDisabled(widget)) {
    00303       this->ToggleWidgetLoweredState(widget);
    00304       this->SetDirty();
    00305     }
    00306   } else {
    00307     switch (widget) {
    00308       case EWW_ZOOMOUT: DoZoomInOutWindow(ZOOM_OUT, this); break;
    00309       case EWW_ZOOMIN: DoZoomInOutWindow(ZOOM_IN,  this); break;
    00310
    00311       case EWW_CENTER: { // location button (move main view to same spot as this view) 'Center Main View'
    00312         Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
    00313         int x = this->viewport->scrollpos_x; // Where is the watch looking at
    00314         int y = this->viewport->scrollpos_y;
    00315
    00316         /* set the main view to same location. Based on the center, adjusting for zoom */
    00317         w->viewport->dest_scrollpos_x =  x - (w->viewport->virtual_width -  this->viewport->virtual_width) / 2;
    00318         w->viewport->dest_scrollpos_y =  y - (w->viewport->virtual_height - this->viewport->virtual_height) / 2;
    00319       } break;
    00320
    00321       case EWW_NEW_WINDOW:
    00322         ShowWatchWindow(this->watched_company);
    00323         break;
    00324     }
    00325   }
    00326 }
    00327
    00328 void WatchCompany::OnInvalidateData(int data, bool gui_scope)
    00329 {
    00330   if (!gui_scope) return;
    00331
    00332   for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
    00333     this->SetWidgetDisabledState(EWW_PB_COMPANY_FIRST + i , !Company::IsValidID(i));
    00334     this->SetWidgetDisabledState(EWW_PB_ACTION1_FIRST + i , !Company::IsValidID(i));
    00335   }
    00336   /* Check if the currently selected company is still active. */
    00337   if (this->watched_company != INVALID_COMPANY) {
    00338     /* Make sure the widget is lowered */
    00339     this->LowerWidget(EWW_PB_COMPANY_FIRST + this->watched_company);
    00340     /* Check if the watched Company is still a valid one */
    00341     if (!Company::IsValidID(this->watched_company)) {
    00342       /* Invalid Company Raise the associated widget. */
    00343       this->RaiseWidget(this->watched_company + EWW_PB_COMPANY_FIRST);
    00344       this->watched_company = INVALID_COMPANY;
    00345       GetString(this->company_name, STR_JUST_NOTHING, lastof(this->company_name));
    00346     } else {
    00347       Company *c = Company::Get(this->watched_company);
    00348       SetDParam(0, c->index);
    00349       GetString(this->company_name, STR_COMPANY_NAME, lastof(this->company_name));
    00350     }
    00351   } else {
    00352     GetString(this->company_name, STR_JUST_NOTHING, lastof(this->company_name));
    00353   }
    00354 #ifdef ENABLE_NETWORK
    00355   if (_networking) { // Local game, draw the Blot
    00356     /* Reset company count - network only */
    00357     for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
    00358       this->company_count_client[i] = 0;
    00359     }
    00360     /* Calculate client count into company - network only */
    00361     NetworkClientInfo *ci;
    00362     FOR_ALL_CLIENT_INFOS(ci) {
    00363       if (Company::IsValidID(ci->client_playas)) {
    00364         company_count_client[ci->client_playas]+=1;
    00365       }
    00366     }
    00367   }
    00368 #endif
    00369   HandleZoomMessage(this, this->viewport, EWW_ZOOMIN, EWW_ZOOMOUT);
    00370 }
    00371
    00372 void WatchCompany::ScrollToTile(TileIndex tile)
    00373 {
    00374   /* Scroll window to the tile, only if not zero */
    00375   if (tile != 0) {
    00376     ScrollWindowTo(TileX(tile) * TILE_SIZE + TILE_SIZE / 2, TileY(tile) * TILE_SIZE + TILE_SIZE / 2, -1, this);
    00377   }
    00378 }
    00379
    00384 void WatchCompany::OnDoCommand(CompanyByte company, TileIndex tile)
    00385 {
    00386   /* Check if its my company */
    00387   if (this->watched_company == company)
    00388   {
    00389     this->ScrollToTile(tile);
    00390   }
    00391   /* set the company_activity to its max in order to paint the BLOT in red
    00392    * This will result by having the activity blot set to red for all companies
    00393    * even the one watched. To avoid this behaviour and not to light the blot of
    00394    * the watched company, the code can be moved just after the ScrollToTile call.
    00395    */
    00396   if (tile != 0) {
    00397     this->company_activity[company] = MAX_ACTIVITY;
    00398     this->SetDirty();
    00399   }
    00400 }
    00401
    00405 void WatchCompany::OnTick()
    00406 {
    00407   bool set_dirty = false;
    00408   for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
    00409     if (this->company_activity[i]>0) {
    00410       this->company_activity[i]--;
    00411       if (this->company_activity[i]==0) {
    00412         set_dirty = true;
    00413       }
    00414     }
    00415   }
    00416   /* If one company_activity reaches 0, then redraw */
    00417   if (set_dirty) {
    00418     this->SetDirty();
    00419   }
    00420 }
    00421
    00422 void ShowWatchWindow(CompanyID company_to_watch = INVALID_COMPANY)
    00423 {
    00424   int i = 0;
    00425   /* find next free window number for watch viewport */
    00426   while (FindWindowById(WC_WATCH_COMPANY, i) != NULL) i++;
    00427   new WatchCompany(&_watch_company_desc, i, company_to_watch);
    00428 }