// XTPMarkupFrameworkElement.cpp: implementation of the CXTPMarkupFrameworkElement class. // // This file is a part of the XTREME TOOLKIT PRO MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "XTPMarkupObject.h" #include "XTPMarkupInputElement.h" #include "XTPMarkupUIElement.h" #include "XTPMarkupFrameworkElement.h" #include "XTPMarkupBuilder.h" #include "XTPMarkupResourceDictionary.h" #include "XTPMarkupThickness.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////////// // CXTPMarkupFrameworkElement CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pMarginProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pHorizontalAlignmentProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pVerticalAlignmentProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pWidthProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pHeightProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pMinWidthProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pMinHeightProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pMaxWidthProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pMaxHeightProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupFrameworkElement::m_pTagProperty = NULL; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// IMPLEMENT_MARKUPCLASS(L"FrameworkElement", CXTPMarkupFrameworkElement, CXTPMarkupUIElement) void CXTPMarkupFrameworkElement::RegisterMarkupClass() { CXTPMarkupStyle::RegisterType(); m_pMarginProperty = CXTPMarkupDependencyProperty::Register(L"Margin", MARKUP_TYPE(CXTPMarkupThickness), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(CXTPMarkupThickness::CreateValue(), CXTPMarkupPropertyMetadata::flagAffectsMeasure)); m_pHorizontalAlignmentProperty = CXTPMarkupDependencyProperty::Register(L"HorizontalAlignment", MARKUP_TYPE(CXTPMarkupEnum), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertHorizontalAlignment, CXTPMarkupPropertyMetadata::flagAffectsArrange)); m_pVerticalAlignmentProperty = CXTPMarkupDependencyProperty::Register(L"VerticalAlignment", MARKUP_TYPE(CXTPMarkupEnum), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertVerticalAlignment, CXTPMarkupPropertyMetadata::flagAffectsArrange)); m_pWidthProperty = CXTPMarkupDependencyProperty::Register(L"Width", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertLength, CXTPMarkupPropertyMetadata::flagAffectsMeasure)); m_pHeightProperty = CXTPMarkupDependencyProperty::Register(L"Height", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertLength, CXTPMarkupPropertyMetadata::flagAffectsMeasure)); m_pMinWidthProperty = CXTPMarkupDependencyProperty::Register(L"MinWidth", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertLength, CXTPMarkupPropertyMetadata::flagAffectsMeasure)); m_pMinHeightProperty = CXTPMarkupDependencyProperty::Register(L"MinHeight", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertLength, CXTPMarkupPropertyMetadata::flagAffectsMeasure)); m_pMaxWidthProperty = CXTPMarkupDependencyProperty::Register(L"MaxWidth", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertLength, CXTPMarkupPropertyMetadata::flagAffectsMeasure)); m_pMaxHeightProperty = CXTPMarkupDependencyProperty::Register(L"MaxHeight", MARKUP_TYPE(CXTPMarkupInt), MARKUP_TYPE(CXTPMarkupFrameworkElement), new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertLength, CXTPMarkupPropertyMetadata::flagAffectsMeasure)); m_pTagProperty = CXTPMarkupDependencyProperty::Register(L"Tag", MARKUP_TYPE(CXTPMarkupObject), MARKUP_TYPE(CXTPMarkupFrameworkElement)); } CXTPMarkupFrameworkElement::CXTPMarkupFrameworkElement() { m_bNeedsClipBounds = FALSE; m_bUnclippedDesiredSize = FALSE; m_szUnclippedDesiredSize = CSize(0, 0); } CXTPMarkupFrameworkElement::~CXTPMarkupFrameworkElement() { } CXTPMarkupFrameworkElement::MINMAX::MINMAX() { nMaxHeight = nMaxWidth = INT_MAX; nMinWidth = nMinHeight = 0; } AFX_INLINE int InlineMin(int a, int b) { return a < b ? (a) : (b); } AFX_INLINE int InlineMax(int a, int b) { return a > b ? (a) : (b); } void CXTPMarkupFrameworkElement::MINMAX::Update(const CXTPMarkupFrameworkElement* pElement) { CXTPMarkupInt* pHeight = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(CXTPMarkupFrameworkElement::m_pHeightProperty)); CXTPMarkupInt* pMinHeight = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(CXTPMarkupFrameworkElement::m_pMinHeightProperty)); CXTPMarkupInt* pMaxHeight = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(CXTPMarkupFrameworkElement::m_pMaxHeightProperty)); CXTPMarkupInt* pWidth = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(CXTPMarkupFrameworkElement::m_pWidthProperty)); CXTPMarkupInt* pMinWidth = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(CXTPMarkupFrameworkElement::m_pMinWidthProperty)); CXTPMarkupInt* pMaxWidth = MARKUP_STATICCAST(CXTPMarkupInt, pElement->GetValue(CXTPMarkupFrameworkElement::m_pMaxWidthProperty)); if (pHeight && (int)*pHeight== INT_MAX) pHeight = NULL; // for Auto case if (pWidth && (int)*pWidth== INT_MAX) pWidth = NULL; nMaxHeight = InlineMax(InlineMin(pHeight ? (int)*pHeight : INT_MAX, pMaxHeight ? (int)*pMaxHeight : INT_MAX), pMinHeight ? (int)*pMinHeight : 0); nMinHeight = InlineMax(InlineMin(nMaxHeight, pHeight ? (int)*pHeight : 0), pMinHeight ? (int)*pMinHeight : 0); nMaxWidth = InlineMax(InlineMin(pWidth ? (int)*pWidth : INT_MAX, pMaxWidth ? (int)*pMaxWidth : INT_MAX), pMinWidth ? (int)*pMinWidth : 0); nMinWidth = InlineMax(InlineMin(nMaxWidth, pWidth ? (int)*pWidth : 0), pMinWidth ? (int)*pMinWidth : 0); } inline int SafeSum(int a, int b) { if (a > INT_MAX / 2 || b > INT_MAX / 2) return INT_MAX; return a + b; } CSize CXTPMarkupFrameworkElement::MeasureCore(CXTPMarkupDrawingContext* pDC, CSize szAvailableSize) { CXTPMarkupThickness* pMargin = GetMargin(); long num = pMargin->GetLeft() + pMargin->GetRight(); long num2 = pMargin->GetTop() + pMargin->GetBottom(); CSize transformSpaceBounds = CSize(max(SafeSum(szAvailableSize.cx, -num), 0), max(SafeSum(szAvailableSize.cy, -num2), 0)); m_mmBounds.Update(this); transformSpaceBounds.cx = max(m_mmBounds.nMinWidth, min(transformSpaceBounds.cx, m_mmBounds.nMaxWidth)); transformSpaceBounds.cy = max(m_mmBounds.nMinHeight, min(transformSpaceBounds.cy, m_mmBounds.nMaxHeight)); CSize size2 = MeasureOverride(pDC, transformSpaceBounds); size2 = CSize(max(size2.cx, m_mmBounds.nMinWidth), max(size2.cy, m_mmBounds.nMinHeight)); CSize size = size2; BOOL fClip = FALSE; if (size2.cx > m_mmBounds.nMaxWidth) { size2.cx = m_mmBounds.nMaxWidth; fClip = TRUE; } if (size2.cy > m_mmBounds.nMaxHeight) { size2.cy = m_mmBounds.nMaxHeight; fClip = TRUE; } long width = size2.cx + num; long height = size2.cy + num2; if (width > szAvailableSize.cx) { width = szAvailableSize.cx; fClip = TRUE; } if (height > szAvailableSize.cy) { height = szAvailableSize.cy; fClip = TRUE; } m_bNeedsClipBounds = FALSE; m_bUnclippedDesiredSize = FALSE; if ((fClip || (width < 0)) || (height < 0)) { m_bNeedsClipBounds = TRUE; m_bUnclippedDesiredSize = TRUE; m_szUnclippedDesiredSize = size; } return CSize(max(0, width), max(0, height)); } BOOL CXTPMarkupFrameworkElement::GetClipToBounds() const { CXTPMarkupBool* pClipToBounds = MARKUP_STATICCAST(CXTPMarkupBool, GetValue(m_pClipToBoundsProperty)); return pClipToBounds && (BOOL)*pClipToBounds; } BOOL CXTPMarkupFrameworkElement::GetLayoutClip(CRect& rc) const { if (CXTPMarkupUIElement::GetLayoutClip(rc)) return TRUE; BOOL bClipToBounds = GetClipToBounds(); if (!bClipToBounds && !m_bNeedsClipBounds) return FALSE; CSize szRenderSize = m_szRenderSize; int num = m_mmBounds.nMaxWidth == INT_MAX ? szRenderSize.cx : m_mmBounds.nMaxWidth; int num2 = m_mmBounds.nMaxHeight == INT_MAX ? szRenderSize.cy : m_mmBounds.nMaxHeight; BOOL bFlag = bClipToBounds ||num < szRenderSize.cx || num2 < szRenderSize.cy; szRenderSize = CSize(min(szRenderSize.cx, m_mmBounds.nMaxWidth), min(szRenderSize.cy, m_mmBounds.nMaxHeight)); CXTPMarkupThickness* pMargin = GetMargin(); long num3 = pMargin->GetLeft() + pMargin->GetRight(); long num4 = pMargin->GetTop() + pMargin->GetBottom(); CSize szClientSize = CSize(max(m_rcFinalRect.Width() - num3, 0), max(m_rcFinalRect.Height() - num4, 0)); BOOL bFlag2 = bClipToBounds || szClientSize.cx < szRenderSize.cx || szClientSize.cy < szRenderSize.cy; if (bFlag && !bFlag2) { rc = CRect(0, 0, num, num2); return TRUE; } if (!bFlag && !bFlag2) return FALSE; CPoint offset = ComputeAlignmentOffset(szClientSize, szRenderSize); rc = CRect(-offset, szClientSize); if (bFlag) { rc.IntersectRect(rc, CRect(0, 0, num, num2)); } return TRUE; } CSize CXTPMarkupFrameworkElement::MeasureOverride(CXTPMarkupDrawingContext* /*pDC*/, CSize /*szAvailableSize*/) { return CSize(0, 0); } XTPMarkupHorizontalAlignment CXTPMarkupFrameworkElement::GetHorizontalAlignment() const { CXTPMarkupEnum* pAlign = MARKUP_STATICCAST(CXTPMarkupEnum, GetValue(m_pHorizontalAlignmentProperty)); return pAlign ? (XTPMarkupHorizontalAlignment)(int)(*pAlign) : xtpMarkupHorizontalAlignmentStretch; } XTPMarkupVerticalAlignment CXTPMarkupFrameworkElement::GetVerticalAlignment() const { CXTPMarkupEnum* pAlign = MARKUP_STATICCAST(CXTPMarkupEnum, GetValue(m_pVerticalAlignmentProperty)); return pAlign ? (XTPMarkupVerticalAlignment)(int)(*pAlign) : xtpMarkupVerticalAlignmentStretch; } void CXTPMarkupFrameworkElement::ArrangeCore(CRect rcFinalRect) { CSize size = rcFinalRect.Size(); CXTPMarkupThickness* pMargin = GetMargin(); long num = pMargin->GetLeft() + pMargin->GetRight(); long num2 = pMargin->GetTop() + pMargin->GetBottom(); size.cx = max(0, (size.cx - num)); size.cy = max(0, (size.cy - num2)); CSize untransformedDS(0, 0); if (!m_bUnclippedDesiredSize) { untransformedDS = CSize(m_szDesiredSize.cx - num, m_szDesiredSize.cy - num2); } else { untransformedDS = m_szUnclippedDesiredSize; } if (size.cx < untransformedDS.cx) { m_bNeedsClipBounds = TRUE; size.cx = untransformedDS.cx; } if (size.cy < untransformedDS.cy) { m_bNeedsClipBounds = TRUE; size.cy = untransformedDS.cy; } if (GetHorizontalAlignment() != xtpMarkupHorizontalAlignmentStretch) { size.cx = untransformedDS.cx; } if (GetVerticalAlignment() != xtpMarkupVerticalAlignmentStretch) { size.cy = untransformedDS.cy; } long num3 = max(untransformedDS.cx, m_mmBounds.nMaxWidth); if (num3 < size.cx) { m_bNeedsClipBounds = TRUE; size.cx = num3; } long num4 = max(untransformedDS.cy, m_mmBounds.nMaxHeight); if (num4 < size.cy) { m_bNeedsClipBounds = TRUE; size.cy = num4; } CSize size7 = ArrangeOverride(size); m_szRenderSize = size7; CSize inkSize = CSize(min(size7.cx, m_mmBounds.nMaxWidth), min(size7.cy, m_mmBounds.nMaxHeight)); if (inkSize.cx < size7.cx || inkSize.cy < size7.cy) { m_bNeedsClipBounds = TRUE; } CSize clientSize = CSize(max(0, rcFinalRect.Width() - num), max(0, rcFinalRect.Height() - num2)); if (clientSize.cx < inkSize.cx || clientSize.cy < inkSize.cy) { m_bNeedsClipBounds = TRUE; } CPoint offset = ComputeAlignmentOffset(clientSize, inkSize); offset.x += rcFinalRect.left + pMargin->GetLeft(); offset.y += rcFinalRect.top + pMargin->GetTop(); m_ptVisualOffset = offset; } CPoint CXTPMarkupFrameworkElement::ComputeAlignmentOffset(CSize clientSize, CSize inkSize) const { CPoint vector(0, 0); XTPMarkupHorizontalAlignment horizontalAlignment = GetHorizontalAlignment(); XTPMarkupVerticalAlignment verticalAlignment = GetVerticalAlignment(); if ((horizontalAlignment == xtpMarkupHorizontalAlignmentStretch) && (inkSize.cx > clientSize.cx)) { horizontalAlignment = xtpMarkupHorizontalAlignmentLeft; } if ((verticalAlignment == xtpMarkupVerticalAlignmentStretch) && (inkSize.cy > clientSize.cy)) { verticalAlignment = xtpMarkupVerticalAlignmentTop; } switch (horizontalAlignment) { case xtpMarkupHorizontalAlignmentCenter: case xtpMarkupHorizontalAlignmentStretch: vector.x = (clientSize.cx - inkSize.cx) / 2; break; default: if (horizontalAlignment == xtpMarkupHorizontalAlignmentRight) { vector.x = clientSize.cx - inkSize.cx; } else { vector.x = 0; } break; } switch (verticalAlignment) { case xtpMarkupVerticalAlignmentCenter: case xtpMarkupVerticalAlignmentStretch: vector.y = (clientSize.cy - inkSize.cy) / 2; return vector; case xtpMarkupVerticalAlignmentBottom: vector.y = clientSize.cy - inkSize.cy; return vector; } vector.y = 0; return vector; } CSize CXTPMarkupFrameworkElement::ArrangeOverride(CSize szFinalSize) { return szFinalSize; } void CXTPMarkupFrameworkElement::OnPropertyChanged(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pOldValue, CXTPMarkupObject* pNewValue) { CXTPMarkupUIElement::OnPropertyChanged(pProperty, pOldValue, pNewValue); FireTriggers(pProperty, pNewValue); if (pProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagAffectsMeasure) { InvalidateMeasure(); } if (pProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagAffectsArrange) { InvalidateArrange(); } if (pProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagAffectsRender) { InvalidateVisual(); } } void CXTPMarkupFrameworkElement::SetMargin(int nLeft, int nTop, int nRight, int nBottom) { SetValue(m_pMarginProperty, new CXTPMarkupThickness(nLeft, nTop, nRight, nBottom)); } void CXTPMarkupFrameworkElement::SetMargin(int nMargin) { SetValue(m_pMarginProperty, new CXTPMarkupThickness(nMargin)); } CXTPMarkupThickness* CXTPMarkupFrameworkElement::GetMargin() const { return MARKUP_STATICCAST(CXTPMarkupThickness, GetValue(m_pMarginProperty)); }