menus: align menu item icons and accelerators

This commit is contained in:
Vadim Lopatin 2014-05-07 11:41:22 +04:00
parent a7d062097a
commit 3adf2138b5
1 changed files with 123 additions and 2 deletions

View File

@ -84,13 +84,103 @@ class MenuItem {
}
/// widget to draw menu item
class MenuItemWidget : HorizontalLayout {
class MenuItemWidget : WidgetGroup {
protected MenuItem _item;
protected ImageWidget _icon;
protected TextWidget _accel;
protected TextWidget _label;
protected int _labelWidth;
protected int _iconWidth;
protected int _accelWidth;
protected int _height;
@property MenuItem item() { return _item; }
this(MenuItem item) {
void setSubitemSizes(int maxLabelWidth, int maxHeight, int maxIconWidth, int maxAccelWidth) {
_labelWidth = maxLabelWidth;
_height = maxHeight;
_iconWidth = maxIconWidth;
_accelWidth = maxAccelWidth;
}
void measureSubitems(ref int maxLabelWidth, ref int maxHeight, ref int maxIconWidth, ref int maxAccelWidth) {
_label.measure(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED);
if (maxLabelWidth < _label.measuredWidth)
maxLabelWidth = _label.measuredWidth;
if (maxHeight < _label.measuredHeight)
maxHeight = _label.measuredHeight;
if (_icon) {
_icon.measure(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED);
if (maxIconWidth < _icon.measuredWidth)
maxIconWidth = _icon.measuredWidth;
if (maxHeight < _icon.measuredHeight)
maxHeight = _icon.measuredHeight;
}
if (_accel) {
_accel.measure(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED);
if (maxAccelWidth < _accel.measuredWidth)
maxAccelWidth = _accel.measuredWidth;
if (maxHeight < _accel.measuredHeight)
maxHeight = _accel.measuredHeight;
}
}
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
override void measure(int parentWidth, int parentHeight) {
Rect m = margins;
Rect p = padding;
// calc size constraints for children
int pwidth = parentWidth;
int pheight = parentHeight;
if (parentWidth != SIZE_UNSPECIFIED)
pwidth -= m.left + m.right + p.left + p.right;
if (parentHeight != SIZE_UNSPECIFIED)
pheight -= m.top + m.bottom + p.top + p.bottom;
if (_labelWidth)
measuredContent(parentWidth, parentHeight, _iconWidth + _labelWidth + _accelWidth, _height); // for vertical (popup menu)
else {
_label.measure(pwidth, pheight);
measuredContent(parentWidth, parentHeight, _label.measuredWidth, _label.measuredHeight); // for horizonral (main) menu
}
}
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
override void layout(Rect rc) {
_needLayout = false;
if (visibility == Visibility.Gone) {
return;
}
_pos = rc;
applyMargins(rc);
applyPadding(rc);
Rect labelRc = rc;
Rect iconRc = rc;
Rect accelRc = rc;
iconRc.right = iconRc.left + _iconWidth;
accelRc.left = accelRc.right - _accelWidth;
labelRc.left += _iconWidth;
labelRc.right -= _accelWidth;
if (_icon)
_icon.layout(iconRc);
if (_accel)
_accel.layout(accelRc);
_label.layout(labelRc);
}
/// Draw widget at its position to buffer
override void onDraw(DrawBuf buf) {
if (visibility != Visibility.Visible)
return;
super.onDraw(buf);
Rect rc = _pos;
applyMargins(rc);
applyPadding(rc);
auto saver = ClipRectSaver(buf, rc);
for (int i = 0; i < _children.count; i++) {
Widget item = _children.get(i);
if (item.visibility != Visibility.Visible)
continue;
item.onDraw(buf);
}
}
this(MenuItem item) {
id="menuitem";
_item = item;
styleId = "MENU_ITEM";
@ -147,6 +237,37 @@ class MenuWidgetBase : ListWidget {
ownAdapter = adapter;
}
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
override void measure(int parentWidth, int parentHeight) {
if (_orientation == Orientation.Horizontal) {
// for horizontal (main) menu, don't align items
super.measure(parentWidth, parentHeight);
return;
}
if (visibility == Visibility.Gone) {
_measuredWidth = _measuredHeight = 0;
return;
}
int maxLabelWidth;
int maxHeight;
int maxIconWidth;
int maxAccelWidth;
/// find max dimensions for item icon and accelerator sizes
for (int i = 0; i < itemCount; i++) {
MenuItemWidget w = cast(MenuItemWidget)itemWidget(i);
if (w)
w.measureSubitems(maxLabelWidth, maxHeight, maxIconWidth, maxAccelWidth);
}
/// set equal dimensions for item icon and accelerator sizes
for (int i = 0; i < itemCount; i++) {
MenuItemWidget w = cast(MenuItemWidget)itemWidget(i);
if (w)
w.setSubitemSizes(maxLabelWidth, maxHeight, maxIconWidth, maxAccelWidth);
}
super.measure(parentWidth, parentHeight);
}
protected void onPopupClosed(PopupWidget p) {
_openedPopup = null;
_openedMenu = null;