src/gui/styles/qs60style.cpp
changeset 33 3e2da88830cd
parent 29 b72c6db6890b
child 37 758a864f9613
--- a/src/gui/styles/qs60style.cpp	Tue Jul 06 15:10:48 2010 +0300
+++ b/src/gui/styles/qs60style.cpp	Wed Aug 18 10:37:55 2010 +0300
@@ -135,13 +135,13 @@
     {SE_TableHeaderItem,        QS60StyleEnums::SP_QsnFrCaleHeadingCenter},
     {SE_ToolTip,                QS60StyleEnums::SP_QsnFrPopupPreviewCenter},
     {SE_ToolBar,                QS60StyleEnums::SP_QsnFrPopupSubCenter},
-    {SE_ToolBarButton,          QS60StyleEnums::SP_QsnFrSctrlButtonCenter},
-    {SE_ToolBarButtonPressed,   QS60StyleEnums::SP_QsnFrSctrlButtonCenterPressed},
+    {SE_ToolBarButton,          QS60StyleEnums::SP_QgnFrSctrlButtonCenter},
+    {SE_ToolBarButtonPressed,   QS60StyleEnums::SP_QgnFrSctrlButtonCenterPressed},
     {SE_PanelBackground,        QS60StyleEnums::SP_QsnFrSetOptCenter},
     {SE_ButtonInactive,         QS60StyleEnums::SP_QsnFrButtonCenterInactive},
     {SE_Editor,                 QS60StyleEnums::SP_QsnFrInputCenter},
     {SE_TableItemPressed,       QS60StyleEnums::SP_QsnFrGridCenterPressed},
-    {SE_ListItemPressed,        QS60StyleEnums::SP_QsnFrListPressed},
+    {SE_ListItemPressed,        QS60StyleEnums::SP_QsnFrListCenterPressed},
 };
 
 static const int frameElementsCount =
@@ -1750,45 +1750,56 @@
             }
             const bool enabled = optionMenuItem.state & State_Enabled;
             const bool checkable = optionMenuItem.checkType != QStyleOptionMenuItem::NotCheckable;
+            bool ignoreCheckMark = false;
+
+#ifndef QT_NO_COMBOBOX
+            if (qobject_cast<const QComboBox*>(widget))
+                ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate
+#endif
 
             uint text_flags = Qt::AlignLeading | Qt::TextShowMnemonic | Qt::TextDontClip
                             | Qt::TextSingleLine | Qt::AlignVCenter;
             if (!styleHint(SH_UnderlineShortcut, menuItem, widget))
                 text_flags |= Qt::TextHideMnemonic;
 
-            const bool selected = (option->state & State_Selected) && (option->state & State_Enabled);
-            if (selected)
-                QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
-
             QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget);
             QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget);
 
-            //todo: move the vertical spacing stuff into subElementRect
+            QStyleOptionMenuItem optionCheckBox;
+
+            //Regardless of checkbox visibility, make room for it, this mirrors native implementation,
+            //where text and icon placement is static regardless of content of menu item.
+            optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem);
+            optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth));
+            optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight));
+
             const int vSpacing = QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing);
