Bug 1421088 - Don't pass an nsIFrame* to DrawMeter. r?spohl
MozReview-Commit-ID: 63ZuRb6VRSY
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -79,16 +79,22 @@ public:
eDown
};
enum class SegmentType : uint8_t {
eToolbarButton,
eTab
};
+ enum class OptimumState : uint8_t {
+ eOptimum,
+ eSubOptimum,
+ eSubSubOptimum
+ };
+
struct ControlParams {
ControlParams()
: disabled(false)
, insideActiveWindow(false)
, pressed(false)
, focused(false)
, rtl(false)
{}
@@ -181,16 +187,26 @@ public:
double max = 0.0;
float verticalAlignFactor = 0.5f;
bool insideActiveWindow = false;
bool indeterminate = false;
bool horizontal = false;
bool rtl = false;
};
+ struct MeterParams {
+ double value = 0;
+ double min = 0;
+ double max = 0;
+ OptimumState optimumState = OptimumState::eOptimum;
+ float verticalAlignFactor = 0.5f;
+ bool horizontal = true;
+ bool rtl = false;
+ };
+
struct TreeHeaderCellParams {
ControlParams controlParams;
TreeSortDirection sortDirection = eTreeSortDirection_Natural;
bool lastTreeHeaderCell = false;
};
nsNativeThemeCocoa();
@@ -265,24 +281,25 @@ protected:
SegmentParams ComputeSegmentParams(nsIFrame* aFrame,
mozilla::EventStates aEventState,
SegmentType aSegmentType);
SearchFieldParams ComputeSearchFieldParams(nsIFrame* aFrame,
mozilla::EventStates aEventState);
ProgressParams ComputeProgressParams(nsIFrame* aFrame,
mozilla::EventStates aEventState,
bool aIsHorizontal);
+ MeterParams ComputeMeterParams(nsIFrame* aFrame);
TreeHeaderCellParams ComputeTreeHeaderCellParams(nsIFrame* aFrame,
mozilla::EventStates aEventState);
// HITheme drawing routines
void DrawTextBox(CGContextRef context, const HIRect& inBoxRect,
TextBoxParams aParams);
void DrawMeter(CGContextRef context, const HIRect& inBoxRect,
- nsIFrame* aFrame);
+ const MeterParams& aParams);
void DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect,
const SegmentParams& aParams);
void DrawTabPanel(CGContextRef context, const HIRect& inBoxRect, nsIFrame* aFrame);
void DrawScale(CGContextRef context, const HIRect& inBoxRect,
mozilla::EventStates inState, bool inDirection,
bool inIsReverse, int32_t inCurrentValue, int32_t inMinValue,
int32_t inMaxValue, nsIFrame* aFrame);
void DrawCheckboxOrRadio(CGContextRef cgContext, bool inCheckbox,
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -2166,66 +2166,78 @@ static const CellRenderSettings meterSet
{ // Yosemite
{1, 1, 1, 1}, // mini
{1, 1, 1, 1}, // small
{1, 1, 1, 1} // regular
}
}
};
-void
-nsNativeThemeCocoa::DrawMeter(CGContextRef cgContext, const HIRect& inBoxRect,
- nsIFrame* aFrame)
+nsNativeThemeCocoa::MeterParams
+nsNativeThemeCocoa::ComputeMeterParams(nsIFrame* aFrame)
{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK
-
- NS_PRECONDITION(aFrame, "aFrame should not be null here!");
-
- // When using -moz-meterbar on an non meter element, we will not be able to
- // get all the needed information so we just draw an empty meter.
nsIContent* content = aFrame->GetContent();
if (!(content && content->IsHTMLElement(nsGkAtoms::meter))) {
- DrawCellWithSnapping(mMeterBarCell, cgContext, inBoxRect,
- meterSetting, VerticalAlignFactor(aFrame),
- mCellDrawView, IsFrameRTL(aFrame));
- return;
+ return MeterParams();
}
HTMLMeterElement* meterElement = static_cast<HTMLMeterElement*>(content);
- double value = meterElement->Value();
- double min = meterElement->Min();
- double max = meterElement->Max();
+ MeterParams params;
+ params.value = meterElement->Value();
+ params.min = meterElement->Min();
+ params.max = meterElement->Max();
+ EventStates states = meterElement->State();
+ if (states.HasState(NS_EVENT_STATE_SUB_OPTIMUM)) {
+ params.optimumState = OptimumState::eSubOptimum;
+ } else if (states.HasState(NS_EVENT_STATE_SUB_SUB_OPTIMUM)) {
+ params.optimumState = OptimumState::eSubSubOptimum;
+ }
+ params.horizontal = !IsVerticalMeter(aFrame);
+ params.verticalAlignFactor = VerticalAlignFactor(aFrame);
+ params.rtl = IsFrameRTL(aFrame);
+
+ return params;
+}
+
+void
+nsNativeThemeCocoa::DrawMeter(CGContextRef cgContext, const HIRect& inBoxRect,
+ const MeterParams& aParams)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK
NSLevelIndicatorCell* cell = mMeterBarCell;
- [cell setMinValue:min];
- [cell setMaxValue:max];
- [cell setDoubleValue:value];
+ [cell setMinValue:aParams.min];
+ [cell setMaxValue:aParams.max];
+ [cell setDoubleValue:aParams.value];
/**
* The way HTML and Cocoa defines the meter/indicator widget are different.
* So, we are going to use a trick to get the Cocoa widget showing what we
* are expecting: we set the warningValue or criticalValue to the current
* value when we want to have the widget to be in the warning or critical
* state.
*/
- EventStates states = aFrame->GetContent()->AsElement()->State();
-
- // Reset previously set warning and critical values.
- [cell setWarningValue:max+1];
- [cell setCriticalValue:max+1];
-
- if (states.HasState(NS_EVENT_STATE_SUB_OPTIMUM)) {
- [cell setWarningValue:value];
- } else if (states.HasState(NS_EVENT_STATE_SUB_SUB_OPTIMUM)) {
- [cell setCriticalValue:value];
+ switch (aParams.optimumState) {
+ case OptimumState::eOptimum:
+ [cell setWarningValue:aParams.max+1];
+ [cell setCriticalValue:aParams.max+1];
+ break;
+ case OptimumState::eSubOptimum:
+ [cell setWarningValue:aParams.value];
+ [cell setCriticalValue:aParams.max+1];
+ break;
+ case OptimumState::eSubSubOptimum:
+ [cell setWarningValue:aParams.max+1];
+ [cell setCriticalValue:aParams.value];
+ break;
}
HIRect rect = CGRectStandardize(inBoxRect);
- BOOL vertical = IsVerticalMeter(aFrame);
+ BOOL vertical = !aParams.horizontal;
CGContextSaveGState(cgContext);
if (vertical) {
/**
* Cocoa doesn't provide a vertical meter bar so to show one, we have to
* show a rotated horizontal meter bar.
* Given that we want to show a vertical meter bar, we assume that the rect
@@ -2242,18 +2254,18 @@ nsNativeThemeCocoa::DrawMeter(CGContextR
rect.origin.y += rect.size.width / 2.f - rect.size.height / 2.f;
CGContextTranslateCTM(cgContext, CGRectGetMidX(rect), CGRectGetMidY(rect));
CGContextRotateCTM(cgContext, -M_PI / 2.f);
CGContextTranslateCTM(cgContext, -CGRectGetMidX(rect), -CGRectGetMidY(rect));
}
DrawCellWithSnapping(cell, cgContext, rect,
- meterSetting, VerticalAlignFactor(aFrame),
- mCellDrawView, !vertical && IsFrameRTL(aFrame));
+ meterSetting, aParams.verticalAlignFactor,
+ mCellDrawView, !vertical && aParams.rtl);
CGContextRestoreGState(cgContext);
NS_OBJC_END_TRY_ABORT_BLOCK
}
void
nsNativeThemeCocoa::DrawTabPanel(CGContextRef cgContext, const HIRect& inBoxRect,
@@ -3031,17 +3043,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
}
case NS_THEME_PROGRESSBAR_VERTICAL:
DrawProgress(cgContext, macRect,
ComputeProgressParams(aFrame, eventState, false));
break;
case NS_THEME_METERBAR:
- DrawMeter(cgContext, macRect, aFrame);
+ DrawMeter(cgContext, macRect, ComputeMeterParams(aFrame));
break;
case NS_THEME_PROGRESSCHUNK:
case NS_THEME_PROGRESSCHUNK_VERTICAL:
case NS_THEME_METERCHUNK:
// Do nothing: progress and meter bars cases will draw chunks.
break;