void DisplayElement::GetBounds (WebRect *rect)
{
	if (mFlags & DISPLAY_FLAG_BOUNDS_VALID)
	{
		*rect = mBounds;
		return;
	}

	*rect = mRect;

	WebRect childRect;
	DisplayElement *pChild = mpFirstChild;

	while (pChild)
	{
		if (!(pChild->mFlags & DISPLAY_FLAG_FIXED_POS))
		{
			pChild->GetBounds(&childRect);
			childRect.Shift(mRect.left, mRect.top);
			rect->Or(&childRect);
		}

		pChild = pChild->mpNext;
	}

	SetFlag(DISPLAY_FLAG_BOUNDS_VALID);
	mBounds = *rect;
}
void DisplayElement::InvalidateChild (DisplayElement *pChild, WebRect *pDirty)
{
	WebRect dirty;
	dirty.Set(pDirty);
	dirty.Shift(mRect.left, mRect.top);

	if (GetOverflow() == DISPLAY_OVERFLOW_HIDDEN)
	{
		WebRect clipRect;
		GetClipRect(&clipRect);

		// If completely outside clipping rect, stop here
		if (!dirty.Overlaps(&clipRect))
		{
			return;
		}

		// clip pDirty to our rect
		dirty.And(&clipRect);
	}

	if ((mFlags & DISPLAY_FLAG_FIXED_POS) || !mpParent)
	{
		DisplayManager *pManager = GetManager();
		if (pManager)
		{
			if (mFlags & DISPLAY_FLAG_FIXED_POS)
			{
				dirty.Shift(pManager->mViewRect.left, pManager->mViewRect.top);
			}

			pManager->InvalidateViewportRegion(&dirty);
		}
	}
	else
	{
		mpParent->InvalidateChild(this, &dirty);
	}
 }