-            if (checkable){
-                const int hSpacing = QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing);
-                QStyleOptionMenuItem optionCheckBox;
-                optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem);
-                optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth));
-                optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight));
-                optionCheckBox.rect.moveCenter(QPoint(
-                        optionCheckBox.rect.center().x(), 
-                        menuItem->rect.center().y()));
-                const int moveByX = optionCheckBox.rect.width() + vSpacing;
-                if (optionMenuItem.direction == Qt::LeftToRight) {
-                    textRect.translate(moveByX, 0);
-                    iconRect.translate(moveByX, 0);
-                    iconRect.setWidth(iconRect.width() + vSpacing);
-                    textRect.setWidth(textRect.width() - moveByX - vSpacing);
-                    optionCheckBox.rect.translate(vSpacing >> 1, hSpacing >> 1);
-                } else {
-                    textRect.setWidth(textRect.width() - moveByX);
-                    iconRect.setWidth(iconRect.width() + vSpacing);
-                    iconRect.translate(-optionCheckBox.rect.width() - vSpacing, 0);
-                    optionCheckBox.rect.translate(textRect.width() + iconRect.width(), 0);
-                }
+            //The vertical spacing is doubled; it needs one spacing to separate checkbox from
+            //highlight and then it needs one to separate it whatever is shown after it (text/icon/both).
+            const int moveByX = optionCheckBox.rect.width() + 2 * vSpacing;
+            optionCheckBox.rect.moveCenter(QPoint(
+                    optionCheckBox.rect.center().x() + moveByX >> 1, 
+                    menuItem->rect.center().y()));
+
+            if (optionMenuItem.direction != Qt::LeftToRight)
+                optionCheckBox.rect.translate(textRect.width() + iconRect.width(), 0);
+
+
+            const bool selected = (option->state & State_Selected) && (option->state & State_Enabled);
+            if (selected) {
+                const int spacing = ignoreCheckMark ? (vSpacing + QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth)) : 0;
+                const int start = optionMenuItem.rect.left() + spacing;
+                const int end = optionMenuItem.rect.right() - spacing;
+                //-1 adjustment to avoid highlight being on top of possible separator item
+                const QRect highlightRect = QRect(
+                        QPoint(start, option->rect.top()), 
+                        QPoint(end, option->rect.bottom() - 1));
+                QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, highlightRect, flags);
+            }
+            
+            if (checkable && !ignoreCheckMark)
                 drawPrimitive(PE_IndicatorMenuCheckMark, &optionCheckBox, painter, widget);
-            }
+
             //draw icon and/or checkState
             QPixmap pix = menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize),
                 enabled ? QIcon::Normal : QIcon::Disabled);
@@ -1799,7 +1810,7 @@
                     textRect.translate(vSpacing, 0);
                 else
                     textRect.translate(-vSpacing, 0);
-                textRect.setWidth(textRect.width()-vSpacing);
+                textRect.setWidth(textRect.width() - vSpacing);
             }
 
             //draw indicators
@@ -1817,7 +1828,7 @@
                     QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointSouth;
                 painter->save();
                 painter->setPen(option->palette.windowText().color());
-                QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnIndiSubMenu, painter, arrowOptions.rect,
+                QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnIndiSubmenu, painter, arrowOptions.rect,
                     (flags | QS60StylePrivate::SF_ColorSkinned | arrowDirection));
                 painter->restore();
             }
@@ -1837,6 +1848,24 @@
             QCommonStyle::drawItemText(painter, textRect, text_flags,
                     optionMenuItem.palette, enabled,
                     optionMenuItem.text, QPalette::Text);
+
+            //In Sym^3, native menu items have "lines" between them
+            if (QS60StylePrivate::isSingleClickUi()) {
+                const QColor lineColorAlpha = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 15, 0);
+                const int spacing = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth);
+                //native platform sets each color byte to same value for "line 16" which just defines alpha for
+                //menuitem lines; lets use first byte "red".
+                QColor lineColor = optionMenuItem.palette.text().color();
+                if (lineColorAlpha.isValid())
+                    lineColor.setAlpha(lineColorAlpha.red());
+                painter->save();
+                painter->setPen(lineColor);
+
+                const int lineStartX = optionMenuItem.rect.left() + (QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) - 2) + spacing;
+                const int lineEndX = optionMenuItem.rect.right() - (QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) - 2) - spacing;
+                painter->drawLine(QPoint(lineStartX, optionMenuItem.rect.bottom()), QPoint(lineEndX, optionMenuItem.rect.bottom()));
+                painter->restore();
+            }
             if (!enabled)
                 painter->restore();
         }
@@ -2233,6 +2262,8 @@
             if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget) &&
                 option->palette.window().texture().cacheKey() ==
                     QS60StylePrivate::m_themePalette->window().texture().cacheKey())
+                //todo: for combobox listviews, the background should include area for menu scrollers,
+                //but this produces drawing issues as we need to turn clipping off.
                 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PopupBackground, painter, option->rect, flags);
             else
                 commonStyleDraws = true;
@@ -2548,10 +2579,12 @@
                 }
             }
             sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
+            //native items have small empty areas at the beginning and end of menu item
+            sz.setWidth(sz.width() + 2 * pixelMetric(PM_MenuHMargin) + 2 * QS60StylePrivate::pixelMetric(PM_FrameCornerWidth));
             if (QS60StylePrivate::isTouchSupported())
                 //Make itemview easier to use in touch devices
                 //QCommonStyle does not adjust height with horizontal margin, it only adjusts width
