group_gui.cpp

Go to the documentation of this file.
00001 /* $Id: group_gui.cpp 15724 2009-03-15 15:22:09Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "window_gui.h"
00008 #include "textbuf_gui.h"
00009 #include "command_func.h"
00010 #include "vehicle_gui.h"
00011 #include "vehicle_gui_base.h"
00012 #include "vehicle_base.h"
00013 #include "group.h"
00014 #include "strings_func.h"
00015 #include "window_func.h"
00016 #include "vehicle_func.h"
00017 #include "autoreplace_gui.h"
00018 #include "gfx_func.h"
00019 #include "company_func.h"
00020 #include "widgets/dropdown_type.h"
00021 #include "widgets/dropdown_func.h"
00022 #include "tilehighlight_func.h"
00023 
00024 #include "table/strings.h"
00025 #include "table/sprites.h"
00026 
00027 typedef GUIList<const Group*> GUIGroupList;
00028 
00029 enum GroupListWidgets {
00030   GRP_WIDGET_CLOSEBOX = 0,
00031   GRP_WIDGET_CAPTION,
00032   GRP_WIDGET_STICKY,
00033   GRP_WIDGET_SORT_BY_ORDER,
00034   GRP_WIDGET_SORT_BY_DROPDOWN,
00035   GRP_WIDGET_EMPTY_TOP_RIGHT,
00036   GRP_WIDGET_LIST_VEHICLE,
00037   GRP_WIDGET_LIST_VEHICLE_SCROLLBAR,
00038   GRP_WIDGET_EMPTY2,
00039   GRP_WIDGET_AVAILABLE_VEHICLES,
00040   GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN,
00041   GRP_WIDGET_STOP_ALL,
00042   GRP_WIDGET_START_ALL,
00043   GRP_WIDGET_EMPTY_BOTTOM_RIGHT,
00044   GRP_WIDGET_RESIZE,
00045 
00046   GRP_WIDGET_EMPTY_TOP_LEFT,
00047   GRP_WIDGET_ALL_VEHICLES,
00048   GRP_WIDGET_DEFAULT_VEHICLES,
00049   GRP_WIDGET_LIST_GROUP,
00050   GRP_WIDGET_LIST_GROUP_SCROLLBAR,
00051   GRP_WIDGET_CREATE_GROUP,
00052   GRP_WIDGET_DELETE_GROUP,
00053   GRP_WIDGET_RENAME_GROUP,
00054   GRP_WIDGET_EMPTY1,
00055   GRP_WIDGET_REPLACE_PROTECTION,
00056 };
00057 
00058 enum GroupActionListFunction {
00059   GALF_REPLACE,
00060   GALF_SERVICE,
00061   GALF_DEPOT,
00062   GALF_ADD_SHARED,
00063   GALF_REMOVE_ALL,
00064 };
00065 
00071 static void ShowGroupActionDropdown(Window *w, GroupID gid)
00072 {
00073   DropDownList *list = new DropDownList();
00074 
00075   list->push_back(new DropDownListStringItem(STR_REPLACE_VEHICLES,    GALF_REPLACE, false));
00076   list->push_back(new DropDownListStringItem(STR_SEND_FOR_SERVICING,  GALF_SERVICE, false));
00077   list->push_back(new DropDownListStringItem(STR_SEND_TRAIN_TO_DEPOT, GALF_DEPOT,   false));
00078 
00079   if (IsValidGroupID(gid)) {
00080     list->push_back(new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE,  GALF_ADD_SHARED, false));
00081     list->push_back(new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, GALF_REMOVE_ALL, false));
00082   }
00083 
00084   ShowDropDownList(w, list, 0, GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN);
00085 }
00086 
00087 
00088 static const Widget _group_widgets[] = {
00089 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,             STR_018B_CLOSE_WINDOW},             // GRP_WIDGET_CLOSEBOX
00090 {    WWT_CAPTION,  RESIZE_RIGHT,  COLOUR_GREY,    11,   447,     0,    13, 0x0,                  STR_018C_WINDOW_TITLE_DRAG_THIS},   // GRP_WIDGET_CAPTION
00091 {  WWT_STICKYBOX,     RESIZE_LR,  COLOUR_GREY,   448,   459,     0,    13, 0x0,                  STR_STICKY_BUTTON},                 // GRP_WIDGET_STICKY
00092 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   200,   280,    14,    25, STR_SORT_BY,          STR_SORT_ORDER_TIP},                // GRP_WIDGET_SORT_BY_ORDER
00093 {   WWT_DROPDOWN,   RESIZE_NONE,  COLOUR_GREY,   281,   447,    14,    25, 0x0,                  STR_SORT_CRITERIA_TIP},             // GRP_WIDGET_SORT_BY_DROPDOWN
00094 {      WWT_PANEL,  RESIZE_RIGHT,  COLOUR_GREY,   448,   459,    14,    25, 0x0,                  STR_NULL},                          // GRP_WIDGET_EMPTY_TOP_RIGHT
00095 {     WWT_MATRIX,     RESIZE_RB,  COLOUR_GREY,   200,   447,    26,   181, 0x701,                STR_NULL},                          // GRP_WIDGET_LIST_VEHICLE
00096 {  WWT_SCROLLBAR,    RESIZE_LRB,  COLOUR_GREY,   448,   459,    26,   181, 0x0,                  STR_0190_SCROLL_BAR_SCROLLS_LIST},  // GRP_WIDGET_LIST_VEHICLE_SCROLLBAR
00097 {      WWT_PANEL,     RESIZE_TB,  COLOUR_GREY,   188,   199,   169,   193, 0x0,                  STR_NULL},                          // GRP_WIDGET_EMPTY2
00098 { WWT_PUSHTXTBTN,     RESIZE_TB,  COLOUR_GREY,   200,   305,   182,   193, 0x0,                  STR_AVAILABLE_ENGINES_TIP},         // GRP_WIDGET_AVAILABLE_VEHICLES
00099 {   WWT_DROPDOWN,     RESIZE_TB,  COLOUR_GREY,   306,   423,   182,   193, STR_MANAGE_LIST,      STR_MANAGE_LIST_TIP},               // GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN
00100 { WWT_PUSHIMGBTN,     RESIZE_TB,  COLOUR_GREY,   424,   435,   182,   193, SPR_FLAG_VEH_STOPPED, STR_MASS_STOP_LIST_TIP},            // GRP_WIDGET_STOP_ALL
00101 { WWT_PUSHIMGBTN,     RESIZE_TB,  COLOUR_GREY,   436,   447,   182,   193, SPR_FLAG_VEH_RUNNING, STR_MASS_START_LIST_TIP},           // GRP_WIDGET_START_ALL
00102 {      WWT_PANEL,    RESIZE_RTB,  COLOUR_GREY,   448,   447,   182,   193, 0x0,                  STR_NULL},                          // GRP_WIDGET_EMPTY_BOTTOM_RIGHT
00103 {  WWT_RESIZEBOX,   RESIZE_LRTB,  COLOUR_GREY,   448,   459,   182,   193, 0x0,                  STR_RESIZE_BUTTON},                 // GRP_WIDGET_RESIZE
00104 
00105 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   199,    14,    25, 0x0,                  STR_NULL},                          // GRP_WIDGET_EMPTY_TOP_LEFT
00106 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   199,    26,    38, 0x0,                  STR_NULL},                          // GRP_WIDGET_ALL_VEHICLES
00107 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   199,    39,    51, 0x0,                  STR_NULL},                          // GRP_WIDGET_DEFAULT_VEHICLES
00108 {     WWT_MATRIX, RESIZE_BOTTOM,  COLOUR_GREY,     0,   187,    52,   168, 0x701,                STR_GROUPS_CLICK_ON_GROUP_FOR_TIP}, // GRP_WIDGET_LIST_GROUP
00109 { WWT_SCROLL2BAR, RESIZE_BOTTOM,  COLOUR_GREY,   188,   199,    52,   168, 0x0,                  STR_0190_SCROLL_BAR_SCROLLS_LIST},  // GRP_WIDGET_LIST_GROUP_SCROLLBAR
00110 { WWT_PUSHIMGBTN,     RESIZE_TB,  COLOUR_GREY,     0,    23,   169,   193, 0x0,                  STR_GROUP_CREATE_TIP},              // GRP_WIDGET_CREATE_GROUP
00111 { WWT_PUSHIMGBTN,     RESIZE_TB,  COLOUR_GREY,    24,    47,   169,   193, 0x0,                  STR_GROUP_DELETE_TIP},              // GRP_WIDGET_DELETE_GROUP
00112 { WWT_PUSHIMGBTN,     RESIZE_TB,  COLOUR_GREY,    48,    71,   169,   193, 0x0,                  STR_GROUP_RENAME_TIP},              // GRP_WIDGET_RENAME_GROUP
00113 {      WWT_PANEL,     RESIZE_TB,  COLOUR_GREY,    72,   163,   169,   193, 0x0,                  STR_NULL},                          // GRP_WIDGET_EMPTY1
00114 { WWT_PUSHIMGBTN,     RESIZE_TB,  COLOUR_GREY,   164,   187,   169,   193, 0x0,                  STR_GROUP_REPLACE_PROTECTION_TIP},  // GRP_WIDGET_REPLACE_PROTECTION
00115 {   WIDGETS_END},
00116 };
00117 
00118 
00119 class VehicleGroupWindow : public BaseVehicleListWindow {
00120 private:
00121   GroupID group_sel;
00122   VehicleID vehicle_sel;
00123   GUIGroupList groups;
00124 
00130   void BuildGroupList(Owner owner)
00131   {
00132     if (!this->groups.NeedRebuild()) return;
00133 
00134     this->groups.Clear();
00135 
00136     const Group *g;
00137     FOR_ALL_GROUPS(g) {
00138       if (g->owner == owner && g->vehicle_type == this->vehicle_type) {
00139         *this->groups.Append() = g;
00140       }
00141     }
00142 
00143     this->groups.Compact();
00144     this->groups.RebuildDone();
00145   }
00146 
00148   static int CDECL GroupNameSorter(const Group * const *a, const Group * const *b)
00149   {
00150     static const Group *last_group[2] = { NULL, NULL };
00151     static char         last_name[2][64] = { "", "" };
00152 
00153     if (*a != last_group[0]) {
00154       last_group[0] = *a;
00155       SetDParam(0, (*a)->index);
00156       GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
00157     }
00158 
00159     if (*b != last_group[1]) {
00160       last_group[1] = *b;
00161       SetDParam(0, (*b)->index);
00162       GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
00163     }
00164 
00165     int r = strcmp(last_name[0], last_name[1]); // sort by name
00166     if (r == 0) return (*a)->index - (*b)->index;
00167     return r;
00168   }
00169 
00170 public:
00171   VehicleGroupWindow(const WindowDesc *desc, WindowNumber window_number) : BaseVehicleListWindow(desc, window_number)
00172   {
00173     const Owner owner = (Owner)GB(this->window_number, 0, 8);
00174     this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5);
00175 
00176     this->owner = owner;
00177     this->resize.step_width = 1;
00178 
00179     switch (this->vehicle_type) {
00180       default: NOT_REACHED();
00181       case VEH_TRAIN:
00182       case VEH_ROAD:
00183         this->vscroll2.cap = 9;
00184         this->vscroll.cap = 6;
00185         this->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_SMALL;
00186         break;
00187       case VEH_SHIP:
00188       case VEH_AIRCRAFT:
00189         this->vscroll2.cap = 9;
00190         this->vscroll.cap = 4;
00191         this->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_BIG;
00192         break;
00193     }
00194 
00195     this->widget[GRP_WIDGET_LIST_GROUP].data = (this->vscroll2.cap << 8) + 1;
00196     this->widget[GRP_WIDGET_LIST_VEHICLE].data = (this->vscroll.cap << 8) + 1;
00197 
00198     switch (this->vehicle_type) {
00199       default: NOT_REACHED();
00200       case VEH_TRAIN:    this->sorting = &_sorting.train;    break;
00201       case VEH_ROAD:     this->sorting = &_sorting.roadveh;  break;
00202       case VEH_SHIP:     this->sorting = &_sorting.ship;     break;
00203       case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
00204     }
00205 
00206     this->vehicles.SetListing(*this->sorting);
00207     this->vehicles.ForceRebuild();
00208     this->vehicles.NeedResort();
00209 
00210     this->groups.ForceRebuild();
00211     this->groups.NeedResort();
00212 
00213     this->group_sel = ALL_GROUP;
00214     this->vehicle_sel = INVALID_VEHICLE;
00215 
00216     switch (this->vehicle_type) {
00217       case VEH_TRAIN:
00218         this->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_883D_TRAINS_CLICK_ON_TRAIN_FOR;
00219         this->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_TRAINS;
00220 
00221         this->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_TRAIN;
00222         this->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_TRAIN;
00223         this->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_TRAIN;
00224         break;
00225 
00226       case VEH_ROAD:
00227         this->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_901A_ROAD_VEHICLES_CLICK_ON;
00228         this->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_ROAD_VEHICLES;
00229 
00230         this->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_ROADVEH;
00231         this->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_ROADVEH;
00232         this->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_ROADVEH;
00233         break;
00234 
00235       case VEH_SHIP:
00236         this->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_9823_SHIPS_CLICK_ON_SHIP_FOR;
00237         this->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_SHIPS;
00238 
00239         this->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_SHIP;
00240         this->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_SHIP;
00241         this->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_SHIP;
00242         break;
00243 
00244       case VEH_AIRCRAFT:
00245         this->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT;
00246         this->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_AIRCRAFT;
00247 
00248         this->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_AIRCRAFT;
00249         this->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_AIRCRAFT;
00250         this->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_AIRCRAFT;
00251         break;
00252 
00253       default: NOT_REACHED();
00254     }
00255 
00256     this->FindWindowPlacementAndResize(desc);
00257     if (this->vehicle_type == VEH_TRAIN) ResizeWindow(this, 65, 0);
00258   }
00259 
00260   ~VehicleGroupWindow()
00261   {
00262     *this->sorting = this->vehicles.GetListing();
00263   }
00264 
00265   virtual void OnInvalidateData(int data)
00266   {
00267     if (data == 0) {
00268       this->vehicles.ForceRebuild();
00269       this->groups.ForceRebuild();
00270     } else {
00271       this->vehicles.ForceResort();
00272       this->groups.ForceResort();
00273     }
00274 
00275     if (!(IsAllGroupID(this->group_sel) || IsDefaultGroupID(this->group_sel) || IsValidGroupID(this->group_sel))) {
00276       this->group_sel = ALL_GROUP;
00277       HideDropDownMenu(this);
00278     }
00279     this->SetDirty();
00280   }
00281 
00282   virtual void OnPaint()
00283   {
00284     const Owner owner = (Owner)GB(this->window_number, 0, 8);
00285     int x = this->widget[GRP_WIDGET_LIST_VEHICLE].left + 2;
00286     int y1 = PLY_WND_PRC__OFFSET_TOP_WIDGET + 2;
00287     int max;
00288     int i;
00289 
00290     /* If we select the all vehicles, this->list will contain all vehicles of the owner
00291      * else this->list will contain all vehicles which belong to the selected group */
00292     this->BuildVehicleList(owner, this->group_sel, IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST);
00293     this->SortVehicleList();
00294 
00295     this->BuildGroupList(owner);
00296     this->groups.Sort(&GroupNameSorter);
00297 
00298     SetVScroll2Count(this, this->groups.Length());
00299     SetVScrollCount(this, this->vehicles.Length());
00300 
00301     /* The drop down menu is out, *but* it may not be used, retract it. */
00302     if (this->vehicles.Length() == 0 && this->IsWidgetLowered(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) {
00303       this->RaiseWidget(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN);
00304       HideDropDownMenu(this);
00305     }
00306 
00307     /* Disable all lists management button when the list is empty */
00308     this->SetWidgetsDisabledState(this->vehicles.Length() == 0 || _local_company != owner,
00309         GRP_WIDGET_STOP_ALL,
00310         GRP_WIDGET_START_ALL,
00311         GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN,
00312         WIDGET_LIST_END);
00313 
00314     /* Disable the group specific function when we select the default group or all vehicles */
00315     this->SetWidgetsDisabledState(IsDefaultGroupID(this->group_sel) || IsAllGroupID(this->group_sel) || _local_company != owner,
00316         GRP_WIDGET_DELETE_GROUP,
00317         GRP_WIDGET_RENAME_GROUP,
00318         GRP_WIDGET_REPLACE_PROTECTION,
00319         WIDGET_LIST_END);
00320 
00321     /* Disable remaining buttons for non-local companies
00322      * Needed while changing _local_company, eg. by cheats
00323      * All procedures (eg. move vehicle to another group)
00324      *  verify, whether you are the owner of the vehicle,
00325      *  so it doesn't have to be disabled
00326      */
00327     this->SetWidgetsDisabledState(_local_company != owner,
00328         GRP_WIDGET_CREATE_GROUP,
00329         GRP_WIDGET_AVAILABLE_VEHICLES,
00330         WIDGET_LIST_END);
00331 
00332 
00333     /* If selected_group == DEFAULT_GROUP || ALL_GROUP, draw the standard caption
00334         We list all vehicles or ungrouped vehicles */
00335     if (IsDefaultGroupID(this->group_sel) || IsAllGroupID(this->group_sel)) {
00336       SetDParam(0, owner);
00337       SetDParam(1, this->vehicles.Length());
00338 
00339       switch (this->vehicle_type) {
00340         case VEH_TRAIN:
00341           this->widget[GRP_WIDGET_CAPTION].data = STR_881B_TRAINS;
00342           this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_TRAIN;
00343           break;
00344         case VEH_ROAD:
00345           this->widget[GRP_WIDGET_CAPTION].data = STR_9001_ROAD_VEHICLES;
00346           this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_ROADVEH;
00347           break;
00348         case VEH_SHIP:
00349           this->widget[GRP_WIDGET_CAPTION].data = STR_9805_SHIPS;
00350           this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_SHIP;
00351           break;
00352         case VEH_AIRCRAFT:
00353           this->widget[GRP_WIDGET_CAPTION].data =  STR_A009_AIRCRAFT;
00354           this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_AIRCRAFT;
00355           break;
00356         default: NOT_REACHED();
00357       }
00358     } else {
00359       const Group *g = GetGroup(this->group_sel);
00360 
00361       SetDParam(0, g->index);
00362       SetDParam(1, g->num_vehicle);
00363 
00364       switch (this->vehicle_type) {
00365         case VEH_TRAIN:
00366           this->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_TRAINS_CAPTION;
00367           this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_TRAIN : SPR_GROUP_REPLACE_OFF_TRAIN;
00368           break;
00369         case VEH_ROAD:
00370           this->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_ROADVEH_CAPTION;
00371           this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_ROADVEH : SPR_GROUP_REPLACE_OFF_ROADVEH;
00372           break;
00373         case VEH_SHIP:
00374           this->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_SHIPS_CAPTION;
00375           this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_SHIP : SPR_GROUP_REPLACE_OFF_SHIP;
00376           break;
00377         case VEH_AIRCRAFT:
00378           this->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_AIRCRAFTS_CAPTION;
00379           this->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_AIRCRAFT : SPR_GROUP_REPLACE_OFF_AIRCRAFT;
00380           break;
00381         default: NOT_REACHED();
00382       }
00383     }
00384 
00385     /* Set text of sort by dropdown */
00386     this->widget[GRP_WIDGET_SORT_BY_DROPDOWN].data = this->vehicle_sorter_names[this->vehicles.SortType()];
00387 
00388     this->DrawWidgets();
00389 
00390     /* Draw Matrix Group
00391      * The selected group is drawn in white */
00392     StringID str_all_veh, str_no_group_veh;
00393 
00394     switch (this->vehicle_type) {
00395       case VEH_TRAIN:
00396         str_all_veh = STR_GROUP_ALL_TRAINS;
00397         str_no_group_veh = STR_GROUP_DEFAULT_TRAINS;
00398         break;
00399       case VEH_ROAD:
00400         str_all_veh = STR_GROUP_ALL_ROADS;
00401         str_no_group_veh = STR_GROUP_DEFAULT_ROADS;
00402         break;
00403       case VEH_SHIP:
00404         str_all_veh = STR_GROUP_ALL_SHIPS;
00405         str_no_group_veh = STR_GROUP_DEFAULT_SHIPS;
00406         break;
00407       case VEH_AIRCRAFT:
00408         str_all_veh = STR_GROUP_ALL_AIRCRAFTS;
00409         str_no_group_veh = STR_GROUP_DEFAULT_AIRCRAFTS;
00410         break;
00411       default: NOT_REACHED();
00412     }
00413     DrawString(10, y1, str_all_veh, IsAllGroupID(this->group_sel) ? TC_WHITE : TC_BLACK);
00414 
00415     y1 += 13;
00416 
00417     DrawString(10, y1, str_no_group_veh, IsDefaultGroupID(this->group_sel) ? TC_WHITE : TC_BLACK);
00418 
00419     max = min(this->vscroll2.pos + this->vscroll2.cap, this->groups.Length());
00420     for (i = this->vscroll2.pos ; i < max ; ++i) {
00421       const Group *g = this->groups[i];
00422 
00423       assert(g->owner == owner);
00424 
00425       y1 += PLY_WND_PRC__SIZE_OF_ROW_TINY;
00426 
00427       /* draw the selected group in white, else we draw it in black */
00428       SetDParam(0, g->index);
00429       DrawString(10, y1, STR_GROUP_NAME, (this->group_sel == g->index) ? TC_WHITE : TC_BLACK);
00430 
00431       /* draw the number of vehicles of the group */
00432       SetDParam(0, g->num_vehicle);
00433       DrawStringRightAligned(187, y1 + 1, STR_GROUP_TINY_NUM, (this->group_sel == g->index) ? TC_WHITE : TC_BLACK);
00434     }
00435 
00436     this->DrawSortButtonState(GRP_WIDGET_SORT_BY_ORDER, this->vehicles.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
00437 
00438     this->DrawVehicleListItems(x, this->vehicle_sel);
00439   }
00440 
00441   virtual void OnClick(Point pt, int widget)
00442   {
00443     switch(widget) {
00444       case GRP_WIDGET_SORT_BY_ORDER: // Flip sorting method ascending/descending
00445         this->vehicles.ToggleSortOrder();
00446         this->SetDirty();
00447         break;
00448 
00449       case GRP_WIDGET_SORT_BY_DROPDOWN: // Select sorting criteria dropdown menu
00450         ShowDropDownMenu(this, this->vehicle_sorter_names, this->vehicles.SortType(),  GRP_WIDGET_SORT_BY_DROPDOWN, 0, (this->vehicle_type == VEH_TRAIN || this->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
00451         return;
00452 
00453       case GRP_WIDGET_ALL_VEHICLES: // All vehicles button
00454         if (!IsAllGroupID(this->group_sel)) {
00455           this->group_sel = ALL_GROUP;
00456           this->vehicles.ForceRebuild();
00457           this->SetDirty();
00458         }
00459         break;
00460 
00461       case GRP_WIDGET_DEFAULT_VEHICLES: // Ungrouped vehicles button
00462         if (!IsDefaultGroupID(this->group_sel)) {
00463           this->group_sel = DEFAULT_GROUP;
00464           this->vehicles.ForceRebuild();
00465           this->SetDirty();
00466         }
00467         break;
00468 
00469       case GRP_WIDGET_LIST_GROUP: { // Matrix Group
00470         uint16 id_g = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET - 26) / PLY_WND_PRC__SIZE_OF_ROW_TINY;
00471 
00472         if (id_g >= this->vscroll2.cap) return;
00473 
00474         id_g += this->vscroll2.pos;
00475 
00476         if (id_g >= this->groups.Length()) return;
00477 
00478         this->group_sel = this->groups[id_g]->index;;
00479 
00480         this->vehicles.ForceRebuild();
00481         this->SetDirty();
00482         break;
00483       }
00484 
00485       case GRP_WIDGET_LIST_VEHICLE: { // Matrix Vehicle
00486         uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)this->resize.step_height;
00487         const Vehicle *v;
00488 
00489         if (id_v >= this->vscroll.cap) return; // click out of bounds
00490 
00491         id_v += this->vscroll.pos;
00492 
00493         if (id_v >= this->vehicles.Length()) return; // click out of list bound
00494 
00495         v = this->vehicles[id_v];
00496 
00497         this->vehicle_sel = v->index;
00498 
00499         if (v->IsValid()) {
00500           SetObjectToPlaceWnd(v->GetImage(DIR_W), GetVehiclePalette(v), VHM_DRAG, this);
00501           _cursor.vehchain = true;
00502         }
00503 
00504         this->SetDirty();
00505         break;
00506       }
00507 
00508       case GRP_WIDGET_CREATE_GROUP: // Create a new group
00509         DoCommandP(0, this->vehicle_type, 0, CMD_CREATE_GROUP | CMD_MSG(STR_GROUP_CAN_T_CREATE));
00510         break;
00511 
00512       case GRP_WIDGET_DELETE_GROUP: { // Delete the selected group
00513         GroupID group = this->group_sel;
00514         this->group_sel = ALL_GROUP;
00515 
00516         DoCommandP(0, group, 0, CMD_DELETE_GROUP | CMD_MSG(STR_GROUP_CAN_T_DELETE));
00517         break;
00518       }
00519 
00520       case GRP_WIDGET_RENAME_GROUP: { // Rename the selected roup
00521         assert(IsValidGroupID(this->group_sel));
00522 
00523         const Group *g = GetGroup(this->group_sel);
00524 
00525         SetDParam(0, g->index);
00526         ShowQueryString(STR_GROUP_NAME, STR_GROUP_RENAME_CAPTION, MAX_LENGTH_GROUP_NAME_BYTES, MAX_LENGTH_GROUP_NAME_PIXELS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT);
00527       } break;
00528 
00529 
00530       case GRP_WIDGET_AVAILABLE_VEHICLES:
00531         ShowBuildVehicleWindow(INVALID_TILE, this->vehicle_type);
00532         break;
00533 
00534       case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:
00535         ShowGroupActionDropdown(this, this->group_sel);
00536         break;
00537 
00538       case GRP_WIDGET_START_ALL:
00539       case GRP_WIDGET_STOP_ALL: { // Start/stop all vehicles of the list
00540         DoCommandP(0, this->group_sel, ((IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
00541                           | (1 << 6)
00542                           | (widget == GRP_WIDGET_START_ALL ? (1 << 5) : 0)
00543                           | this->vehicle_type, CMD_MASS_START_STOP);
00544 
00545         break;
00546       }
00547 
00548       case GRP_WIDGET_REPLACE_PROTECTION:
00549         if (IsValidGroupID(this->group_sel)) {
00550           const Group *g = GetGroup(this->group_sel);
00551 
00552           DoCommandP(0, this->group_sel, !g->replace_protection, CMD_SET_GROUP_REPLACE_PROTECTION);
00553         }
00554         break;
00555     }
00556   }
00557 
00558   virtual void OnDragDrop(Point pt, int widget)
00559   {
00560     switch (widget) {
00561       case GRP_WIDGET_ALL_VEHICLES: // All vehicles
00562       case GRP_WIDGET_DEFAULT_VEHICLES: // Ungrouped vehicles
00563         DoCommandP(0, DEFAULT_GROUP, this->vehicle_sel, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
00564 
00565         this->vehicle_sel = INVALID_VEHICLE;
00566 
00567         this->SetDirty();
00568 
00569         break;
00570 
00571       case GRP_WIDGET_LIST_GROUP: { // Maxtrix group
00572         uint16 id_g = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET - 26) / PLY_WND_PRC__SIZE_OF_ROW_TINY;
00573         const VehicleID vindex = this->vehicle_sel;
00574 
00575         this->vehicle_sel = INVALID_VEHICLE;
00576 
00577         this->SetDirty();
00578 
00579         if (id_g >= this->vscroll2.cap) return;
00580 
00581         id_g += this->vscroll2.pos;
00582 
00583         if (id_g >= this->groups.Length()) return;
00584 
00585         DoCommandP(0, this->groups[id_g]->index, vindex, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
00586 
00587         break;
00588       }
00589 
00590       case GRP_WIDGET_LIST_VEHICLE: { // Maxtrix vehicle
00591         uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)this->resize.step_height;
00592         const Vehicle *v;
00593         const VehicleID vindex = this->vehicle_sel;
00594 
00595         this->vehicle_sel = INVALID_VEHICLE;
00596 
00597         this->SetDirty();
00598 
00599         if (id_v >= this->vscroll.cap) return; // click out of bounds
00600 
00601         id_v += this->vscroll.pos;
00602 
00603         if (id_v >= this->vehicles.Length()) return; // click out of list bound
00604 
00605         v = this->vehicles[id_v];
00606 
00607         if (vindex == v->index) {
00608           ShowVehicleViewWindow(v);
00609         }
00610 
00611         break;
00612       }
00613     }
00614     _cursor.vehchain = false;
00615   }
00616 
00617   virtual void OnQueryTextFinished(char *str)
00618   {
00619     if (str == NULL) return;
00620 
00621     DoCommandP(0, this->group_sel, 0, CMD_RENAME_GROUP | CMD_MSG(STR_GROUP_CAN_T_RENAME), NULL, str);
00622   }
00623 
00624   virtual void OnResize(Point new_size, Point delta)
00625   {
00626     this->vscroll2.cap += delta.y / PLY_WND_PRC__SIZE_OF_ROW_TINY;
00627     this->vscroll.cap += delta.y / (int)this->resize.step_height;
00628 
00629     this->widget[GRP_WIDGET_LIST_GROUP].data = (this->vscroll2.cap << 8) + 1;
00630     this->widget[GRP_WIDGET_LIST_VEHICLE].data = (this->vscroll.cap << 8) + 1;
00631   }
00632 
00633   virtual void OnDropdownSelect(int widget, int index)
00634   {
00635     switch (widget) {
00636       case GRP_WIDGET_SORT_BY_DROPDOWN:
00637         this->vehicles.SetSortType(index);
00638         break;
00639 
00640       case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:
00641         assert(this->vehicles.Length() != 0);
00642 
00643         switch (index) {
00644           case GALF_REPLACE: // Replace window
00645             ShowReplaceGroupVehicleWindow(this->group_sel, this->vehicle_type);
00646             break;
00647           case GALF_SERVICE: // Send for servicing
00648             DoCommandP(0, this->group_sel, ((IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
00649                   | DEPOT_MASS_SEND
00650                   | DEPOT_SERVICE, GetCmdSendToDepot(this->vehicle_type));
00651             break;
00652           case GALF_DEPOT: // Send to Depots
00653             DoCommandP(0, this->group_sel, ((IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
00654                   | DEPOT_MASS_SEND, GetCmdSendToDepot(this->vehicle_type));
00655             break;
00656           case GALF_ADD_SHARED: // Add shared Vehicles
00657             assert(IsValidGroupID(this->group_sel));
00658 
00659             DoCommandP(0, this->group_sel, this->vehicle_type, CMD_ADD_SHARED_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_SHARED_VEHICLE));
00660             break;
00661           case GALF_REMOVE_ALL: // Remove all Vehicles from the selected group
00662             assert(IsValidGroupID(this->group_sel));
00663 
00664             DoCommandP(0, this->group_sel, this->vehicle_type, CMD_REMOVE_ALL_VEHICLES_GROUP | CMD_MSG(STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES));
00665             break;
00666           default: NOT_REACHED();
00667         }
00668         break;
00669 
00670       default: NOT_REACHED();
00671     }
00672 
00673     this->SetDirty();
00674   }
00675 
00676   virtual void OnTick()
00677   {
00678     if (_pause_game != 0) return;
00679     if (this->groups.NeedResort() || this->vehicles.NeedResort()) {
00680       this->SetDirty();
00681     }
00682   }
00683 
00684   virtual void OnPlaceObjectAbort()
00685   {
00686     /* abort drag & drop */
00687     this->vehicle_sel = INVALID_VEHICLE;
00688     this->InvalidateWidget(GRP_WIDGET_LIST_VEHICLE);
00689   }
00690 
00696   void UnselectVehicle(VehicleID vehicle)
00697   {
00698     if (this->vehicle_sel == vehicle) ResetObjectToPlace();
00699   }
00700 };
00701 
00702 
00703 static WindowDesc _group_desc(
00704   WDP_AUTO, WDP_AUTO, 460, 194, 460, 246,
00705   WC_INVALID, WC_NONE,
00706   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
00707   _group_widgets
00708 );
00709 
00710 void ShowCompanyGroup(CompanyID company, VehicleType vehicle_type)
00711 {
00712   if (!IsValidCompanyID(company)) return;
00713 
00714   _group_desc.cls = GetWindowClassForVehicleType(vehicle_type);
00715   WindowNumber num = (vehicle_type << 11) | VLW_GROUP_LIST | company;
00716   AllocateWindowDescFront<VehicleGroupWindow>(&_group_desc, num);
00717 }
00718 
00723 void DeleteGroupHighlightOfVehicle(const Vehicle *v)
00724 {
00725   VehicleGroupWindow *w;
00726 
00727   /* If we haven't got any vehicles on the mouse pointer, we haven't got any highlighted in any group windows either
00728    * If that is the case, we can skip looping though the windows and save time
00729    */
00730   if (_special_mouse_mode != WSM_DRAGDROP) return;
00731 
00732   VehicleType vehicle_type = v->type;
00733   w = dynamic_cast<VehicleGroupWindow *>(FindWindowById(GetWindowClassForVehicleType(vehicle_type), (vehicle_type << 11) | VLW_GROUP_LIST | v->owner));
00734   if (w != NULL) w->UnselectVehicle(v->index);
00735 }
00736 

Generated on Tue Dec 1 00:06:15 2009 for OpenTTD by  doxygen 1.5.6