Exemple #3
0
/*---------------------------------------------------------------------------*/
template<class T> IPositionedFormatContext* HTMLElementDisplay<T>::FormatSelfPositioned (
		DisplayElement* displayParent,
		IPositionedFormatContext* rootContext,
		IPositionedFormatContext* parentContext,
		FormatContextFactory* childContextFactory,
		WEBC_BOOL generateChildContext
	)
{
	WebRect rect;
	WEBC_UINT16 position = GetPosition();
	IPositionedFormatContext* childContext = 0;

	if (position == TU_POSITION_RELATIVE)
	{
		if (generateChildContext)
		{
			const WebRect * tmpRect = 	&(((DisplayElement *)(this))->mRect);
			rect.Set(tmpRect);
			rect.MoveTo(0,0);

			CSSLength height;
			GetCSSLength(&height, CSS_PROPERTY_HEIGHT);

			childContext = childContextFactory->newPositioned (
					&rect,
					(height.type == CSS_LENGTH_UNIT_AUTO) ||
					(height.type == CSS_LENGTH_UNIT_PERCENT && parentContext->parentHeightIsAuto()), // parent height is auto
					TU_DIR_LTR,
					0, // border-left-width
					0, // border-top-width
					0, // border-right-width
					0, // border-bottom-width
					0, // autoIndentLeft
					0, // autoIndentTop
					0  // autoIndentRight
				);
		}
	}
	else
	{
		WebRect containingBlock;
		IPositionedFormatContext* containingContext;
		DISPLAY_INT borderLeftValue;
		DISPLAY_INT borderTopValue;
		DISPLAY_INT borderRightValue;
		DISPLAY_INT borderBottomValue;

		if (displayParent)
		{
			if (displayParent != T::mpParent)
			{
				mHtmlElementDisplayFlags &= ~HELEM_DISPLAY_FLAG_STYLE_SET;
			}
			displayParent->InsertOrdered(this);
		}

		if (position == TU_POSITION_FIXED)
		{
			T::SetFixedPosition(WEBC_TRUE);
			containingContext = rootContext;
		}
		else
		{
			T::SetFixedPosition(WEBC_FALSE);
			containingContext = parentContext;
		}

		containingContext->getContainingBlock(&containingBlock);

		WEBC_BOOL   parentHeightIsAuto = containingContext->parentHeightIsAuto();
		int         textDirection      = containingContext->getTextDirection();
		DISPLAY_INT parentBorderLeft   = containingContext->getParentBorderLeft();
		DISPLAY_INT parentBorderTop    = containingContext->getParentBorderTop();
		DISPLAY_INT parentBorderRight  = containingContext->getParentBorderRight();
		DISPLAY_INT parentBorderBottom = containingContext->getParentBorderBottom();

		DISPLAY_INT autoIndentLeft     = parentContext->getAutoIndentLeft();
		DISPLAY_INT autoIndentTop      = parentContext->getAutoIndentTop();
		DISPLAY_INT autoIndentRight    = parentContext->getAutoIndentRight();

		if (position == TU_POSITION_FIXED)
		{
			WebRect parentRect;

			parentContext->getContainingBlock(&parentRect);

			autoIndentLeft  += parentRect.left;
			autoIndentTop   += parentRect.top;
			autoIndentRight += (containingBlock.right - parentRect.right);
		}

		DISPLAY_INT parentWidth = containingBlock.Width() - (parentBorderLeft + parentBorderRight);
		DISPLAY_INT parentHeight = containingBlock.Height() - (parentBorderTop + parentBorderBottom);

		WebFont font = mpHtmlElement->GetWebFont();
		DISPLAY_INT emHeight = font? WEB_FONT_HEIGHT(font) : WEBC_CFG_DEFAULT_TEXT_HEIGHT;
		DISPLAY_INT exHeight = emHeight >> 1;

		// First find the left edge and width

		CSSLength left;
		CSSLength right;
		CSSLength width;

		// Find value for left, right, width, marginLeft, marginRight

		GetCSSLength(&left,  CSS_PROPERTY_LEFT);
		GetCSSLength(&right, CSS_PROPERTY_RIGHT);
		GetCSSLength(&width, CSS_PROPERTY_WIDTH);

		DISPLAY_INT leftValue;
		DISPLAY_INT rightValue;
		DISPLAY_INT widthValue;
		DISPLAY_INT marginLeftValue;
		DISPLAY_INT paddingLeftValue;
		DISPLAY_INT paddingTopValue;
		DISPLAY_INT paddingRightValue;
		DISPLAY_INT paddingBottomValue;

		// Find value for padding and border

		paddingLeftValue   = GetPixelLength(CSS_PROPERTY_PADDING_LEFT,   parentWidth, emHeight, exHeight, 0);
		paddingTopValue    = GetPixelLength(CSS_PROPERTY_PADDING_TOP,    parentWidth, emHeight, exHeight, 0);
		paddingRightValue  = GetPixelLength(CSS_PROPERTY_PADDING_RIGHT,  parentWidth, emHeight, exHeight, 0);
		paddingBottomValue = GetPixelLength(CSS_PROPERTY_PADDING_BOTTOM, parentWidth, emHeight, exHeight, 0);

		borderLeftValue    = GetBorderWidth(CSS_LEFT,   parentWidth, emHeight, exHeight, parentBorderLeft);
		borderTopValue     = GetBorderWidth(CSS_TOP,    parentWidth, emHeight, exHeight, parentBorderTop);
		borderRightValue   = GetBorderWidth(CSS_RIGHT,  parentWidth, emHeight, exHeight, parentBorderRight);
		borderBottomValue  = GetBorderWidth(CSS_BOTTOM, parentWidth, emHeight, exHeight, parentBorderBottom);

		CSSLength height;
		CSSLength top;
		CSSLength bottom;
		DISPLAY_INT heightValue=0;
		WEBC_BOOL heightIsAuto=0;

		GetCSSLength(&height, CSS_PROPERTY_HEIGHT);
		GetCSSLength(&top, CSS_PROPERTY_TOP);

#define NOTHING_KNOWN 0
#define HEIGHT_KNOWN  1
#define TOP_KNOWN     2
#define BOTTOM_KNOWN  4

		WEBC_UINT8 verticalCase;

		verticalCase =  (height.type == CSS_LENGTH_UNIT_AUTO ||
		                 (height.type == CSS_LENGTH_UNIT_PERCENT && parentHeightIsAuto))? 0 : HEIGHT_KNOWN;
		verticalCase |= (top.type == CSS_LENGTH_UNIT_AUTO)? 0 : TOP_KNOWN;

		if (verticalCase != (HEIGHT_KNOWN|TOP_KNOWN))
		{
			GetCSSLength(&bottom, CSS_PROPERTY_BOTTOM);
			verticalCase |= (bottom.type == CSS_LENGTH_UNIT_AUTO || parentHeightIsAuto)? 0 : BOTTOM_KNOWN;
		}

		DISPLAY_INT topValue = 0;
		DISPLAY_INT bottomValue = 0;
		DISPLAY_INT marginTopValue = 0;
		DISPLAY_INT marginBottomValue = 0;

		switch (verticalCase)
		{
			case NOTHING_KNOWN:
				// top = auto indent top
				// height = content height
				topValue = autoIndentTop;
				heightValue = 0;
				heightIsAuto = WEBC_TRUE;
				marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0);
				break;

			case HEIGHT_KNOWN:
				// top = auto indent top
				// height = height
				topValue = autoIndentTop;
				heightValue = CSS_LengthToPixels(&height, parentHeight, emHeight, exHeight);
				heightIsAuto = WEBC_FALSE;
				marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0);
				break;

			case TOP_KNOWN:
				// top = top
				// height = content height
				if (top.type == CSS_LENGTH_UNIT_PERCENT && parentHeightIsAuto)
				{
					topValue = autoIndentTop;
				}
				else
				{
					topValue = CSS_LengthToPixels(&top, parentHeight, emHeight, exHeight);
				}
				heightValue = 0;
				heightIsAuto = WEBC_TRUE;
				marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0);
				break;

			case HEIGHT_KNOWN|TOP_KNOWN:
				// top = top
				// height = height
				if (top.type == CSS_LENGTH_UNIT_PERCENT && parentHeightIsAuto)
				{
					topValue = autoIndentTop;
				}
				else
				{
					topValue = CSS_LengthToPixels(&top, parentHeight, emHeight, exHeight);
				}
				heightValue = CSS_LengthToPixels(&height, parentHeight, emHeight, exHeight);
				heightIsAuto = WEBC_FALSE;
				marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0);
				break;

			case BOTTOM_KNOWN:
				// bottom = bottom
				// height = content height
				// top = parentHeight - (height + bottom)
				bottomValue = GetPixelLength(&bottom, parentHeight, emHeight, exHeight, 0);
				marginBottomValue = GetPixelLength(CSS_PROPERTY_MARGIN_BOTTOM, parentWidth, emHeight, exHeight, 0);
				heightValue = 0;
				heightIsAuto = WEBC_TRUE;
				break;

			case HEIGHT_KNOWN|BOTTOM_KNOWN:
				// bottom = bottom
				// height = height
				// top = parentHeight - (height + bottom)
				bottomValue = GetPixelLength(&bottom, parentHeight, emHeight, exHeight, 0);
				heightValue = CSS_LengthToPixels(&height, parentHeight, emHeight, exHeight);
				heightIsAuto = WEBC_FALSE;

				marginBottomValue = GetPixelLength(CSS_PROPERTY_MARGIN_BOTTOM, parentWidth, emHeight, exHeight, 0);

				topValue = parentHeight -
			               (borderTopValue +
			                paddingTopValue +
			                heightValue +
			                paddingBottomValue +
			                borderBottomValue +
			                marginBottomValue +
			                bottomValue);
				break;

			case TOP_KNOWN|BOTTOM_KNOWN:
				// top = top
				// bottom = bottom
				// height = parentHeight - (top + bottom)
				if (top.type == CSS_LENGTH_UNIT_PERCENT && parentHeightIsAuto)
				{
					topValue = autoIndentTop;
				}
				else
				{
					topValue = CSS_LengthToPixels(&top, parentHeight, emHeight, exHeight);
				}
				bottomValue = GetPixelLength(&bottom, parentHeight, emHeight, exHeight, 0);

				marginTopValue = GetPixelLength(CSS_PROPERTY_MARGIN_TOP, parentWidth, emHeight, exHeight, 0);
				marginBottomValue = GetPixelLength(CSS_PROPERTY_MARGIN_BOTTOM, parentWidth, emHeight, exHeight, 0);

				heightValue = parentHeight -
				              (topValue +
							   marginTopValue +
							   borderTopValue +
							   paddingTopValue +
				               paddingBottomValue +
							   borderBottomValue +
							   marginBottomValue +
							   bottomValue);
				heightIsAuto = WEBC_FALSE;
				break;
		}

		if (width.type != CSS_LENGTH_UNIT_AUTO)
		{
			widthValue = CSS_LengthToPixels(&width, parentWidth, emHeight, exHeight);

			WEBC_BOOL leftAligned = (textDirection == TU_DIR_RTL)?
			                            (right.type == CSS_LENGTH_UNIT_AUTO && left.type  != CSS_LENGTH_UNIT_AUTO) :
										(left.type  != CSS_LENGTH_UNIT_AUTO || right.type == CSS_LENGTH_UNIT_AUTO);

			if (leftAligned)
			{
				// ignore right and margin-right
				leftValue = GetPixelLength(&left, parentWidth, emHeight, exHeight, autoIndentLeft);
				marginLeftValue = GetPixelLength(CSS_PROPERTY_MARGIN_LEFT, parentWidth, emHeight, exHeight, 0);
			}
			else
			{
				DISPLAY_INT marginRightValue;

				// ignore left and margin-left
				rightValue = GetPixelLength(&right, parentWidth, emHeight, exHeight, autoIndentRight);
				marginRightValue = GetPixelLength(CSS_PROPERTY_MARGIN_RIGHT, parentWidth, emHeight, exHeight, 0);
				leftValue = parentWidth -
				            (rightValue +
							 marginRightValue +
							 borderRightValue +
							 paddingRightValue +
				             widthValue +
							 paddingLeftValue +
							 borderLeftValue);

				marginLeftValue = 0;
			}
		}
		else
		{
			// width.type == CSS_LENGTH_UNIT_AUTO

			// try to get the intrinsic width of the element.  This might rely on the
			//  calculated height of the element; for example, in the case of an image with
			//  specified height and auto width, the aspect ratio of the source image determines
			//  the resulting intrinsic width.

			DISPLAY_INT marginRightValue;
			WEBC_BOOL hasIntrinsicWidth = GetIntrinsicWidth(&widthValue, heightValue, heightIsAuto);

			if (left.type == CSS_LENGTH_UNIT_AUTO && right.type != CSS_LENGTH_UNIT_AUTO && hasIntrinsicWidth)
			{
				rightValue = GetPixelLength(&right, parentWidth, emHeight, exHeight, autoIndentRight);
				marginRightValue = GetPixelLength(CSS_PROPERTY_MARGIN_RIGHT, parentWidth, emHeight, exHeight, 0);
				marginLeftValue = 0;

				leftValue = parentWidth -
							 (widthValue +
							  borderLeftValue +
							  paddingLeftValue +
							  paddingRightValue +
							  borderRightValue +
							  marginRightValue +
							  rightValue);
			}
			else
			{
				leftValue = GetPixelLength(&left,  parentWidth, emHeight, exHeight, autoIndentLeft);
				marginLeftValue = GetPixelLength(CSS_PROPERTY_MARGIN_LEFT,  parentWidth, emHeight, exHeight, 0);

				if (!hasIntrinsicWidth || (right.type != CSS_LENGTH_UNIT_AUTO && left.type != CSS_LENGTH_UNIT_AUTO))
				{
					// right and left are both non-auto, OR element has no intrinsic width:
					//  calculate left, right, and margins then extrapolate width
					rightValue = GetPixelLength(&right, parentWidth, emHeight, exHeight, autoIndentRight);
					marginRightValue = GetPixelLength(CSS_PROPERTY_MARGIN_RIGHT, parentWidth, emHeight, exHeight, 0);

					widthValue = parentWidth -
								 (leftValue +
								  marginLeftValue +
								  borderLeftValue +
								  paddingLeftValue +
								  paddingRightValue +
								  borderRightValue +
								  marginRightValue +
								  rightValue);

					// we don't want to stretch the width beyond what the maximum content
					//  width; only give the element as much space as it actually needs.
					if (right.type == CSS_LENGTH_UNIT_AUTO || left.type == CSS_LENGTH_UNIT_AUTO)
					{
						// to speed this up, bail out of GetMaxWidth when we exceed widthValue
						DISPLAY_INT maxWidth = GetMaxWidthSmallerThan(widthValue);

						// NOTE: GetMaxWidth and GetMaxWidthSmallerThan return the total width
						//  of the element, including borders and padding.  So we must subtract
						//  borders and padding to make it correspond to the contentWidth

						maxWidth -= (borderLeftValue + paddingLeftValue + paddingRightValue + borderRightValue);

						if (maxWidth < widthValue)
						{
							WEBC_BOOL leftAligned = (textDirection == TU_DIR_RTL)?
														(right.type == CSS_LENGTH_UNIT_AUTO && left.type  != CSS_LENGTH_UNIT_AUTO) :
														(left.type  != CSS_LENGTH_UNIT_AUTO || right.type == CSS_LENGTH_UNIT_AUTO);

							if (!leftAligned)
							{
								// box is right-aligned
								//  adjust leftValue to account for the unused space
								leftValue += (widthValue - maxWidth);
							}
							widthValue = maxWidth;
						}
					}
				}
			}
		}

		// Now format the content of this element

		DISPLAY_INT contentHeight = FormatContentPositioned (
				widthValue,
				heightValue,
				heightIsAuto,
				borderLeftValue,
				borderTopValue,
				borderRightValue,
				borderBottomValue,
				paddingLeftValue,
				paddingTopValue,
				paddingRightValue,
				paddingBottomValue
			);

		// Find the top edge and height

		//  NOTE: top and bottom percentages are relative to parent's HEIGHT, whereas
		//   margin-top and margin-bottom are relative to parent's WIDTH, except in the root
		//   context (tbd - handle this special case correctly)

		switch (verticalCase)
		{
			case NOTHING_KNOWN:
			case TOP_KNOWN:
				heightValue = contentHeight;
				break;

			case BOTTOM_KNOWN:
				// height = content height
				// top = parentHeight - (height + bottom)
				heightValue = contentHeight;
				topValue = parentHeight -
			               (borderTopValue +
			                paddingTopValue +
			                heightValue +
			                paddingBottomValue +
			                borderBottomValue +
			                marginBottomValue +
			                bottomValue);
				break;
		}

		rect.Set (0, 0,
				borderLeftValue + paddingLeftValue + widthValue  + paddingRightValue  + borderRightValue - 1,
				borderTopValue  + paddingTopValue  + heightValue + paddingBottomValue + borderBottomValue - 1
			);

		rect.MoveTo (
				parentBorderLeft + leftValue + marginLeftValue,
				parentBorderTop + topValue  + marginTopValue
			);

		if (position == TU_POSITION_FIXED)
		{
			rect.Shift(containingBlock.left, containingBlock.top);
		}

		Move(&rect);

		if (generateChildContext)
		{
			childContext = childContextFactory->newPositioned (
					&rect,
					heightIsAuto,
					TU_DIR_LTR,
					borderLeftValue,
					borderTopValue,
					borderRightValue,
					borderBottomValue,
					paddingLeftValue,
					paddingTopValue,
					paddingRightValue
				);
		}
	}

	return (childContext);
}
void WebEditBox::DrawThisOnly (DISPLAY_INT x, DISPLAY_INT y, WebGraphics *gc)
{
	WebChar c;
	long line;

	WebRect box;
	GetFrameRect(&box);
	box.Shift(x,y);

//	gc->StartBuffer();                      // begin buffering graphics commands
	gc->Rectangle(&box, GetBgColor(gc), GetBgColor(gc), 1);	// draw background
	DrawFrame(&box, gc);

	// save the current graphics context clip rectangle and set clipping to the
	//  text display region of the widget
	GetTextRect(&box);
	box.Shift(x,y);
	WebRect clipSave;
	gc->GetClip(&clipSave);
	if (clipSave.Overlaps(&box))
	{
		WebRect clip(box);
		clip.And(&clipSave);
		gc->SetClip(&clip);

		miXOffset = (mpHScroll)? mpHScroll->GetPosition() : 0;
		miYOffset = (mpVScroll)? mpVScroll->GetPosition() : 0;

		// render our text
		WebFont font = mFont.GetFont();
		if (mpText && font)
		{
			// this loop draws up to the last line
			for (line=0; line<(miNumLines-1); line++)
			{
				c = mpText[GetLineOffset(line+1)];
				mpText[GetLineOffset(line+1)] = 0;
				DrawText(gc, box.left - miXOffset, box.top - miYOffset + (line * WEB_FONT_HEIGHT(font)),
				         mpText + GetLineOffset(line), GetTextColor(gc), 0, 0, font);
				mpText[GetLineOffset(line+1)] = c;
			}

			// now draw the last line of text.
			DrawText(gc, box.left - miXOffset, box.top - miYOffset + (line*WEB_FONT_HEIGHT(font)),
			         mpText + GetLineOffset(line), GetTextColor(gc), 0, 0, font);

			// if we have the focus, draw the cursor
			if ((mFlags & DISPLAY_FLAG_FOCUS) && !(mFlags & DISPLAY_FLAG_DISABLED))
			{
				// now render the selected portion in reverse video (if we have one)
				if (mEditFlags & EDIT_FLAG_HAS_SELECTION)
				{
					long begin = EBSMIN(miCursorPos, miSelectBegin);
					long end = EBSMAX(miCursorPos, miSelectBegin);
					long beginLine = FindLine(begin), endLine = FindLine(end);
					DISPLAY_INT textLeft;
					long currentBegin, currentEnd;

					for (line=beginLine; line<=endLine; line++)
					{
						currentBegin = EBSMAX(begin, GetLineOffset(line));
						if (line == endLine)
						{
							currentEnd = end;
						}
						else
						{
							currentEnd = EBSMIN(end, GetLineOffset(line+1));
						}
						textLeft = gc->TextWidthLen(mpText + GetLineOffset(line), font, EBSMAX(0, begin - GetLineOffset(line)));

						c = mpText[currentEnd];
						mpText[currentEnd] = 0;
						DrawText(gc, box.left - miXOffset + textLeft,
						             box.top - miYOffset + (line*WEB_FONT_HEIGHT(font)),
						             mpText + currentBegin, GetBgColor(gc), GetSelectColor(gc), 1, font);
						mpText[currentEnd] = c;
					}
				}

				DISPLAY_INT cursorX = box.left - miXOffset +
					gc->TextWidthLen(mpText + GetLineOffset(miCurrentLine), font, miCursorPos - GetLineOffset(miCurrentLine)) ;
				box.Set(cursorX, box.top - miYOffset + WEB_FONT_HEIGHT(font)*miCurrentLine,
				        cursorX, box.top - miYOffset + WEB_FONT_HEIGHT(font)*(miCurrentLine+1));
				gc->Rectangle(&box, GetSelectColor(gc), GetSelectColor(gc), 1);
			}

		}

		gc->SetClip(&clipSave);	 // restore the clip rectangle
	} // if clip overlaps

/*	if (mpVScroll && mpHScroll)
	{
		GetCornerRect(&box);
		box.Shift(x,y);
		gc->Rectangle(&box, LIGHTGRAY, LIGHTGRAY, 1);
	}*/

//	gc->EndBuffer();	     // send all buffered commands to the display

}
void DisplayManager::Draw(DISPLAY_INT x, DISPLAY_INT y, WebRect *pViewport, WebGraphics *pGC)
{
	if (mNoRefresh)
	{
		DisplayManager* parentDisplayManager = GetManager();

		if (parentDisplayManager)
		{
			// This handles the case where a DisplayManager that is NOT the root
			//  DisplayManager has a positive refresh lock, prohibiting its being
			//  drawn, but the parent DisplayManager does not (otherwise we would
			//  not even be in our Draw method); in this case:
			//
			// IF this element is within the collective invalid region being
			//    painted, THEN we want to re-invalidate the invalid part of (this),
			//    which will cause said region to re-paint when the refresh lock
			//    is removed from this element and this->Refresh is eventually called.

			WebRect clipRect;
			pGC->GetClip(&clipRect);

			WebRect screenRect(mRect);
			screenRect.MoveTo(x,y);

			if (clipRect.Overlaps(&screenRect))
			{
				SetManagerFlag(MANAGER_FLAG_TRIED_TO_DRAW);
				//screenRect.And(&clipRect);
				//screenRect.Shift(-pViewport->left, -pViewport->top);
				//parentDisplayManager->InvalidateViewportRegion(&screenRect);
			}
		}

		return;
	}

	FormatResult result;

	switch (GetScrollMode())
	{
		case SCROLL_MODE_NONE:
			if (mpVScroll || mpHScroll)
			{
				DetachVScroll();
				DetachHScroll();
				UpdateViewport();
			}
			break;

		case SCROLL_MODE_HSCROLL:
			if (mpVScroll || !mpHScroll)
			{
				DetachVScroll();
				AttachHScroll();
				UpdateViewport();
			}
			break;

		case SCROLL_MODE_VSCROLL:
			if (!mpVScroll || mpHScroll)
			{
				AttachVScroll();
				DetachHScroll();
				UpdateViewport();
			}
			break;

		case SCROLL_MODE_BOTH:
			if (!mpVScroll || !mpHScroll)
			{
				AttachVScroll();
				AttachHScroll();
				UpdateViewport();
			}
			break;

		case SCROLL_MODE_AUTO:
			break;
	}

	if (mRoot.Get())
	{
		int i = 0;

		do
		{
			result = mRoot.Get()->FormatForViewport(&mViewRect, (mpHScroll != 0), (mpVScroll != 0));

			if (GetScrollMode() == SCROLL_MODE_AUTO)
			{
				if (result == DISPLAY_FORMAT_NEEDS_VSCROLL)
				{
					// create a vscroll bar
					if (mpVScroll)
					{
						// what the... we already have a vscroll bar!
						break;
					}
					AttachVScroll();

					// check for creation failure - may indicate low memory condition
					if (!mpVScroll)
					{
						// can't go on...
						break;
					}

					UpdateViewport();
				}
				else if (result == DISPLAY_FORMAT_NEEDS_HSCROLL)
				{
					// create a hscroll bar
					if (mpHScroll)
					{
						// what the... we already have a hscroll bar!
						break;
					}
					AttachHScroll();

					// check for creation failure - may indicate low memory condition
					if (!mpHScroll)
					{
						// can't go on...
						break;
					}

					UpdateViewport();
				}
			}
			else
			{
				break;
			}

			// put a hard upper bound on the number of times we try to re-format
			//  (4, since this means we've covered all combinations of horizontal
			//   and vertical scroll bars on the window)
			i++;
		}
		while (result != DISPLAY_FORMAT_SUCCESS && i < 5);

		if (GetScrollMode() == SCROLL_MODE_AUTO)
		{
			WebRect rootBounds;
			GetRootBounds(&rootBounds);

			if (rootBounds.Height() <= mViewRect.Height() && mpVScroll)
			{
				DetachVScroll();
				UpdateViewport();
				mRoot.Get()->FormatForViewport(&mViewRect, (mpHScroll != 0), (mpVScroll != 0));
				GetRootBounds(&rootBounds);
			}

			if (rootBounds.Width() <= mViewRect.Width() && mpHScroll)
			{
				DetachHScroll();
				UpdateViewport();
				mRoot.Get()->FormatForViewport(&mViewRect, (mpHScroll != 0), (mpVScroll != 0));
				GetRootBounds(&rootBounds);
			}

			if (rootBounds.Height() <= mViewRect.Height() && mpVScroll)
			{
				DetachVScroll();
				UpdateViewport();
				mRoot.Get()->FormatForViewport(&mViewRect, (mpHScroll != 0), (mpVScroll != 0));
				GetRootBounds(&rootBounds);
			}
		}

		mViewportChanged = WEBC_FALSE;

		CorrectViewportPosition();

		if (mpFocus && (mpVScroll!=0) && (mpHScroll!=0))
		{
			WebRect focusRect;
			WebRect elemRect;
			WEBC_BOOL ensureFocusVisible = mpFocus->GetFocusRect (&focusRect);
			if (ensureFocusVisible)
			{
				GetElementRect(&elemRect, mpFocus);
				focusRect.Shift(elemRect.left, elemRect.top);

				// this will adjust the scroll bars so that the given rect is in view
				EnsureRectVisible(&focusRect);
			}
		}
	}

	DisplayElement::Draw(x, y, pViewport, pGC);
}
Exemple #6
0
void WebDropBox::Drop(void)
{
	WEBC_ASSERT(GetManager());
	if (mState == DROPBOX_STATE_DROPPED)
	{
		return;
	}

	int spaceUp, spaceDown;
	CalculateAvailableSpace(&spaceUp, &spaceDown);

	int neededSpace = mListbox.GetTotalTextHeight() +
		mListbox.GetMargin() + mListbox.GetPadding() * 2 +
		mListbox.GetBorder() * 2;

	WebRect rect;
	if (spaceDown >= neededSpace || spaceDown > spaceUp)
	{
		DISPLAY_INT space = EBSMIN(spaceDown, neededSpace);
		rect.top = Height() - DROPBOX_MARGIN;
		rect.left = DROPBOX_MARGIN;
		rect.right = Width() - DROPBOX_MARGIN - 1;
		rect.bottom = rect.top + space - 1;
	}
	else
	{
		DISPLAY_INT space = EBSMIN(spaceUp, neededSpace);
		rect.top = -space;
		rect.left = DROPBOX_MARGIN;
		rect.right = Width() - DROPBOX_MARGIN - 1;
		rect.bottom = DROPBOX_MARGIN - 1;
	}


	SetFlag(DISPLAY_FLAG_DIRTY);
	Invalidate();
	mState = DROPBOX_STATE_DROPPED;

	if (mpParent)
	{
		DISPLAY_INT left,top;
		mpParent->GetDisplayPosition(this, &left, &top);
		rect.Shift(left,top);
	}

	mListbox.Move(&rect);
	DisplayManager *m = GetManager();
	WebGraphics *gc = m? m->GetGraphics() : 0;
	if (gc)
	{
		mListbox.SetupScrollBars(gc);
	}

	// we need to make sure the list box appears on top of everything.
	DisplayElement *parent = this;
	while (parent->mpParent)
	{
		parent = parent->mpParent;
	}
	parent->InsertLast(&mListbox);

	mListbox.Invalidate();
}
Exemple #7
0
void WebDropBox::DrawThisOnly (DISPLAY_INT x, DISPLAY_INT y, WebGraphics *gc)
{
	WEBC_BOOL focused = (mFlags & DISPLAY_FLAG_FOCUS) || (mState == DROPBOX_STATE_DROPPED);

	mListbox.CalculateTextMetrics(gc);

	WebRect oldClip;
	gc->GetClip(&oldClip);
	WebRect clip;
	clip.top = y;
	clip.left = x;
	clip.bottom = y + Height() - 1;
	clip.right = x + Width() - 1;
	clip.And(&oldClip);

	gc->SetClip(&clip);

	WebRect rect;
	rect.top = y;
	rect.left = x;
	rect.bottom = y + Height() - 1;
	rect.right = x + Width() - 1;

//	gc->StartBuffer();

	WebColor hilite, lolite, blue, white, black;
	HTMLColor col = HTML_RGBAToColor(0,0,0,0);
	black = hilite = gc->RGBToColor(col);

	col = HTML_RGBAToColor(0xff,0xff,0xff,0);
	white = lolite = gc->RGBToColor(col);

	col = HTML_RGBAToColor(0,0,0xff,0);
	blue = gc->RGBToColor(col);

	if (focused)
	{
		gc->Rectangle(&rect, black, black, WEBC_FALSE);
	}

	GetFrameRect(&rect);
	rect.Shift(x,y);
	DrawFrame(&rect, gc);

	GetContentRect(&rect);
	rect.Shift(x,y);

	if (focused)
	{
		gc->Rectangle(&rect, GetSelectColor(gc), GetSelectColor(gc), WEBC_TRUE);
	}
	else
	{
		gc->Rectangle(&rect, GetBgColor(gc), GetBgColor(gc), WEBC_TRUE);
	}

	if (mpText && mFont.GetFont())
	{
		DISPLAY_INT offset = (rect.Height() - gc->TextHeight(mpText, mFont.GetFont())) / 2;

		clip.Set(&rect);
		clip.And(&oldClip);
		gc->SetClip(&clip);
		gc->Text(rect.left + DROPBOX_PADDING,
			 rect.top + DROPBOX_PADDING + offset,
			 mpText, (focused) ? GetBgColor(gc) : GetTextColor(gc),
			 0, WEBC_FALSE, mFont.GetFont());
	}

//	gc->EndBuffer();
	gc->SetClip(&oldClip);

}