-                sz.setHeight(sz.height() + 2 * pixelMetric(PM_FocusFrameVMargin));
+                sz.setHeight(sz.height() + 2 * pixelMetric(PM_FocusFrameVMargin) - 8); //QCommonstyle adds 8 to height that this style handles through PM values
             break;
 #ifndef QT_NO_COMBOBOX
         case CT_ComboBox: {
@@ -2816,16 +2849,7 @@
                     }
                 break;
                 case SC_ComboBoxListBoxPopup: {
-                    const QRect desktopContent = QApplication::desktop()->availableGeometry();
-
-                    // take the size of this and position bottom above available area
-                    QRect popupRect;
-                    const int width = desktopContent.width() - pixelMetric(PM_LayoutRightMargin) - pixelMetric(PM_LayoutLeftMargin);
-                    popupRect.setWidth(width);
-                    popupRect.setHeight(desktopContent.height()); //combobox resets height anyway based on content
-                    popupRect.setBottom(desktopContent.bottom());
-                    popupRect.translate(pixelMetric(PM_LayoutLeftMargin), 0);
-                    ret = popupRect;
+                    ret = QApplication::desktop()->availableGeometry();
                     }
                 break;
             default:
@@ -2980,21 +3004,38 @@
                     pixelMetric(PM_SmallIconSize, opt, widget);
                 ret = menuItem->rect;
 
+                QRect checkBoxRect = checkable ? menuItem->rect : QRect();
+                if (checkable) {
+                    checkBoxRect.setWidth(pixelMetric(PM_IndicatorWidth));
+                    checkBoxRect.setHeight(pixelMetric(PM_IndicatorHeight));
+                }
+
+                const int vSpacing = QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing);
+                //The vertical spacing is doubled; it needs one spacing to separate checkbox from
+                //highlight and then it needs one to separate it whatever is shown after it (text/icon/both).
+                const int moveByX = checkBoxRect.width() + 2 * vSpacing;
+
                 if (element == SE_ItemViewItemDecoration) {
                     if (menuItem->icon.isNull()) {
                         ret = QRect();
                     } else {
                         if (menuItem->direction == Qt::RightToLeft)
-                            ret.translate(ret.width() - indicatorWidth, 0);
+                            ret.translate(ret.width() - indicatorWidth - moveByX, 0);
+                        else
+                            ret.translate(moveByX, 0);
                         ret.setWidth(indicatorWidth);
                     }
                 } else {
-                    ret = menuItem->rect;
-                    if (!menuItem->icon.isNull())
+                    if (!menuItem->icon.isNull()) {
                         if (menuItem->direction == Qt::LeftToRight)
                             ret.adjust(indicatorWidth, 0, 0, 0);
                         else
                             ret.adjust(0, 0, -indicatorWidth, 0);
+                    }
+                    if (menuItem->direction == Qt::LeftToRight)
+                        ret.adjust(moveByX, 0, 0, 0);
+                    else
+                        ret.adjust(0, 0, -moveByX, 0);
 
                     // Make room for submenu indicator
                     if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu){
@@ -3072,6 +3113,11 @@
         case SE_CheckBoxFocusRect:
             ret = opt->rect;
             break;
+        case SE_ProgressBarLabel:
+        case SE_ProgressBarContents:
+        case SE_ProgressBarGroove:
+            ret = opt->rect;
+            break;
         default:
             ret = QCommonStyle::subElementRect(element, opt, widget);
     }
@@ -3321,13 +3367,13 @@
             part = QS60StyleEnums::SP_QgnNoteErased;
             break;
         case SP_ToolBarHorizontalExtensionButton:
-            part = QS60StyleEnums::SP_QgnIndiSubMenu;
+            part = QS60StyleEnums::SP_QgnIndiSubmenu;
             if (QApplication::layoutDirection() == Qt::RightToLeft)
                 adjustedFlags |= QS60StylePrivate::SF_PointSouth;
             break;
         case SP_ToolBarVerticalExtensionButton:
             adjustedFlags |= QS60StylePrivate::SF_PointEast;
-            part = QS60StyleEnums::SP_QgnIndiSubMenu;
+            part = QS60StyleEnums::SP_QgnIndiSubmenu;
             break;
 
         default: