static void compute_bounding_box_subtree(TreeWidget tree, Widget w, int depth) { TreeConstraints tc = TREE_CONSTRAINT(w); /* info attached to all kids */ int i; Bool horiz = IsHorizontal (tree); Dimension newwidth, newheight; Dimension bw2 = w->core.border_width * 2; /* * Set the max-size per level. */ if (depth >= tree->tree.n_largest) { initialize_dimensions (&tree->tree.largest, &tree->tree.n_largest, depth + 1); } newwidth = ((horiz ? w->core.width : w->core.height) + bw2); if (tree->tree.largest[depth] < newwidth) tree->tree.largest[depth] = newwidth; /* * initialize */ tc->tree.bbwidth = w->core.width + bw2; tc->tree.bbheight = w->core.height + bw2; if (tc->tree.n_children == 0) return; /* * Figure the size of the opposite dimension (vertical if tree is * horizontal, else vice versa). The other dimension will be set * in the second pass once we know the maximum dimensions. */ newwidth = 0; newheight = 0; for (i = 0; i < tc->tree.n_children; i++) { Widget child = tc->tree.children[i]; TreeConstraints cc = TREE_CONSTRAINT(child); compute_bounding_box_subtree (tree, child, depth + 1); if (horiz) { if (newwidth < cc->tree.bbwidth) newwidth = cc->tree.bbwidth; newheight += tree->tree.vpad + cc->tree.bbheight; } else { if (newheight < cc->tree.bbheight) newheight = cc->tree.bbheight; newwidth += tree->tree.hpad + cc->tree.bbwidth; } } tc->tree.bbsubwidth = newwidth; tc->tree.bbsubheight = newheight; /* * Now fit parent onto side (or top) of bounding box and correct for * extra padding. Be careful of unsigned arithmetic. */ if (horiz) { tc->tree.bbwidth += tree->tree.hpad + newwidth; newheight -= tree->tree.vpad; if (newheight > tc->tree.bbheight) tc->tree.bbheight = newheight; } else { tc->tree.bbheight += tree->tree.vpad + newheight; newwidth -= tree->tree.hpad; if (newwidth > tc->tree.bbwidth) tc->tree.bbwidth = newwidth; } }
static void arrange_subtree(TreeWidget tree, Widget w, int depth, int x, int y) { TreeConstraints tc = TREE_CONSTRAINT(w); /* info attached to all kids */ TreeConstraints firstcc, lastcc; int i; int newx, newy; Bool horiz = IsHorizontal (tree); Widget child = NULL; Dimension tmp; Dimension bw2 = w->core.border_width * 2; Bool relayout = True; /* * If no children, then just lay out where requested. */ tc->tree.x = x; tc->tree.y = y; if (horiz) { int myh = (w->core.height + bw2); if (myh > (int)tc->tree.bbsubheight) { y += (myh - (int)tc->tree.bbsubheight) / 2; relayout = False; } } else { int myw = (w->core.width + bw2); if (myw > (int)tc->tree.bbsubwidth) { x += (myw - (int)tc->tree.bbsubwidth) / 2; relayout = False; } } if ((tmp = ((Dimension) x) + tc->tree.bbwidth) > tree->tree.maxwidth) tree->tree.maxwidth = tmp; if ((tmp = ((Dimension) y) + tc->tree.bbheight) > tree->tree.maxheight) tree->tree.maxheight = tmp; if (tc->tree.n_children == 0) return; /* * Have children, so walk down tree laying out children, then laying * out parents. */ if (horiz) { newx = x + tree->tree.largest[depth]; if (depth > 0) newx += tree->tree.hpad; newy = y; } else { newx = x; newy = y + tree->tree.largest[depth]; if (depth > 0) newy += tree->tree.vpad; } for (i = 0; i < tc->tree.n_children; i++) { TreeConstraints cc; child = tc->tree.children[i]; /* last value is used outside loop */ cc = TREE_CONSTRAINT(child); arrange_subtree (tree, child, depth + 1, newx, newy); if (horiz) { newy += tree->tree.vpad + cc->tree.bbheight; } else { newx += tree->tree.hpad + cc->tree.bbwidth; } } /* * now layout parent between first and last children */ if (relayout) { Position adjusted; firstcc = TREE_CONSTRAINT (tc->tree.children[0]); lastcc = TREE_CONSTRAINT (child); /* Adjustments are disallowed if they result in a position above * or to the left of the originally requested position, because * this could collide with the position of the previous sibling. */ if (horiz) { tc->tree.x = x; adjusted = firstcc->tree.y + ((lastcc->tree.y + (Position) child->core.height + (Position) child->core.border_width * 2 - firstcc->tree.y - (Position) w->core.height - (Position) w->core.border_width * 2 + 1) / 2); if (adjusted > tc->tree.y) tc->tree.y = adjusted; } else { adjusted = firstcc->tree.x + ((lastcc->tree.x + (Position) child->core.width + (Position) child->core.border_width * 2 - firstcc->tree.x - (Position) w->core.width - (Position) w->core.border_width * 2 + 1) / 2); if (adjusted > tc->tree.x) tc->tree.x = adjusted; tc->tree.y = y; } } }
void GUISlider::Draw(Common::Bitmap *ds) { Rect bar; Rect handle; int thickness; if (MinValue >= MaxValue) MaxValue = MinValue + 1; Value = Math::Clamp(Value, MinValue, MaxValue); // it's a horizontal slider if (IsHorizontal()) { thickness = Height / 3; bar.Left = X + 1; bar.Top = Y + Height / 2 - thickness; bar.Right = X + Width - 1; bar.Bottom = Y + Height / 2 + thickness + 1; handle.Left = (int)(((float)(Value - MinValue) / (float)(MaxValue - MinValue)) * (float)(Width - 4) - 2) + bar.Left + 1; handle.Top = bar.Top - (thickness - 1); handle.Right = handle.Left + 4; handle.Bottom = bar.Bottom + (thickness - 1); if (HandleImage > 0) { // store the centre of the pic rather than the top handle.Top = bar.Top + (bar.Bottom - bar.Top) / 2 + 1; handle.Left += 2; } handle.Top += HandleOffset; handle.Bottom += HandleOffset; } // vertical slider else { thickness = Width / 3; bar.Left = X + Width / 2 - thickness; bar.Top = Y + 1; bar.Right = X + Width / 2 + thickness + 1; bar.Bottom = Y + Height - 1; handle.Top = (int)(((float)(MaxValue - Value) / (float)(MaxValue - MinValue)) * (float)(Height - 4) - 2) + bar.Top + 1; handle.Left = bar.Left - (thickness - 1); handle.Bottom = handle.Top + 4; handle.Right = bar.Right + (thickness - 1); if (HandleImage > 0) { // store the centre of the pic rather than the left handle.Left = bar.Left + (bar.Right - bar.Left) / 2 + 1; handle.Top += 2; } handle.Left += HandleOffset; handle.Right += HandleOffset; } color_t draw_color; if (BgImage > 0) { // tiled image as slider background int x_inc = 0; int y_inc = 0; if (IsHorizontal()) { x_inc = get_adjusted_spritewidth(BgImage); // centre the image vertically bar.Top = Y + (Height / 2) - get_adjusted_spriteheight(BgImage) / 2; } else { y_inc = get_adjusted_spriteheight(BgImage); // centre the image horizontally bar.Left = X + (Width / 2) - get_adjusted_spritewidth(BgImage) / 2; } int cx = bar.Left; int cy = bar.Top; // draw the tiled background image do { draw_gui_sprite(ds, BgImage, cx, cy, true); cx += x_inc; cy += y_inc; // done as a do..while so that at least one of the image is drawn } while ((cx + x_inc <= bar.Right) && (cy + y_inc <= bar.Bottom)); } else { // normal grey background draw_color = ds->GetCompatibleColor(16); ds->FillRect(Rect(bar.Left + 1, bar.Top + 1, bar.Right - 1, bar.Bottom - 1), draw_color); draw_color = ds->GetCompatibleColor(8); ds->DrawLine(Line(bar.Left, bar.Top, bar.Left, bar.Bottom), draw_color); ds->DrawLine(Line(bar.Left, bar.Top, bar.Right, bar.Top), draw_color); draw_color = ds->GetCompatibleColor(15); ds->DrawLine(Line(bar.Right, bar.Top + 1, bar.Right, bar.Bottom), draw_color); ds->DrawLine(Line(bar.Left, bar.Bottom, bar.Right, bar.Bottom), draw_color); } if (HandleImage > 0) { // an image for the slider handle if (spriteset[HandleImage] == NULL) HandleImage = 0; handle.Left -= get_adjusted_spritewidth(HandleImage) / 2; handle.Top -= get_adjusted_spriteheight(HandleImage) / 2; draw_gui_sprite(ds, HandleImage, handle.Left, handle.Top, true); handle.Right = handle.Left + get_adjusted_spritewidth(HandleImage); handle.Bottom = handle.Top + get_adjusted_spriteheight(HandleImage); } else { // normal grey tracker handle draw_color = ds->GetCompatibleColor(7); ds->FillRect(Rect(handle.Left, handle.Top, handle.Right, handle.Bottom), draw_color); draw_color = ds->GetCompatibleColor(15); ds->DrawLine(Line(handle.Left, handle.Top, handle.Right, handle.Top), draw_color); ds->DrawLine(Line(handle.Left, handle.Top, handle.Left, handle.Bottom), draw_color); draw_color = ds->GetCompatibleColor(16); ds->DrawLine(Line(handle.Right, handle.Top + 1, handle.Right, handle.Bottom), draw_color); ds->DrawLine(Line(handle.Left + 1, handle.Bottom, handle.Right, handle.Bottom), draw_color); } _cachedHandle = handle; }