FBoxSphereBounds UTextRenderComponent::CalcBounds(const FTransform& LocalToWorld) const
{
	if(!Text.IsEmpty() && Font)
	{
		FVector2D Size(FLT_MIN, 0);
		FVector2D LeftTop(FLT_MAX, FLT_MAX);
		float FirstLineHeight = -1;

		FTextIterator It(*Text.ToString());

		float AdjustedXScale = WorldSize * XScale * InvDefaultSize;
		float AdjustedYScale = WorldSize * YScale * InvDefaultSize;

		while (It.NextLine())
		{
			FVector2D LineSize = ComputeTextSize(It, Font, AdjustedXScale, AdjustedYScale, HorizSpacingAdjust);
			float LineLeft = ComputeHorizontalAlignmentOffset(LineSize, HorizontalAlignment);

			Size.X = FMath::Max(LineSize.X, Size.X);
			Size.Y += LineSize.Y > 0 ? LineSize.Y : Font->GetMaxCharHeight();
			LeftTop.X = FMath::Min(LeftTop.X, LineLeft);

			if (FirstLineHeight < 0)
			{
				FirstLineHeight = LineSize.Y;
			}

			int32 Ch;
			while (It.NextCharacterInLine(Ch));
		}

		LeftTop.Y = ComputeVerticalAlignmentOffset(Size.Y, VerticalAlignment, FirstLineHeight);
		FBox LocalBox(FVector(0, -LeftTop.X, -LeftTop.Y), FVector(0, -(LeftTop.X + Size.X), -(LeftTop.Y + Size.Y)));

		FBoxSphereBounds Ret(LocalBox.TransformBy(LocalToWorld));

		Ret.BoxExtent *= BoundsScale;
		Ret.SphereRadius *= BoundsScale;

		return Ret;
	}
	else
	{
		return FBoxSphereBounds(ForceInit);
	}
}
HRGN CPenBrushUnit::GetRedrawHRGN(HDC hDC, std::vector<DataInfo> &DataArray,DataInfo &pDataInfo)
{
	CPoint sPoint,ePoint,psPoint,pePoint,ptPoint;
	GraphicsPath RgnPath(FillModeWinding);
	double dx,dy,xlen,ylen;
	double preWidth,nWidth;
	int count=1;
	int alpha;
	int v=0;
	Matrix matrix;
	Graphics mGraphics(hDC);
	mGraphics.TranslateTransform(pDataInfo.CenterPoint.x,pDataInfo.CenterPoint.y);
	mGraphics.RotateTransform(pDataInfo.RotateAngle);
	mGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
	sPoint=CaculatePoint(pDataInfo.StartPoint,pDataInfo);
	ePoint=CaculatePoint(pDataInfo.EndPoint,pDataInfo);
	xlen=ePoint.x-sPoint.x;
	ylen=ePoint.y-sPoint.y;
	preWidth=pDataInfo.AllRate[0].preWidth;
	alpha=pDataInfo.AllRate[0].alpha;
	psPoint.x=sPoint.x+xlen*pDataInfo.AllRate[0].xRate;
	psPoint.y=sPoint.y+ylen*pDataInfo.AllRate[0].yRate;	
	int Size=pDataInfo.AllRate.size();
	for(int Index=1;Index<Size;Index++)
	{
		pePoint.x=sPoint.x+xlen*pDataInfo.AllRate[Index].xRate;
		pePoint.y=sPoint.y+ylen*pDataInfo.AllRate[Index].yRate;
		dx=(pePoint.x-psPoint.x);
		dy=(pePoint.y-psPoint.y);
		nWidth=pDataInfo.AllRate[Index].preWidth;
		float Angle=atan2(dy,dx)*Rate;
		GraphicsPath path(FillModeWinding);
		GraphicsPath path1,path2,path3,path4;
		RectF sRectF(psPoint.x,psPoint.y,0,0);
		sRectF.Inflate(preWidth+4,preWidth+4);
		RectF eRectF(pePoint.x,pePoint.y,0,0);
		eRectF.Inflate(nWidth+4,nWidth+4);
		///////////////////////////////////////////
		REAL  left=sRectF.GetLeft();
		REAL  top=sRectF.GetTop();
		REAL  bottom=sRectF.GetBottom();
		REAL  right=sRectF.GetRight();
		Point pts0[]={Point((left+right)/2,top),Point((left+right)/2,bottom)};
		matrix.RotateAt(Angle,PointF(psPoint.x,psPoint.y));
		matrix.TransformPoints(pts0,2);
		Point LeftTop(pts0[0].X,pts0[0].Y);
		Point LeftBottom(pts0[1].X,pts0[1].Y);
		path1.AddArc(sRectF,270.0f,-180.0f);
		path1.Transform(&matrix);
		matrix.Reset();

		top=eRectF.GetTop();
		bottom=eRectF.GetBottom();
		right=eRectF.GetRight();
		left=eRectF.GetLeft();
		Point pts1[]={Point((right+left)/2,bottom),Point((right+left)/2,top)};
		matrix.RotateAt(Angle,PointF(pePoint.x,pePoint.y));
		matrix.TransformPoints(pts1,2);
		Point RightBottom(pts1[0].X,pts1[0].Y);
		Point RightTop(pts1[1].X,pts1[1].Y);
		path3.AddArc(eRectF,90.0f,-180.0f);
		path3.Transform(&matrix);
		matrix.Reset();
		Point pts[]={LeftTop,RightTop,RightBottom,LeftBottom};
		///////////////////////////////////////////
		path2.AddLine(LeftBottom,RightBottom);
		path4.AddLine(RightTop,LeftTop);
		path.AddPath(&path1,true);
		path.AddPath(&path2,true);
		path.AddPath(&path3,true);
		path.AddPath(&path4,true);
		RgnPath.AddPath(&path,false);

		preWidth=nWidth;
		psPoint=pePoint;
	}
	mGraphics.ResetTransform();
	Region Rgn(&RgnPath);
	return Rgn.GetHRGN(&mGraphics);
}
void CPenBrushUnit::ErasedDraw(CDC *memDC, DataInfo &pDataInfo,HRGN ErasedRgn)
{
	CPoint sPoint,ePoint,psPoint,pePoint,ptPoint;
	double dx,dy,xlen,ylen;
	double preWidth,nWidth;
	int count=1;
	int alpha;
	int v=0;
	int Red,Green,Blue;
	Red=GetRValue(pDataInfo.penColor);
	Green=GetGValue(pDataInfo.penColor);
	Blue=GetBValue(pDataInfo.penColor);
	Color colors[]={Color(10,Red,Green,Blue)};
	Graphics mGraphics(memDC->m_hDC);
	///////////////////////////////////
	Matrix matrix;
	Region tRgn;
	Region *ptRgn=tRgn.FromHRGN(ErasedRgn);	
	mGraphics.ExcludeClip(ptRgn);
	matrix.Reset();
	delete ptRgn;
	////////////////////////////////////
	mGraphics.TranslateTransform(pDataInfo.CenterPoint.x,pDataInfo.CenterPoint.y);
	mGraphics.RotateTransform(pDataInfo.RotateAngle);
	mGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
	sPoint=CaculatePoint(pDataInfo.StartPoint,pDataInfo);
	ePoint=CaculatePoint(pDataInfo.EndPoint,pDataInfo);
	xlen=ePoint.x-sPoint.x;
	ylen=ePoint.y-sPoint.y;
	preWidth=pDataInfo.AllRate[0].preWidth;
	alpha=pDataInfo.AllRate[0].alpha;
	psPoint.x=sPoint.x+xlen*pDataInfo.AllRate[0].xRate;
	psPoint.y=sPoint.y+ylen*pDataInfo.AllRate[0].yRate; 
	int Size=pDataInfo.AllRate.size();
	for(int Index=1;Index<Size;Index++)
	{
		pePoint.x=sPoint.x+xlen*pDataInfo.AllRate[Index].xRate;
		pePoint.y=sPoint.y+ylen*pDataInfo.AllRate[Index].yRate;
		dx=(pePoint.x-psPoint.x);
		dy=(pePoint.y-psPoint.y);
		nWidth=pDataInfo.AllRate[0].preWidth;
		float Angle=atan2(dy,dx)*Rate;
		GraphicsPath path(FillModeWinding);
		GraphicsPath path1,path2,path3,path4;
		RectF sRectF(psPoint.x,psPoint.y,0,0);
		sRectF.Inflate(preWidth,preWidth);
		RectF eRectF(pePoint.x,pePoint.y,0,0);
		eRectF.Inflate(nWidth,nWidth);
		///////////////////////////////////////////
		REAL  left=sRectF.GetLeft();
		REAL  top=sRectF.GetTop();
		REAL  bottom=sRectF.GetBottom();
		REAL  right=sRectF.GetRight();
		Point pts0[]={Point((left+right)/2,top),Point((left+right)/2,bottom)};
		matrix.RotateAt(Angle,PointF(psPoint.x,psPoint.y));
		matrix.TransformPoints(pts0,2);
		Point LeftTop(pts0[0].X,pts0[0].Y);
		Point LeftBottom(pts0[1].X,pts0[1].Y);
		path1.AddArc(sRectF,270.0f,-180.0f);
		path1.Transform(&matrix);
		matrix.Reset();

		top=eRectF.GetTop();
		bottom=eRectF.GetBottom();
		right=eRectF.GetRight();
		left=eRectF.GetLeft();
		Point pts1[]={Point((right+left)/2,bottom),Point((right+left)/2,top)};
		matrix.RotateAt(Angle,PointF(pePoint.x,pePoint.y));
		matrix.TransformPoints(pts1,2);
		Point RightBottom(pts1[0].X,pts1[0].Y);
		Point RightTop(pts1[1].X,pts1[1].Y);
		path3.AddArc(eRectF,90.0f,-180.0f);
		path3.Transform(&matrix);
		matrix.Reset();
		Point pts[]={LeftTop,RightTop,RightBottom,LeftBottom};
		///////////////////////////////////////////
		path2.AddLine(LeftBottom,RightBottom);
		path4.AddLine(RightTop,LeftTop);
		path.AddPath(&path1,true);
		path.AddPath(&path2,true);
		path.AddPath(&path3,true);
		path.AddPath(&path4,true);

		SolidBrush brush(Color(255,Red,Green,Blue));
		mGraphics.FillPath(&brush,&path);
		Pen pen(Color(255,Red,Green,Blue),1);
		mGraphics.DrawPath(&pen,&path);

		preWidth=nWidth;
		psPoint=pePoint;
	}
	mGraphics.ResetTransform();
}
TEST_F(FSDKBaseFormEmbeddertest, CBA_AnnotIterator) {
  EXPECT_TRUE(OpenDocument("annotiter.pdf"));
  FPDF_PAGE page0 = LoadPage(0);
  FPDF_PAGE page1 = LoadPage(1);
  FPDF_PAGE page2 = LoadPage(2);
  EXPECT_TRUE(page0);
  EXPECT_TRUE(page1);
  EXPECT_TRUE(page2);

  CFX_FloatRect LeftBottom(200, 200, 220, 220);
  CFX_FloatRect RightBottom(400, 201, 420, 221);
  CFX_FloatRect LeftTop(201, 400, 221, 420);
  CFX_FloatRect RightTop(401, 401, 421, 421);

  CPDFSDK_FormFillEnvironment* pFormFillEnv =
      static_cast<CPDFSDK_FormFillEnvironment*>(form_handle());

  {
    // Page 0 specifies "row order".
    CBA_AnnotIterator iter(pFormFillEnv->GetPageView(0),
                           CPDF_Annot::Subtype::WIDGET);
    CPDFSDK_Annot* pAnnot = iter.GetFirstAnnot();
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    EXPECT_EQ(iter.GetFirstAnnot(), pAnnot);

    pAnnot = iter.GetLastAnnot();
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    EXPECT_EQ(iter.GetLastAnnot(), pAnnot);
  }
  {
    // Page 1 specifies "column order"
    CBA_AnnotIterator iter(pFormFillEnv->GetPageView(1),
                           CPDF_Annot::Subtype::WIDGET);
    CPDFSDK_Annot* pAnnot = iter.GetFirstAnnot();
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    EXPECT_EQ(iter.GetFirstAnnot(), pAnnot);

    pAnnot = iter.GetLastAnnot();
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    EXPECT_EQ(iter.GetLastAnnot(), pAnnot);
  }
  {
    // Page 2 specifies "struct order"
    CBA_AnnotIterator iter(pFormFillEnv->GetPageView(2),
                           CPDF_Annot::Subtype::WIDGET);
    CPDFSDK_Annot* pAnnot = iter.GetFirstAnnot();
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    EXPECT_EQ(iter.GetFirstAnnot(), pAnnot);

    pAnnot = iter.GetLastAnnot();
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    EXPECT_EQ(iter.GetLastAnnot(), pAnnot);
  }
  UnloadPage(page2);
  UnloadPage(page1);
  UnloadPage(page0);
}
Esempio n. 5
0
void
BListView::KeyDown(const char* bytes, int32 numBytes)
{
	bool extend = fListType == B_MULTIPLE_SELECTION_LIST
		&& (modifiers() & B_SHIFT_KEY) != 0;

	switch (bytes[0]) {
		case B_UP_ARROW:
		{
			if (fFirstSelected == -1) {
				// if nothing is selected yet, always select the first item
				Select(0);
			} else {
				if (fAnchorIndex > 0) {
					if (!extend || fAnchorIndex <= fFirstSelected)
						Select(fAnchorIndex - 1, extend);
					else
						Deselect(fAnchorIndex--);
				}
			}

			ScrollToSelection();
			break;
		}
		case B_DOWN_ARROW:
		{
			if (fFirstSelected == -1) {
				// if nothing is selected yet, always select the first item
				Select(0);
			} else {
				if (fAnchorIndex < CountItems() - 1) {
					if (!extend || fAnchorIndex >= fLastSelected)
						Select(fAnchorIndex + 1, extend);
					else
						Deselect(fAnchorIndex++);
				}
			}

			ScrollToSelection();
			break;
		}

		case B_HOME:
			if (extend) {
				Select(0, fAnchorIndex, true);
				fAnchorIndex = 0;
			} else
				Select(0, false);

			ScrollToSelection();
			break;
		case B_END:
			if (extend) {
				Select(fAnchorIndex, CountItems() - 1, true);
				fAnchorIndex = CountItems() - 1;
			} else
				Select(CountItems() - 1, false);

			ScrollToSelection();
			break;

		case B_PAGE_UP:
		{
			BPoint scrollOffset(LeftTop());
			scrollOffset.y = max_c(0, scrollOffset.y - Bounds().Height());
			ScrollTo(scrollOffset);
			break;
		}
		case B_PAGE_DOWN:
		{
			BPoint scrollOffset(LeftTop());
			if (BListItem* item = LastItem()) {
				scrollOffset.y += Bounds().Height();
				scrollOffset.y = min_c(item->Bottom() - Bounds().Height(),
					scrollOffset.y);
			}
			ScrollTo(scrollOffset);
			break;
		}

		case B_RETURN:
		case B_SPACE:
			Invoke();
			break;

		default:
			BView::KeyDown(bytes, numBytes);
	}
}
TEST_F(FSDKBaseFormEmbeddertest, CBA_AnnotIterator) {
  EXPECT_TRUE(OpenDocument("annotiter.pdf"));
  EXPECT_TRUE(LoadPage(0));
  EXPECT_TRUE(LoadPage(1));
  EXPECT_TRUE(LoadPage(2));

  CPDF_Rect LeftBottom(200, 200, 220, 220);
  CPDF_Rect RightBottom(400, 201, 420, 221);
  CPDF_Rect LeftTop(201, 400, 221, 420);
  CPDF_Rect RightTop(401, 401, 421, 421);

  CPDFSDK_Document* pSDKDoc =
      CPDFSDK_Document::FromFPDFFormHandle(form_handle());
  {
    // Page 0 specifies "row order".
    CBA_AnnotIterator iter(pSDKDoc->GetPageView(0), "Widget", "");
    CPDFSDK_Annot* pAnnot = iter.GetFirstAnnot();
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    EXPECT_EQ(iter.GetFirstAnnot(), pAnnot);

    pAnnot = iter.GetLastAnnot();
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    EXPECT_EQ(iter.GetLastAnnot(), pAnnot);
  }
  {
    // Page 1 specifies "column order"
    CBA_AnnotIterator iter(pSDKDoc->GetPageView(1), "Widget", "");
    CPDFSDK_Annot* pAnnot = iter.GetFirstAnnot();
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    EXPECT_EQ(iter.GetFirstAnnot(), pAnnot);

    pAnnot = iter.GetLastAnnot();
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    EXPECT_EQ(iter.GetLastAnnot(), pAnnot);
  }
  {
    // Page 2 specifies "struct order"
    CBA_AnnotIterator iter(pSDKDoc->GetPageView(2), "Widget", "");
    CPDFSDK_Annot* pAnnot = iter.GetFirstAnnot();
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetNextAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetNextAnnot(pAnnot);
    EXPECT_EQ(iter.GetFirstAnnot(), pAnnot);

    pAnnot = iter.GetLastAnnot();
    CheckRect(pAnnot->GetRect(), RightBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), RightTop);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    CheckRect(pAnnot->GetRect(), LeftBottom);
    pAnnot = iter.GetPrevAnnot(pAnnot);
    EXPECT_EQ(iter.GetLastAnnot(), pAnnot);
  }
}
Esempio n. 7
0
void
BListView::KeyDown(const char* bytes, int32 numBytes)
{
    bool extend = fListType == B_MULTIPLE_SELECTION_LIST
                  && (modifiers() & B_SHIFT_KEY) != 0;

    if (fFirstSelected == -1
            && (bytes[0] == B_UP_ARROW || bytes[0] == B_DOWN_ARROW)) {
        // nothing is selected yet, select the first enabled item
        int32 lastItem = CountItems() - 1;
        for (int32 i = 0; i <= lastItem; i++) {
            if (ItemAt(i)->IsEnabled()) {
                Select(i);
                break;
            }
        }
        return;
    }

    switch (bytes[0]) {
    case B_UP_ARROW:
    {
        if (fAnchorIndex > 0) {
            if (!extend || fAnchorIndex <= fFirstSelected) {
                for (int32 i = 1; fAnchorIndex - i >= 0; i++) {
                    if (ItemAt(fAnchorIndex - i)->IsEnabled()) {
                        // Select the previous enabled item
                        Select(fAnchorIndex - i, extend);
                        break;
                    }
                }
            } else {
                Deselect(fAnchorIndex);
                do
                    fAnchorIndex--;
                while (fAnchorIndex > 0
                        && !ItemAt(fAnchorIndex)->IsEnabled());
            }
        }

        ScrollToSelection();
        break;
    }

    case B_DOWN_ARROW:
    {
        int32 lastItem = CountItems() - 1;
        if (fAnchorIndex < lastItem) {
            if (!extend || fAnchorIndex >= fLastSelected) {
                for (int32 i = 1; fAnchorIndex + i <= lastItem; i++) {
                    if (ItemAt(fAnchorIndex + i)->IsEnabled()) {
                        // Select the next enabled item
                        Select(fAnchorIndex + i, extend);
                        break;
                    }
                }
            } else {
                Deselect(fAnchorIndex);
                do
                    fAnchorIndex++;
                while (fAnchorIndex < lastItem
                        && !ItemAt(fAnchorIndex)->IsEnabled());
            }
        }

        ScrollToSelection();
        break;
    }

    case B_HOME:
        if (extend) {
            Select(0, fAnchorIndex, true);
            fAnchorIndex = 0;
        } else {
            // select the first enabled item
            int32 lastItem = CountItems() - 1;
            for (int32 i = 0; i <= lastItem; i++) {
                if (ItemAt(i)->IsEnabled()) {
                    Select(i, false);
                    break;
                }
            }
        }

        ScrollToSelection();
        break;

    case B_END:
        if (extend) {
            Select(fAnchorIndex, CountItems() - 1, true);
            fAnchorIndex = CountItems() - 1;
        } else {
            // select the last enabled item
            for (int32 i = CountItems() - 1; i >= 0; i--) {
                if (ItemAt(i)->IsEnabled()) {
                    Select(i, false);
                    break;
                }
            }
        }

        ScrollToSelection();
        break;

    case B_PAGE_UP:
    {
        BPoint scrollOffset(LeftTop());
        scrollOffset.y = std::max(0.0f, scrollOffset.y - Bounds().Height());
        ScrollTo(scrollOffset);
        break;
    }

    case B_PAGE_DOWN:
    {
        BPoint scrollOffset(LeftTop());
        if (BListItem* item = LastItem()) {
            scrollOffset.y += Bounds().Height();
            scrollOffset.y = std::min(item->Bottom() - Bounds().Height(),
                                      scrollOffset.y);
        }
        ScrollTo(scrollOffset);
        break;
    }

    case B_RETURN:
    case B_SPACE:
        Invoke();
        break;

    default:
        BView::KeyDown(bytes, numBytes);
    }
}