//***************************************************************************************
int CBCGPRadialMenuObject::HitTestShape(const CBCGPPoint& pt)
{
	CBCGPRect rect = m_rect;
	if (rect.Width() < rect.Height())
	{
		rect.top += (rect.Height() - rect.Width()) / 2;
		rect.bottom = rect.top + rect.Width();
	}
	else if (rect.Height() < rect.Width())
	{
		rect.left += (rect.Width() - rect.Height()) / 2;
		rect.right = rect.left + rect.Height();
	}

	rect.DeflateRect(2., 2.);

	rect.right -= m_nShadowDepth;
	rect.bottom -= m_nShadowDepth;

	const double radius = rect.Width() / 2;
	const double radiusSmall = INTERNAL_PART * rect.Width() + 1.0;
	const CBCGPPoint center = rect.CenterPoint();

	double dblDistanceToCenter = bcg_distance(pt, center);

	if (dblDistanceToCenter > radius)
	{
		return -1;
	}
	
	const int nItems = (int)m_arItems.GetSize();
	if (dblDistanceToCenter <= radiusSmall)
	{
		return m_bHasCenterButton ? nItems - 1 : -1;
	}

	const int nCircleItems = m_bHasCenterButton ? nItems - 1 : nItems;
	if (nCircleItems == 0)
	{
		return -1;
	}

	double dblDeltaAngle = 360. / nCircleItems;
	double dblStartAngle = 90. - dblDeltaAngle / 2;
	double dblAngle = bcg_normalize_deg(bcg_rad2deg(acos((pt.x - center.x) / dblDistanceToCenter)));
	if (pt.y > center.y)
	{
		dblAngle = 360 - dblAngle;
	}

	int nHit = (int)((dblAngle - dblStartAngle) / dblDeltaAngle);
	if (dblAngle < dblStartAngle)
	{
		nHit = nCircleItems - 1 - (int)((dblStartAngle - dblAngle) / dblDeltaAngle);
	}

	return nHit;
}
//*******************************************************************************
BOOL CBCGPLinearGaugeImpl::ValueToPoint(double dblValue, CBCGPPoint& point, int nScale) const
{
	CBCGPGaugeScaleObject* pScale = GetScale(nScale);
	if (pScale == NULL)
	{
		ASSERT(FALSE);
		return FALSE;
	}

	double dblStart = min(pScale->m_dblStart, pScale->m_dblFinish);
	double dblFinish = max(pScale->m_dblStart, pScale->m_dblFinish);

	if (dblValue < dblStart || dblValue > dblFinish)
	{
		return FALSE;
	}

	if (pScale->m_dblFinish == pScale->m_dblStart)
	{
		return FALSE;
	}

	CBCGPRect rect = m_rect;

	if (m_bIsVertical)
	{
		rect.DeflateRect((pScale->m_dblOffsetFromFrame + m_nFrameSize) * m_sizeScaleRatio.cx, m_sizeMaxLabel.cy / 2 + (m_nFrameSize + 1) * m_sizeScaleRatio.cy);
	}
	else
	{
		rect.DeflateRect(m_sizeMaxLabel.cx / 2 + (m_nFrameSize + 1) * m_sizeScaleRatio.cx, (pScale->m_dblOffsetFromFrame + m_nFrameSize) * m_sizeScaleRatio.cy);
	}

	const double dblTotalSize = m_bIsVertical ? rect.Height() : rect.Width();
	const double delta = dblTotalSize * fabs(dblValue - pScale->m_dblStart) / fabs(pScale->m_dblFinish - pScale->m_dblStart);

	point.x = m_bIsVertical ? rect.left : rect.left + delta;
	point.y = m_bIsVertical ? rect.bottom - delta : rect.top;

	return TRUE;
}
//*******************************************************************************
BOOL CBCGPLinearGaugeImpl::HitTestValue(const CBCGPPoint& pt, double& dblValue, int nScale, BOOL bInsideGauge) const
{
	CBCGPGaugeScaleObject* pScale = GetScale(nScale);
	if (pScale == NULL)
	{
		ASSERT(FALSE);
		return FALSE;
	}

	CBCGPRect rect = m_rect;
	rect.OffsetRect(-m_ptScrollOffset);

	if (m_bIsVertical)
	{
		rect.DeflateRect((pScale->m_dblOffsetFromFrame + m_nFrameSize) * m_sizeScaleRatio.cx, m_sizeMaxLabel.cy / 2 + (m_nFrameSize + 1) * m_sizeScaleRatio.cy);
	}
	else
	{
		rect.DeflateRect(m_sizeMaxLabel.cx / 2 + (m_nFrameSize + 1) * m_sizeScaleRatio.cx, (pScale->m_dblOffsetFromFrame + m_nFrameSize) * m_sizeScaleRatio.cy);
	}

	if (bInsideGauge && !rect.PtInRect(pt))
	{
		return FALSE;
	}

	if (m_bIsVertical)
	{
		const double dblTotalSize = rect.Height();
		dblValue = pScale->m_dblStart + (rect.bottom - pt.y) * fabs(pScale->m_dblFinish - pScale->m_dblStart) / dblTotalSize;
	}
	else
	{
		const double dblTotalSize = rect.Width();
		dblValue = pScale->m_dblStart + (pt.x - rect.left) * fabs(pScale->m_dblFinish - pScale->m_dblStart) / dblTotalSize;
	}

	return TRUE;
}
Example #4
0
//********************************************************************************
void CBCGPTreeMapGroup::SetRect(const CBCGPRect& rectIn)
{
	CBCGPRect rect = rectIn;

	if (m_sizeMargin != CBCGPSize(-1., -1.))
	{
		rect.DeflateRect(m_sizeMargin);
	}
	else
	{
		for (CBCGPBaseTreeMapNode* pParent = m_pParent; pParent != NULL; pParent = pParent->m_pParent)
		{
			ASSERT_VALID(pParent);

			if (pParent->m_sizeMargin != CBCGPSize(-1., -1.))
			{
				rect.DeflateRect(pParent->m_sizeMargin);
				break;
			}
		}
	}

	m_rect = rect;
}
//*******************************************************************************
BOOL CBCGPLinearGaugeImpl::OnSetMouseCursor(const CBCGPPoint& pt)
{
	if (m_bIsInteractiveMode)
	{
		CBCGPRect rect = m_rect;
		rect.DeflateRect(m_nFrameSize, m_nFrameSize);

		if (rect.PtInRect(pt))
		{
			::SetCursor (globalData.GetHandCursor());
			return TRUE;
		}
	}

	return CBCGPGaugeImpl::OnSetMouseCursor(pt);
}
//*******************************************************************************
void CBCGPChartObject::OnDrawText(CBCGPGraphicsManager* pGM, const CBCGPRect& /*rectDiagram*/)
{
	ASSERT_VALID(this);

	if (m_strText.IsEmpty() || m_rectScreen.IsRectEmpty())
	{
		return;
	}

	CBCGPRect rectShape = m_rectScreen;
	rectShape.DeflateRect(m_format.GetContentPadding(TRUE));

	const CBCGPBrush& brText = m_format.m_brTextColor.IsEmpty() ? 
		m_pParentChart->GetColors().m_brChartObjectTextColor : m_format.m_brTextColor;

	pGM->DrawText(m_strText, rectShape, m_format.m_textFormat, brText);
}
//***************************************************************************************
void CBCGPRadialMenuObject::OnDraw(CBCGPGraphicsManager* pGM, const CBCGPRect& /*rectClip*/, DWORD dwFlags)
{
	if (dwFlags == BCGP_DRAW_STATIC)
	{
		return;
	}

	m_nShadowDepth = pGM->IsSupported(BCGP_GRAPHICS_MANAGER_COLOR_OPACITY) ? GetShadowDepth() : 0;

	CBCGPRect rect = m_rect;
	if (rect.Width() < rect.Height())
	{
		rect.top += (rect.Height() - rect.Width()) / 2;
		rect.bottom = rect.top + rect.Width();
	}
	else if (rect.Height() < rect.Width())
	{
		rect.left += (rect.Width() - rect.Height()) / 2;
		rect.right = rect.left + rect.Height();
	}

	rect.DeflateRect(2., 2.);

	rect.right -= m_nShadowDepth;
	rect.bottom -= m_nShadowDepth;

	const double radius = rect.Width() / 2;
	const double radiusSmall = INTERNAL_PART * rect.Width() + 1.0;
	const CBCGPPoint center = rect.CenterPoint();

	CBCGPSize sizeIcon((double)m_cxIcon, 16);

	if (!m_Icons.IsNull())
	{
		sizeIcon.cy = pGM->GetImageSize(m_Icons).cy;
	}

	const int nItems = (int)m_arItems.GetSize();

	if (IsDirty())
	{
		int nCircleItems = m_bHasCenterButton ? nItems - 1 : nItems;

		double dblDeltaAngle = nCircleItems == 0 ? 0. : 360. / nCircleItems;
		double dblStartAngle = 90. - dblDeltaAngle / 2;

		for (int i = 0; i < nItems; i++)
		{
			CBCGPRadialMenuItem* pItem = m_arItems[i];
			ASSERT_VALID(pItem);

			pItem->m_bIsCenter = i == nItems -1 && m_bHasCenterButton;

			pItem->m_Shape.Destroy();
			pItem->m_Shape.Clear();

			if (!pItem->m_bIsCenter)
			{
				double dblFinishAngle = dblStartAngle + dblDeltaAngle;

				const double dblStartAngleRad = bcg_deg2rad(dblStartAngle);
				const double dblFinishAngleRad = bcg_deg2rad(dblFinishAngle);
				const double dblMiddleAngleRad = bcg_deg2rad(dblStartAngle + dblDeltaAngle / 2);

				double angleStartCos = cos(dblStartAngleRad);
				double angleStartSin = sin(dblStartAngleRad);
				double angleFinishCos = cos(dblFinishAngleRad);
				double angleFinishSin = sin(dblFinishAngleRad);

				pItem->m_Shape.SetStart(
					CBCGPPoint(center.x + angleStartCos * radius, center.y - angleStartSin * radius));
				pItem->m_Shape.AddArc(
					CBCGPPoint(center.x + angleFinishCos * radius, center.y - angleFinishSin * radius),
					CBCGPSize(radius, radius), dblStartAngle > dblFinishAngle, FALSE);
				pItem->m_Shape.AddLine(
					CBCGPPoint(center.x + angleFinishCos * radiusSmall, center.y - angleFinishSin * radiusSmall));
				pItem->m_Shape.AddArc(
					CBCGPPoint(center.x + angleStartCos * radiusSmall, center.y - angleStartSin * radiusSmall),
					CBCGPSize(radiusSmall, radiusSmall), dblStartAngle < dblFinishAngle, FALSE);

				pItem->m_ptCenter = CBCGPPoint(
					center.x + cos(dblMiddleAngleRad) * 2 * radius / 3,
					center.y - sin(dblMiddleAngleRad) * 2 * radius / 3);

				dblStartAngle = dblFinishAngle;
			}
			else
			{
				pItem->m_Shape.SetStart(center);
				pItem->m_Shape.AddLine(center);
				pGM->CombineGeometry(pItem->m_Shape, pItem->m_Shape, CBCGPEllipseGeometry(CBCGPEllipse(center, radiusSmall, radiusSmall)), RGN_OR);

				pItem->m_ptCenter = center;
			}
		}
	}

	CBCGPEllipse ellipseInt(center, radiusSmall, radiusSmall);

	CBCGPRect rectShadow = rect;
	rectShadow.OffsetRect(m_nShadowDepth, m_nShadowDepth);

	if (!m_bHasCenterButton && m_pCtrl->GetSafeHwnd() != NULL && (m_pCtrl->GetExStyle() & WS_EX_LAYERED))
	{
		if (m_nShadowDepth > 0)
		{
			CBCGPEllipseGeometry egShadow(rectShadow);

			CBCGPPoint centerShadow = center;
			centerShadow.x += m_nShadowDepth;
			centerShadow.y += m_nShadowDepth;

			CBCGPEllipse ellipseIntShadow(centerShadow, radiusSmall, radiusSmall);
			CBCGPEllipseGeometry egInternalShadow(ellipseIntShadow);

			CBCGPComplexGeometry shapeShadow;
			pGM->CombineGeometry(shapeShadow, egShadow, egInternalShadow, RGN_DIFF);

			pGM->FillGeometry(shapeShadow, m_brShadow);
		}

		CBCGPEllipseGeometry eg(rect);
		CBCGPEllipseGeometry egInternal(ellipseInt);

		CBCGPComplexGeometry shape;
		pGM->CombineGeometry(shape, eg, egInternal, RGN_DIFF);

		pGM->FillGeometry(shape, m_brFill);

	}
	else
	{
		if (m_nShadowDepth > 0)
		{
			pGM->FillEllipse(rectShadow, m_brShadow);
		}

		pGM->FillEllipse(rect, m_brFill);
	}

	pGM->DrawEllipse(rect, m_brBorder);

	if (!pGM->IsSupported(BCGP_GRAPHICS_MANAGER_COLOR_OPACITY))
	{
		CBCGPRect rect1 = rect;
		rect1.DeflateRect(1, 1);

		pGM->DrawEllipse(rect1, m_brFill);
	}

	BOOL bIsCtrlDisabled = m_pCtrl->GetSafeHwnd() != NULL && !m_pCtrl->IsWindowEnabled();

	for (int i = 0; i < nItems; i++)
	{
		CBCGPRadialMenuItem* pItem = m_arItems[i];
		ASSERT_VALID(pItem);

		if (i == m_nHighlighted)
		{
			pGM->FillGeometry(pItem->m_Shape, m_nHighlighted == m_nPressed ? m_brPressed : 
				m_brHighlighted.IsEmpty() ? m_brFill : m_brHighlighted);
		}

		pItem->OnDrawIcon(pGM, bIsCtrlDisabled, m_Icons, sizeIcon);

		pGM->DrawGeometry(pItem->m_Shape, m_brBorder);
	}

	pGM->DrawEllipse(ellipseInt, m_brBorder);

	if (!pGM->IsSupported(BCGP_GRAPHICS_MANAGER_ANTIALIAS))
	{
		rect.InflateRect(1, 1);
		pGM->DrawEllipse(rect, m_brBorder);
	}

	if (m_pCtrl->GetSafeHwnd() != NULL && m_pCtrl->IsFocused() && !m_pCtrl->IsPopup())
	{
		rect.InflateRect(1, 1);
		pGM->DrawEllipse(rect, m_brFocusedBorder);
	}
}
//*******************************************************************************
void CBCGPLinearGaugeImpl::OnDraw(CBCGPGraphicsManager* pGMSrc, const CBCGPRect& /*rectClip*/, DWORD dwFlags/* = BCGP_DRAW_STATIC | BCGP_DRAW_DYNAMIC*/)
{
	ASSERT_VALID(this);
	ASSERT_VALID(pGMSrc);

	if (m_rect.IsRectEmpty() || !m_bIsVisible)
	{
		return;
	}

	BOOL bCacheImage = m_bCacheImage;

	if (pGMSrc->IsOffscreen())
	{
		bCacheImage = FALSE;
	}

	CBCGPGraphicsManager* pGM = pGMSrc;
	CBCGPGraphicsManager* pGMMem = NULL;

	CBCGPRect rectSaved;

	if (bCacheImage)
	{	
		if (m_ImageCache.GetHandle() == NULL)
		{
			SetDirty();
		}

		if (m_ImageCache.GetHandle() != NULL && !IsDirty() && (dwFlags & BCGP_DRAW_STATIC))
		{
			pGMSrc->DrawImage(m_ImageCache, m_rect.TopLeft());
			dwFlags &= ~BCGP_DRAW_STATIC;

			if (dwFlags == 0)
			{
				return;
			}
		}

		if (dwFlags & BCGP_DRAW_STATIC)
		{
			pGMMem = pGM->CreateOffScreenManager(m_rect, &m_ImageCache);

			if (pGMMem != NULL)
			{
				pGM = pGMMem;

				rectSaved = m_rect;
				m_rect = m_rect - m_rect.TopLeft();
			}
		}
	}

	if (IsDirty())
	{
		int i = 0;

		for (i = 0; i < m_arScales.GetSize(); i++)
		{
			CBCGPGaugeScaleObject* pScale = m_arScales[i];
			ASSERT_VALID(pScale);

			pScale->CleanUp();
		}

		SetDirty(FALSE);
	}

	CBCGPRect rect = m_rect;
	rect.DeflateRect(1., 1.);

	const double scaleRatio = GetScaleRatioMid();
	const double nFrameSize = m_nFrameSize * scaleRatio;

	if (dwFlags & BCGP_DRAW_STATIC)
	{
		const CBCGPBrush& brFill = m_nFrameSize <= 2 ? m_Colors.m_brFill : m_Colors.m_brFrameFill;

		pGM->FillRectangle(rect, brFill);
		pGM->DrawRectangle(rect, m_Colors.m_brFrameOutline, scaleRatio);

		if (scaleRatio == 1.0 && !pGM->IsSupported(BCGP_GRAPHICS_MANAGER_ANTIALIAS))
		{
			CBCGPRect rect1 = rect;
			rect1.DeflateRect(1, 1);

			pGM->DrawRectangle(rect1, m_Colors.m_brFrameOutline);
		}

		if (m_nFrameSize > 2)
		{
			CBCGPRect rectInternal = rect;
			rectInternal.DeflateRect(nFrameSize, nFrameSize);

			pGM->FillRectangle(rectInternal, m_Colors.m_brFill);
			pGM->DrawRectangle(rectInternal, m_Colors.m_brFrameOutline, scaleRatio);
		}

		m_sizeMaxLabel = GetTextLabelMaxSize(pGM);

		int i = 0;

		m_dblMaxRangeSize = 0.;

		// Draw colored ranges:
		for (i = 0; i < m_arRanges.GetSize(); i++)
		{
			CBCGPGaugeColoredRangeObject* pRange = m_arRanges[i];
			ASSERT_VALID(pRange);

			CBCGPRect rectRange;
			CBCGPPolygonGeometry shapeRange;

			if (GetRangeShape(rectRange, shapeRange, 
				pRange->m_dblStartValue, pRange->m_dblFinishValue, 
				pRange->m_dblStartWidth, pRange->m_dblFinishWidth,
				pRange->m_dblOffsetFromFrame, pRange->m_nScale))
			{
				if (!rectRange.IsRectEmpty())
				{
					pGM->FillRectangle(rectRange, pRange->m_brFill);
					pGM->DrawRectangle(rectRange, pRange->m_brOutline, scaleRatio);
				}
				else
				{
					pGM->FillGeometry(shapeRange, pRange->m_brFill);
					pGM->DrawGeometry(shapeRange, pRange->m_brOutline, scaleRatio);
				}

				m_dblMaxRangeSize = max(m_dblMaxRangeSize, max(pRange->m_dblStartWidth, pRange->m_dblFinishWidth) * scaleRatio);
			}
		}

		// Draw scales:
		for (i = 0; i < m_arScales.GetSize(); i++)
		{
			OnDrawScale(pGM, i);
		}
	}

	if (pGMMem != NULL)
	{
		delete pGMMem;
		pGM = pGMSrc;

		m_rect = rectSaved;

		pGMSrc->DrawImage(m_ImageCache, m_rect.TopLeft());
	}

	if (dwFlags & BCGP_DRAW_DYNAMIC)
	{
		CBCGPRect rectSaved = m_rect;
		m_rect.OffsetRect(-m_ptScrollOffset);

		int i = 0;

		for (i = 0; i < m_arData.GetSize(); i++)
		{
			CBCGPPointsArray pts;
			CBCGPPointsArray ptsShadow;

			CreatePointerPoints(pts, i, FALSE);

			if (pGM->IsSupported(BCGP_GRAPHICS_MANAGER_COLOR_OPACITY))
			{
				CreatePointerPoints(ptsShadow, i, TRUE);
			}

			OnDrawPointer(pGM, pts, ptsShadow, i);
		}

		m_rect = rectSaved;
	}
}