void
ParagraphLayout::GetLineBounds(int32 lineIndex, float& x1, float& y1,
	float& x2, float& y2)
{
	_ValidateLayout();

	if (fGlyphInfos.CountItems() == 0) {
		_GetEmptyLayoutBounds(x1, y1, x2, y2);
		return;
	}

	if (lineIndex < 0)
		lineIndex = 0;
	if (lineIndex >= fLineInfos.CountItems())
		lineIndex = fLineInfos.CountItems() - 1;

	const LineInfo& lineInfo = fLineInfos.ItemAt(lineIndex);
	int32 firstGlyphIndex = lineInfo.textOffset;

	int32 lastGlyphIndex;
	if (lineIndex < fLineInfos.CountItems() - 1)
		lastGlyphIndex = fLineInfos.ItemAt(lineIndex + 1).textOffset - 1;
	else
		lastGlyphIndex = fGlyphInfos.CountItems() - 1;

	const GlyphInfo& firstInfo = fGlyphInfos.ItemAtFast(firstGlyphIndex);
	const GlyphInfo& lastInfo = fGlyphInfos.ItemAtFast(lastGlyphIndex);

	x1 = firstInfo.x;
	y1 = lineInfo.y;
	x2 = lastInfo.x + lastInfo.width;
	y2 = lineInfo.y + lineInfo.height;
}
void
ParagraphLayout::GetTextBounds(int32 textOffset, float& x1, float& y1,
	float& x2, float& y2)
{
	_ValidateLayout();

	if (fGlyphInfos.CountItems() == 0) {
		_GetEmptyLayoutBounds(x1, y1, x2, y2);
		return;
	}

	if (textOffset >= fGlyphInfos.CountItems()) {
		const GlyphInfo& glyph = fGlyphInfos.LastItem();
		const LineInfo& line = fLineInfos.ItemAt(glyph.lineIndex);

		x1 = glyph.x + glyph.width;
		x2 = x1;
		y1 = line.y;
		y2 = y1 + line.height;

		return;
	}

	if (textOffset < 0)
		textOffset = 0;
	
	const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset);
	const LineInfo& line = fLineInfos.ItemAt(glyph.lineIndex);

	x1 = glyph.x;
	x2 = x1 + glyph.width;
	y1 = line.y;
	y2 = y1 + line.height;
}
int32
TextDocumentLayout::_ParagraphLayoutIndexForOffset(int32& textOffset)
{
	_ValidateLayout();

	int32 paragraphs = fParagraphLayouts.CountItems();
	for (int32 i = 0; i < paragraphs - 1; i++) {
		const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(i);
		
		int32 length = info.layout->CountGlyphs();
		if (textOffset >= length) {
			textOffset -= length;
			continue;
		}
		
		return i;
	}
	
	if (paragraphs > 0) {
		const ParagraphLayoutInfo& info = fParagraphLayouts.LastItem();

		// Return last paragraph if the textOffset is still within or
		// exactly behind the last valid offset in that paragraph.
		int32 length = info.layout->CountGlyphs();
		if (textOffset <= length)
			return paragraphs - 1;
	}
	
	return -1;
}
Exemple #4
0
BTextControl::BTextControl(const char* name, const char* label,
		const char* text, BMessage* message, uint32 flags)
	: BControl(name, label, message, flags | B_FRAME_EVENTS)
{
	_InitData(label, text);
	_ValidateLayout();
}
Exemple #5
0
BTextControl::BTextControl(const char* label, const char* text,
		BMessage* message)
	: BControl(NULL, label, message,
		B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS)
{
	_InitData(label, text);
	_ValidateLayout();
}
Exemple #6
0
BTextControl::BTextControl(BRect frame, const char* name, const char* label,
		const char* text, BMessage* message, uint32 mask, uint32 flags)
	:
	BControl(frame, name, label, message, mask, flags | B_FRAME_EVENTS)
{
	_InitData(label);
	_InitText(text);
	_ValidateLayout();
}
Exemple #7
0
void
ParagraphLayout::Draw(BView* view, const BPoint& offset)
{
	_ValidateLayout();
	
	int lineCount = fLineInfos.CountItems();
	for (int i = 0; i < lineCount; i++) {
		const LineInfo& line = fLineInfos.ItemAtFast(i);
		_DrawLine(view, line);
	}
}
int32
ParagraphLayout::FirstOffsetOnLine(int32 lineIndex)
{
	_ValidateLayout();

	if (lineIndex < 0)
		lineIndex = 0;
	if (lineIndex >= fLineInfos.CountItems())
		lineIndex = fLineInfos.CountItems() - 1;

	return fLineInfos.ItemAt(lineIndex).textOffset;
}
int32
ParagraphLayout::LastOffsetOnLine(int32 lineIndex)
{
	_ValidateLayout();

	if (lineIndex < 0)
		lineIndex = 0;

	if (lineIndex >= fLineInfos.CountItems() - 1)
		return CountGlyphs() - 1;

	return fLineInfos.ItemAt(lineIndex + 1).textOffset - 1;
}
float
TextDocumentLayout::Height()
{
	_ValidateLayout();

	float height = 0.0f;

	if (fParagraphLayouts.CountItems() > 0) {
		const ParagraphLayoutInfo& lastLayout = fParagraphLayouts.LastItem();
		height = lastLayout.y + lastLayout.layout->Height();
	}

	return height;
}
Exemple #11
0
float
ParagraphLayout::Height()
{
	_ValidateLayout();

	float height = 0.0f;

	if (fLineInfos.CountItems() > 0) {
		const LineInfo& lastLine = fLineInfos.LastItem();
		height = lastLine.y + lastLine.height;
	}

	return height;
}
int32
TextDocumentLayout::CountLines()
{
	_ValidateLayout();

	int32 lineCount = 0;

	int32 count = fParagraphLayouts.CountItems();
	for (int32 i = 0; i < count; i++) {
		const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(i);
		lineCount += info.layout->CountLines();
	}

	return lineCount;
}
void
TextDocumentLayout::Draw(BView* view, const BPoint& offset,
	const BRect& updateRect)
{
	_ValidateLayout();

	int layoutCount = fParagraphLayouts.CountItems();
	for (int i = 0; i < layoutCount; i++) {
		const ParagraphLayoutInfo& layout = fParagraphLayouts.ItemAtFast(i);
		BPoint location(offset.x, offset.y + layout.y);
		if (location.y > updateRect.bottom)
			break;
		if (location.y + layout.layout->Height() > updateRect.top)
			layout.layout->Draw(view, location);
	}
}
Exemple #14
0
int32
ParagraphLayout::LineIndexForOffset(int32 textOffset)
{
	_ValidateLayout();

	if (fGlyphInfos.CountItems() == 0)
		return 0;

	if (textOffset >= fGlyphInfos.CountItems()) {
		const GlyphInfo& glyph = fGlyphInfos.LastItem();
		return glyph.lineIndex;
	}

	if (textOffset < 0)
		textOffset = 0;
	
	const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset);
	return glyph.lineIndex;
}
Exemple #15
0
void
ParagraphLayout::Draw(BView* view, const BPoint& offset)
{
	_ValidateLayout();

	int lineCount = fLineInfos.CountItems();
	for (int i = 0; i < lineCount; i++) {
		const LineInfo& line = fLineInfos.ItemAtFast(i);
		_DrawLine(view, offset, line);
	}

	const Bullet& bullet = fParagraphStyle.Bullet();
	if (bullet.Spacing() > 0.0f && bullet.String().Length() > 0) {
		// Draw bullet at offset
		view->SetHighColor(0, 0, 0, 255);
		BPoint bulletPos(offset);
		bulletPos.x += fParagraphStyle.FirstLineInset()
			+ fParagraphStyle.LineInset();
		bulletPos.y += fLineInfos.ItemAt(0).maxAscent;
		view->DrawString(bullet.String(), bulletPos);
	}
}
int32
TextDocumentLayout::TextOffsetAt(float x, float y, bool& rightOfCenter)
{
	_ValidateLayout();

	int32 textOffset = 0;
	rightOfCenter = false;

	int32 paragraphs = fParagraphLayouts.CountItems();
	for (int32 i = 0; i < paragraphs; i++) {
		const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(i);
		if (y > info.y + info.layout->Height()) {
			textOffset += info.layout->CountGlyphs();
			continue;
		}

		textOffset += info.layout->TextOffsetAt(x, y - info.y, rightOfCenter);
		break;
	}
	
	return textOffset;
}
int32
TextDocumentLayout::_ParagraphLayoutIndexForLineIndex(int32& lineIndex,
	int32& paragraphOffset)
{
	_ValidateLayout();

	paragraphOffset = 0;
	int32 paragraphs = fParagraphLayouts.CountItems();
	for (int32 i = 0; i < paragraphs; i++) {
		const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(i);

		int32 lineCount = info.layout->CountLines();
		if (lineIndex >= lineCount) {
			lineIndex -= lineCount;
			paragraphOffset += info.layout->CountGlyphs();
			continue;
		}
		
		return i;
	}

	return -1;
}
Exemple #18
0
int32
ParagraphLayout::TextOffsetAt(float x, float y, bool& rightOfCenter)
{
	_ValidateLayout();

	rightOfCenter = false;

	int32 lineCount = fLineInfos.CountItems();
	if (fGlyphInfos.CountItems() == 0 || lineCount == 0
		|| fLineInfos.ItemAtFast(0).y > y) {
		// Above first line or empty text
		return 0;
	}

	int32 lineIndex = 0;
	if (floorf(fLineInfos.LastItem().y
			+ fLineInfos.LastItem().height + 0.5) > y) {
		// TODO: Optimize, can binary search line here:
		for (; lineIndex < lineCount; lineIndex++) {
			const LineInfo& line = fLineInfos.ItemAtFast(lineIndex);
			float lineBottom = floorf(line.y + line.height + 0.5);
			if (lineBottom > y)
				break;
		}
	} else {
		lineIndex = lineCount - 1;
	}

	// Found line
	const LineInfo& line = fLineInfos.ItemAtFast(lineIndex);
	int32 textOffset = line.textOffset;
	int32 end;
	if (lineIndex < lineCount - 1)
		end = fLineInfos.ItemAtFast(lineIndex + 1).textOffset - 1;
	else
		end = fGlyphInfos.CountItems() - 1;

	// TODO: Optimize, can binary search offset here:
	for (; textOffset <= end; textOffset++) {
		const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset);
		float x1 = glyph.x;
		if (x1 > x)
			return textOffset;

		// x2 is the location at the right bounding box of the glyph
		float x2 = x1 + glyph.width;

		// x3 is the location of the next glyph, which may be different from
		// x2 in case the line is justified.
		float x3;
		if (textOffset < end - 1)
			x3 = fGlyphInfos.ItemAtFast(textOffset + 1).x;
		else
			x3 = x2;

		if (x3 > x) {
			rightOfCenter = x > (x1 + x2) / 2.0f;
			return textOffset;
		}
	}

	// Account for trailing line break at end of line, the
	// returned offset should be before that.
	rightOfCenter = fGlyphInfos.ItemAtFast(end).charCode != '\n';

	return end;
}
Exemple #19
0
int32
ParagraphLayout::CountLines()
{
	_ValidateLayout();
	return fLineInfos.CountItems();
}