|
|
|
@ -30,6 +30,8 @@
|
|
|
|
|
|
|
|
|
|
#include "table/sprites.h"
|
|
|
|
|
|
|
|
|
|
static const int LEVEL_WIDTH = 10; ///< Indenting width of a sub-group in pixels
|
|
|
|
|
|
|
|
|
|
typedef GUIList<const Group*> GUIGroupList;
|
|
|
|
|
|
|
|
|
|
static const NWidgetPart _nested_group_widgets[] = {
|
|
|
|
@ -105,34 +107,26 @@ private:
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VehicleID vehicle_sel; ///< Selected vehicle
|
|
|
|
|
GroupID group_sel; ///< Selected group (for drag/drop)
|
|
|
|
|
GroupID group_rename; ///< Group being renamed, INVALID_GROUP if none
|
|
|
|
|
GroupID group_over; ///< Group over which a vehicle is dragged, INVALID_GROUP if none
|
|
|
|
|
GUIGroupList groups; ///< List of groups
|
|
|
|
|
uint tiny_step_height; ///< Step height for the group list
|
|
|
|
|
Scrollbar *group_sb;
|
|
|
|
|
|
|
|
|
|
SmallVector<int, 16> indents; ///< Indentation levels
|
|
|
|
|
|
|
|
|
|
Dimension column_size[VGC_END]; ///< Size of the columns in the group list.
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* (Re)Build the group list.
|
|
|
|
|
*
|
|
|
|
|
* @param owner The owner of the window
|
|
|
|
|
*/
|
|
|
|
|
void BuildGroupList(Owner owner)
|
|
|
|
|
void AddParents(GUIGroupList *source, GroupID parent, int indent)
|
|
|
|
|
{
|
|
|
|
|
if (!this->groups.NeedRebuild()) return;
|
|
|
|
|
|
|
|
|
|
this->groups.Clear();
|
|
|
|
|
|
|
|
|
|
const Group *g;
|
|
|
|
|
FOR_ALL_GROUPS(g) {
|
|
|
|
|
if (g->owner == owner && g->vehicle_type == this->vli.vtype) {
|
|
|
|
|
*this->groups.Append() = g;
|
|
|
|
|
for (const Group **g = source->Begin(); g != source->End(); g++) {
|
|
|
|
|
if ((*g)->parent == parent) {
|
|
|
|
|
*this->groups.Append() = *g;
|
|
|
|
|
*this->indents.Append() = indent;
|
|
|
|
|
AddParents(source, (*g)->index, indent + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->groups.Compact();
|
|
|
|
|
this->groups.RebuildDone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Sort the groups by their name */
|
|
|
|
@ -158,6 +152,36 @@ private:
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* (Re)Build the group list.
|
|
|
|
|
*
|
|
|
|
|
* @param owner The owner of the window
|
|
|
|
|
*/
|
|
|
|
|
void BuildGroupList(Owner owner)
|
|
|
|
|
{
|
|
|
|
|
if (!this->groups.NeedRebuild()) return;
|
|
|
|
|
|
|
|
|
|
this->groups.Clear();
|
|
|
|
|
this->indents.Clear();
|
|
|
|
|
|
|
|
|
|
GUIGroupList list;
|
|
|
|
|
|
|
|
|
|
const Group *g;
|
|
|
|
|
FOR_ALL_GROUPS(g) {
|
|
|
|
|
if (g->owner == owner && g->vehicle_type == this->vli.vtype) {
|
|
|
|
|
*list.Append() = g;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list.ForceResort();
|
|
|
|
|
list.Sort(&GroupNameSorter);
|
|
|
|
|
|
|
|
|
|
AddParents(&list, INVALID_GROUP, 0);
|
|
|
|
|
|
|
|
|
|
this->groups.Compact();
|
|
|
|
|
this->groups.RebuildDone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Compute tiny_step_height and column_size
|
|
|
|
|
* @return Total width required for the group list.
|
|
|
|
@ -204,9 +228,10 @@ private:
|
|
|
|
|
* @param left Left of the row.
|
|
|
|
|
* @param right Right of the row.
|
|
|
|
|
* @param g_id Group to list.
|
|
|
|
|
* @param indent Indentation level.
|
|
|
|
|
* @param protection Whether autoreplace protection is set.
|
|
|
|
|
*/
|
|
|
|
|
void DrawGroupInfo(int y, int left, int right, GroupID g_id, bool protection = false) const
|
|
|
|
|
void DrawGroupInfo(int y, int left, int right, GroupID g_id, int indent = 0, bool protection = false) const
|
|
|
|
|
{
|
|
|
|
|
/* Highlight the group if a vehicle is dragged over it */
|
|
|
|
|
if (g_id == this->group_over) {
|
|
|
|
@ -231,7 +256,7 @@ private:
|
|
|
|
|
str = STR_GROUP_NAME;
|
|
|
|
|
}
|
|
|
|
|
int x = rtl ? right - WD_FRAMERECT_RIGHT - 8 - this->column_size[VGC_NAME].width + 1 : left + WD_FRAMERECT_LEFT + 8;
|
|
|
|
|
DrawString(x, x + this->column_size[VGC_NAME].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, str, colour);
|
|
|
|
|
DrawString(x + indent * LEVEL_WIDTH, x + this->column_size[VGC_NAME].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, str, colour);
|
|
|
|
|
|
|
|
|
|
/* draw autoreplace protection */
|
|
|
|
|
x = rtl ? x - 8 - this->column_size[VGC_PROTECT].width : x + 8 + this->column_size[VGC_NAME].width;
|
|
|
|
@ -295,6 +320,7 @@ public:
|
|
|
|
|
|
|
|
|
|
this->vli.index = ALL_GROUP;
|
|
|
|
|
this->vehicle_sel = INVALID_VEHICLE;
|
|
|
|
|
this->group_sel = INVALID_GROUP;
|
|
|
|
|
this->group_rename = INVALID_GROUP;
|
|
|
|
|
this->group_over = INVALID_GROUP;
|
|
|
|
|
|
|
|
|
@ -308,7 +334,6 @@ public:
|
|
|
|
|
this->groups.ForceRebuild();
|
|
|
|
|
this->groups.NeedResort();
|
|
|
|
|
this->BuildGroupList(vli.company);
|
|
|
|
|
this->groups.Sort(&GroupNameSorter);
|
|
|
|
|
|
|
|
|
|
this->GetWidget<NWidgetCore>(WID_GL_CAPTION)->widget_data = STR_VEHICLE_LIST_TRAIN_CAPTION + this->vli.vtype;
|
|
|
|
|
this->GetWidget<NWidgetCore>(WID_GL_LIST_VEHICLE)->tool_tip = STR_VEHICLE_LIST_TRAIN_LIST_TOOLTIP + this->vli.vtype;
|
|
|
|
@ -442,7 +467,6 @@ public:
|
|
|
|
|
this->SortVehicleList();
|
|
|
|
|
|
|
|
|
|
this->BuildGroupList(this->owner);
|
|
|
|
|
this->groups.Sort(&GroupNameSorter);
|
|
|
|
|
|
|
|
|
|
this->group_sb->SetCount(this->groups.Length());
|
|
|
|
|
this->vscroll->SetCount(this->vehicles.Length());
|
|
|
|
@ -508,7 +532,7 @@ public:
|
|
|
|
|
|
|
|
|
|
assert(g->owner == this->owner);
|
|
|
|
|
|
|
|
|
|
DrawGroupInfo(y1, r.left, r.right, g->index, g->replace_protection);
|
|
|
|
|
DrawGroupInfo(y1, r.left, r.right, g->index, this->indents[i], g->replace_protection);
|
|
|
|
|
|
|
|
|
|
y1 += this->tiny_step_height;
|
|
|
|
|
}
|
|
|
|
@ -523,6 +547,19 @@ public:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case WID_GL_LIST_VEHICLE:
|
|
|
|
|
if (this->vli.index != ALL_GROUP) {
|
|
|
|
|
/* Mark vehicles which are in sub-groups */
|
|
|
|
|
int y = r.top;
|
|
|
|
|
uint max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->vehicles.Length());
|
|
|
|
|
for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
|
|
|
|
|
const Vehicle *v = this->vehicles[i];
|
|
|
|
|
if (v->group_id != this->vli.index) {
|
|
|
|
|
GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->resize.step_height - 2, _colour_gradient[COLOUR_GREY][3], FILLRECT_CHECKER);
|
|
|
|
|
}
|
|
|
|
|
y += this->resize.step_height;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->DrawVehicleListItems(this->vehicle_sel, this->resize.step_height, r);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -560,7 +597,9 @@ public:
|
|
|
|
|
uint id_g = this->group_sb->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_GROUP, 0, this->tiny_step_height);
|
|
|
|
|
if (id_g >= this->groups.Length()) return;
|
|
|
|
|
|
|
|
|
|
this->vli.index = this->groups[id_g]->index;
|
|
|
|
|
this->group_sel = this->vli.index = this->groups[id_g]->index;
|
|
|
|
|
|
|
|
|
|
SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this);
|
|
|
|
|
|
|
|
|
|
this->vehicles.ForceRebuild();
|
|
|
|
|
this->SetDirty();
|
|
|
|
@ -620,14 +659,46 @@ public:
|
|
|
|
|
case WID_GL_REPLACE_PROTECTION: {
|
|
|
|
|
const Group *g = Group::GetIfValid(this->vli.index);
|
|
|
|
|
if (g != NULL) {
|
|
|
|
|
DoCommandP(0, this->vli.index, !g->replace_protection, CMD_SET_GROUP_REPLACE_PROTECTION);
|
|
|
|
|
DoCommandP(0, this->vli.index, !g->replace_protection | (_ctrl_pressed << 1), CMD_SET_GROUP_REPLACE_PROTECTION);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void OnDragDrop(Point pt, int widget)
|
|
|
|
|
void OnDragDrop_Group(Point pt, int widget)
|
|
|
|
|
{
|
|
|
|
|
const Group *g = Group::Get(this->group_sel);
|
|
|
|
|
|
|
|
|
|
switch (widget) {
|
|
|
|
|
case WID_GL_ALL_VEHICLES: // All vehicles
|
|
|
|
|
case WID_GL_DEFAULT_VEHICLES: // Ungroupd vehicles
|
|
|
|
|
if (g->parent != INVALID_GROUP) {
|
|
|
|
|
DoCommandP(0, this->group_sel | (1 << 16), INVALID_GROUP, CMD_ALTER_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_SET_PARENT));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->group_sel = INVALID_GROUP;
|
|
|
|
|
this->group_over = INVALID_GROUP;
|
|
|
|
|
this->SetDirty();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case WID_GL_LIST_GROUP: { // Matrix group
|
|
|
|
|
uint id_g = this->group_sb->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_GROUP, 0, this->tiny_step_height);
|
|
|
|
|
GroupID new_g = id_g >= this->groups.Length() ? INVALID_GROUP : this->groups[id_g]->index;
|
|
|
|
|
|
|
|
|
|
if (this->group_sel != new_g && g->parent != new_g) {
|
|
|
|
|
DoCommandP(0, this->group_sel | (1 << 16), new_g, CMD_ALTER_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_SET_PARENT));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->group_sel = INVALID_GROUP;
|
|
|
|
|
this->group_over = INVALID_GROUP;
|
|
|
|
|
this->SetDirty();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnDragDrop_Vehicle(Point pt, int widget)
|
|
|
|
|
{
|
|
|
|
|
switch (widget) {
|
|
|
|
|
case WID_GL_DEFAULT_VEHICLES: // Ungrouped vehicles
|
|
|
|
@ -668,12 +739,19 @@ public:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void OnDragDrop(Point pt, int widget)
|
|
|
|
|
{
|
|
|
|
|
if (this->vehicle_sel != INVALID_VEHICLE) OnDragDrop_Vehicle(pt, widget);
|
|
|
|
|
if (this->group_sel != INVALID_GROUP) OnDragDrop_Group(pt, widget);
|
|
|
|
|
|
|
|
|
|
_cursor.vehchain = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void OnQueryTextFinished(char *str)
|
|
|
|
|
{
|
|
|
|
|
if (str != NULL) DoCommandP(0, this->group_rename, 0, CMD_RENAME_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_RENAME), NULL, str);
|
|
|
|
|
if (str != NULL) DoCommandP(0, this->group_rename, 0, CMD_ALTER_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_RENAME), NULL, str);
|
|
|
|
|
this->group_rename = INVALID_GROUP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -742,7 +820,7 @@ public:
|
|
|
|
|
|
|
|
|
|
virtual void OnMouseDrag(Point pt, int widget)
|
|
|
|
|
{
|
|
|
|
|
if (this->vehicle_sel == INVALID_VEHICLE) return;
|
|
|
|
|
if (this->vehicle_sel == INVALID_VEHICLE && this->group_sel == INVALID_GROUP) return;
|
|
|
|
|
|
|
|
|
|
/* A vehicle is dragged over... */
|
|
|
|
|
GroupID new_group_over = INVALID_GROUP;
|
|
|
|
@ -759,7 +837,11 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Do not highlight when dragging over the current group */
|
|
|
|
|
if (Vehicle::Get(vehicle_sel)->group_id == new_group_over) new_group_over = INVALID_GROUP;
|
|
|
|
|
if (this->vehicle_sel != INVALID_VEHICLE) {
|
|
|
|
|
if (Vehicle::Get(vehicle_sel)->group_id == new_group_over) new_group_over = INVALID_GROUP;
|
|
|
|
|
} else if (this->group_sel != INVALID_GROUP) {
|
|
|
|
|
if (this->group_sel == new_group_over || Group::Get(this->group_sel)->parent == new_group_over) new_group_over = INVALID_GROUP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mark widgets as dirty if the group changed. */
|
|
|
|
|
if (new_group_over != this->group_over) {
|
|
|
|
|