summaryrefslogtreecommitdiff
path: root/src/group_gui.cpp
diff options
context:
space:
mode:
authorpeter1138 <peter1138@openttd.org>2014-04-08 21:09:06 +0000
committerpeter1138 <peter1138@openttd.org>2014-04-08 21:09:06 +0000
commit567d0ff3a7286fe830bf188c2911e3d10d70eb8c (patch)
treef61a570d4fb3a9bb1419b0eee818692686d75462 /src/group_gui.cpp
parent3e9c10f9e11935a82d33fd5c66592d795c279777 (diff)
downloadopenttd-567d0ff3a7286fe830bf188c2911e3d10d70eb8c.tar.xz
(svn r26450) -Feature: Hierarchical vehicle subgroups.
Diffstat (limited to 'src/group_gui.cpp')
-rw-r--r--src/group_gui.cpp138
1 files changed, 110 insertions, 28 deletions
diff --git a/src/group_gui.cpp b/src/group_gui.cpp
index ed3176e27..698f9a71f 100644
--- a/src/group_gui.cpp
+++ b/src/group_gui.cpp
@@ -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 */
@@ -159,6 +153,36 @@ private:
}
/**
+ * (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) {