Bug 231313 - Change -moz-appearance: tab on Mac OS X to draw new-style tabs. r=roc, a191=beltzner

This commit is contained in:
Markus Stange 2008-11-27 23:16:13 +01:00
Родитель 1df74a8c19
Коммит 20afddfa26
4 изменённых файлов: 111 добавлений и 24 удалений

Просмотреть файл

@ -101,10 +101,8 @@ protected:
void DrawProgress(CGContextRef context, const HIRect& inBoxRect,
PRBool inIsIndeterminate, PRBool inIsHorizontal,
PRInt32 inValue, PRInt32 inMaxValue, nsIFrame* aFrame);
void DrawTab(CGContextRef context, const HIRect& inBoxRect,
PRBool inIsDisabled, PRBool inIsFrontmost,
PRBool inIsHorizontal, PRBool inTabBottom,
PRInt32 inState, nsIFrame* aFrame);
void DrawTab(CGContextRef context, HIRect inBoxRect, PRInt32 inState,
nsIFrame* aFrame);
void DrawTabPanel(CGContextRef context, const HIRect& inBoxRect, nsIFrame* aFrame);
void DrawScale(CGContextRef context, const HIRect& inBoxRect,
PRBool inIsDisabled, PRInt32 inState,

Просмотреть файл

@ -900,10 +900,11 @@ nsNativeThemeCocoa::DrawTabPanel(CGContextRef cgContext, const HIRect& inBoxRect
HIThemeTabPaneDrawInfo tpdi;
tpdi.version = 0;
tpdi.version = 1;
tpdi.state = FrameIsInActiveWindow(aFrame) ? kThemeStateActive : kThemeStateInactive;
tpdi.direction = kThemeTabNorth;
tpdi.size = kHIThemeTabSizeNormal;
tpdi.kind = kHIThemeTabKindNormal;
HIThemeDrawTabPane(&inBoxRect, &tpdi, cgContext, HITHEME_ORIENTATION);
@ -948,25 +949,29 @@ nsNativeThemeCocoa::DrawScale(CGContextRef cgContext, const HIRect& inBoxRect,
}
#define NATURAL_MINI_TAB_BUTTON_HEIGHT 17
#define NATURAL_SMALL_TAB_BUTTON_HEIGHT 20
#define NATURAL_REGULAR_TAB_BUTTON_HEIGHT 23
void
nsNativeThemeCocoa::DrawTab(CGContextRef cgContext, const HIRect& inBoxRect,
PRBool inIsDisabled, PRBool inIsFrontmost,
PRBool inIsHorizontal, PRBool inTabBottom,
nsNativeThemeCocoa::DrawTab(CGContextRef cgContext, HIRect inBoxRect,
PRInt32 inState, nsIFrame* aFrame)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
HIThemeTabDrawInfo tdi;
tdi.version = 1;
tdi.version = 0;
if (inIsFrontmost) {
if (inIsDisabled)
PRBool isSelected = IsSelectedTab(aFrame);
PRBool isDisabled = IsDisabled(aFrame);
if (isSelected) {
if (isDisabled)
tdi.style = kThemeTabFrontUnavailable;
else
tdi.style = FrameIsInActiveWindow(aFrame) ? kThemeTabFront : kThemeTabFrontInactive;
} else {
if (inIsDisabled)
if (isDisabled)
tdi.style = kThemeTabNonFrontUnavailable;
else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
tdi.style = kThemeTabNonFrontPressed;
@ -974,10 +979,55 @@ nsNativeThemeCocoa::DrawTab(CGContextRef cgContext, const HIRect& inBoxRect,
tdi.style = FrameIsInActiveWindow(aFrame) ? kThemeTabNonFront : kThemeTabNonFrontInactive;
}
// don't yet support vertical tabs
tdi.direction = inTabBottom ? kThemeTabSouth : kThemeTabNorth;
tdi.direction = kThemeTabNorth;
tdi.size = kHIThemeTabSizeNormal;
tdi.adornment = kThemeAdornmentNone;
if (inBoxRect.size.height < NATURAL_REGULAR_TAB_BUTTON_HEIGHT)
tdi.size = kHIThemeTabSizeSmall;
if (inBoxRect.size.height < NATURAL_SMALL_TAB_BUTTON_HEIGHT)
tdi.size = kHIThemeTabSizeMini;
PRBool isRTL = IsFrameRTL(aFrame);
PRBool isFirst = isRTL ? IsLastTab(aFrame) : IsFirstTab(aFrame);
PRBool isLast = isRTL ? IsFirstTab(aFrame) : IsLastTab(aFrame);
if (isFirst && isLast)
tdi.position = kHIThemeTabPositionOnly;
else if (isFirst)
tdi.position = kHIThemeTabPositionFirst;
else if (isLast)
tdi.position = kHIThemeTabPositionLast;
else
tdi.position = kHIThemeTabPositionMiddle;
// Tab separator management:
// Normal tabs only draw their left separator, in the leftmost pixel row of
// their frame. Selected tabs additionally draw their right separator, outside
// of their frame. To prevent overlapping, the tab to the right of the
// selected tab shouldn't draw its left separator.
tdi.adornment = kHIThemeTabAdornmentNone;
if (isRTL ? IsBeforeSelectedTab(aFrame) : IsAfterSelectedTab(aFrame)) {
if (nsToolkit::OnLeopardOrLater()) {
// On Leopard, the tab's left edge must be shifted 1px to the right.
// On Tiger, this happens automatically when no leading separator is drawn.
inBoxRect.origin.x += 1;
inBoxRect.size.width -= 1;
}
}
else {
tdi.adornment = kHIThemeTabAdornmentLeadingSeparator;
}
if (isSelected && !isLast) {
tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
if (nsToolkit::OnLeopardOrLater()) {
// On Tiger, the right separator is drawn outside of the frame.
// On Leopard, the right edge must be shifted 1px to the right.
inBoxRect.size.width += 1;
}
}
if (inState & NS_EVENT_STATE_FOCUS)
tdi.adornment |= kThemeAdornmentFocus;
HIThemeDrawTab(&inBoxRect, &tdi, cgContext, HITHEME_ORIENTATION, NULL);
@ -1592,12 +1642,8 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
(IsDisabled(aFrame) || IsReadOnly(aFrame)), eventState);
break;
case NS_THEME_TAB: {
DrawTab(cgContext, macRect,
IsDisabled(aFrame), IsSelectedTab(aFrame),
PR_TRUE, IsBottomTab(aFrame),
eventState, aFrame);
}
case NS_THEME_TAB:
DrawTab(cgContext, macRect, eventState, aFrame);
break;
case NS_THEME_TAB_PANELS:
@ -1739,6 +1785,7 @@ nsNativeThemeCocoa::GetWidgetOverflow(nsIDeviceContext* aContext, nsIFrame* aFra
case NS_THEME_DROPDOWN_BUTTON:
case NS_THEME_CHECKBOX:
case NS_THEME_RADIO:
case NS_THEME_TAB:
{
// We assume that the above widgets can draw a focus ring that will be less than
// or equal to 4 pixels thick.
@ -1833,6 +1880,12 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsIRenderingContext* aContext,
break;
}
case NS_THEME_TAB:
{
aResult->SizeTo(0, NATURAL_MINI_TAB_BUTTON_HEIGHT);
break;
}
case NS_THEME_SCALE_HORIZONTAL:
{
SInt32 scaleHeight = 0;
@ -2072,8 +2125,6 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a
case NS_THEME_TAB_PANELS:
case NS_THEME_TAB:
case NS_THEME_TAB_LEFT_EDGE:
case NS_THEME_TAB_RIGHT_EDGE:
case NS_THEME_TREEVIEW_TWISTY:
case NS_THEME_TREEVIEW_TWISTY_OPEN:

Просмотреть файл

@ -287,6 +287,34 @@ nsNativeTheme::IsHorizontal(nsIFrame* aFrame)
eCaseMatters);
}
PRBool
nsNativeTheme::IsNextToSelectedTab(nsIFrame* aFrame, PRInt32 aOffset)
{
if (!aFrame)
return PR_FALSE;
if (aOffset == 0)
return IsSelectedTab(aFrame);
PRInt32 thisTabIndex = -1, selectedTabIndex = -1;
nsIFrame* currentTab = aFrame->GetParent()->GetFirstChild(NULL);
for (PRInt32 i = 0; currentTab; currentTab = currentTab->GetNextSibling()) {
if (currentTab->GetRect().width == 0)
continue;
if (aFrame == currentTab)
thisTabIndex = i;
if (IsSelectedTab(currentTab))
selectedTabIndex = i;
++i;
}
if (thisTabIndex == -1 || selectedTabIndex == -1)
return PR_FALSE;
return (thisTabIndex - selectedTabIndex == aOffset);
}
// progressbar:
PRBool
nsNativeTheme::IsIndeterminateProgress(nsIFrame* aFrame)

Просмотреть файл

@ -114,6 +114,16 @@ class nsNativeTheme
PRBool IsSelectedTab(nsIFrame* aFrame) {
return CheckBooleanAttr(aFrame, nsWidgetAtoms::selected);
}
PRBool IsNextToSelectedTab(nsIFrame* aFrame, PRInt32 aOffset);
PRBool IsBeforeSelectedTab(nsIFrame* aFrame) {
return IsNextToSelectedTab(aFrame, -1);
}
PRBool IsAfterSelectedTab(nsIFrame* aFrame) {
return IsNextToSelectedTab(aFrame, 1);
}
// toolbarbutton:
PRBool IsCheckedButton(nsIFrame* aFrame) {