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 }