/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if 0 # define FIXME_SELF_INTERSECTING_WORKING #endif using namespace css; class DemoBase : public WorkWindow // hide OutputDevice if necessary { public: DemoBase() : WorkWindow( NULL, WB_APP | WB_STDWORK) { } OutputDevice &getOutDev() { return *this; } }; enum RenderStyle { RENDER_THUMB, // small view to a page RENDER_EXPANDED, // expanded view of this renderer }; class DemoWin : public DemoBase { Bitmap maIntroBW; BitmapEx maIntro; int mnSegmentsX; int mnSegmentsY; struct RenderContext { RenderStyle meStyle; bool mbVDev; DemoWin *mpDemoWin; }; struct RegionRenderer { public: virtual ~RegionRenderer() {} virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &rCtx) = 0; }; std::vector< RegionRenderer * > maRenderers; sal_Int32 mnSelectedRenderer; void InitRenderers(); public: DemoWin() : DemoBase() , mnSegmentsX(4) , mnSegmentsY(3) , mnSelectedRenderer(-1) , mpButton(NULL) , mpButtonWin(NULL) { if (!Application::LoadBrandBitmap("intro", maIntro)) Application::Abort("Failed to load intro image"); maIntroBW = maIntro.GetBitmap(); maIntroBW.Filter( BMP_FILTER_EMBOSS_GREY ); InitRenderers(); } // Bouncing windows on click ... PushButton *mpButton; FloatingWindow *mpButtonWin; AutoTimer maBounce; int mnBounceX, mnBounceY; DECL_LINK(BounceTimerCb, void *); virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE; virtual void Paint( const Rectangle& rRect ) SAL_OVERRIDE { fprintf(stderr, "DemoWin::Paint(%ld,%ld,%ld,%ld)\n", rRect.getX(), rRect.getY(), rRect.getWidth(), rRect.getHeight()); drawToDevice(getOutDev(), false); } static std::vector partition(OutputDevice &rDev, int nX, int nY) { Rectangle r; std::vector aRegions; // Make small cleared area for these guys Size aSize(rDev.GetOutputSizePixel()); long nBorderSize = aSize.Width() / 32; long nBoxWidth = (aSize.Width() - nBorderSize*(nX+1)) / nX; long nBoxHeight = (aSize.Height() - nBorderSize*(nY+1)) / nY; for (int y = 0; y < nY; y++ ) { for (int x = 0; x < nX; x++ ) { r.SetPos(Point(nBorderSize + (nBorderSize + nBoxWidth) * x, nBorderSize + (nBorderSize + nBoxHeight) * y)); r.SetSize(Size(nBoxWidth, nBoxHeight)); aRegions.push_back(r); } } return aRegions; } static void clearRects(OutputDevice &rDev, std::vector &rRects) { for (size_t i = 0; i < rRects.size(); i++) { // knock up a nice little border rDev.SetLineColor(COL_GRAY); rDev.SetFillColor(COL_LIGHTGRAY); if (i % 2) { int nBorderSize = rRects[i].GetWidth() / 5; rDev.DrawRect(rRects[i], nBorderSize, nBorderSize); } else rDev.DrawRect(rRects[i]); } } void drawBackground(OutputDevice &rDev, Rectangle r) { Gradient aGradient; aGradient.SetStartColor(COL_BLUE); aGradient.SetEndColor(COL_GREEN); aGradient.SetStyle(GradientStyle_LINEAR); rDev.DrawGradient(r, aGradient); } struct DrawRadialLines : public RegionRenderer { virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &) SAL_OVERRIDE { rDev.SetFillColor(Color(COL_LIGHTRED)); rDev.SetLineColor(Color(COL_BLACK)); rDev.DrawRect( r ); for(int i=0; i aRegions(DemoWin::partition(rDev, 2, 2)); for (size_t i = 0; i < aRegions.size(); i++) { vcl::Region aRegion; Rectangle aSub(aRegions[i]); Rectangle aSmaller(aSub); aSmaller.Move(10,10); aSmaller.setWidth(aSmaller.getWidth()-20); aSmaller.setHeight(aSmaller.getHeight()-24); switch (i) { case 0: aRegion = vcl::Region(aSub); break; case 1: aRegion = vcl::Region(aSmaller); aRegion.XOr(aSub); break; case 2: { Polygon aPoly(aSub); aPoly.Rotate(aSub.Center(), 450); aPoly.Clip(aSmaller); aRegion = vcl::Region(aPoly); break; } case 3: { tools::PolyPolygon aPolyPoly; sal_Int32 nTW = aSub.GetWidth()/6; sal_Int32 nTH = aSub.GetHeight()/6; Rectangle aTiny(Point(4, 4), Size(nTW*2, nTH*2)); aPolyPoly.Insert(Polygon(aTiny)); aTiny.Move(nTW*3, nTH*3); aPolyPoly.Insert(Polygon(aTiny)); aTiny.Move(nTW, nTH); aPolyPoly.Insert(Polygon(aTiny)); aRegion = vcl::Region(aPolyPoly); break; } } // switch rDev.SetClipRegion(aRegion); rDev.DrawCheckered(aSub.TopLeft(), aSub.GetSize()); rDev.SetClipRegion(); } } else { rDev.DrawCheckered(r.TopLeft(), r.GetSize()); } } }; struct DrawPoly : public RegionRenderer { DrawCheckered maCheckered; virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &rCtx) SAL_OVERRIDE { maCheckered.RenderRegion(rDev, r, rCtx); long nDx = r.GetWidth()/20; long nDy = r.GetHeight()/20; Rectangle aShrunk(r); aShrunk.Move(nDx, nDy); aShrunk.SetSize(Size(r.GetWidth()-nDx*2, r.GetHeight()-nDy*2)); Polygon aPoly(aShrunk); tools::PolyPolygon aPPoly(aPoly); rDev.SetLineColor(Color(COL_RED)); rDev.SetFillColor(Color(COL_RED)); // This hits the optional 'drawPolyPolygon' code-path rDev.DrawTransparent(aPPoly, 64); } }; struct DrawEllipse : public RegionRenderer { virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &) SAL_OVERRIDE { rDev.SetLineColor(Color(COL_RED)); rDev.SetFillColor(Color(COL_GREEN)); rDev.DrawEllipse(r); } }; struct DrawGradient : public RegionRenderer { virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &rCtx) SAL_OVERRIDE { if (rCtx.meStyle == RENDER_EXPANDED) { std::vector aRegions(DemoWin::partition(rDev, 5, 4)); sal_uInt32 nStartCols[] = { COL_RED, COL_RED, COL_RED, COL_GREEN, COL_GREEN, COL_BLUE, COL_BLUE, COL_BLUE, COL_CYAN, COL_CYAN, COL_GRAY, COL_GRAY, COL_LIGHTGRAY, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_WHITE, COL_WHITE, COL_BLACK, COL_BLACK }; sal_uInt32 nEndCols[] = { COL_WHITE, COL_WHITE, COL_BLACK, COL_BLACK, COL_RED, COL_RED, COL_RED, COL_GREEN, COL_GREEN, COL_GRAY, COL_GRAY, COL_LIGHTGRAY, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_BLUE, COL_BLUE, COL_BLUE, COL_CYAN, COL_CYAN }; GradientStyle eStyles[] = { GradientStyle_LINEAR, GradientStyle_AXIAL, GradientStyle_RADIAL, GradientStyle_ELLIPTICAL, GradientStyle_SQUARE, GradientStyle_RECT, GradientStyle_FORCE_EQUAL_SIZE, GradientStyle_LINEAR, GradientStyle_RADIAL, GradientStyle_LINEAR, GradientStyle_AXIAL, GradientStyle_RADIAL, GradientStyle_ELLIPTICAL, GradientStyle_SQUARE, GradientStyle_RECT, GradientStyle_FORCE_EQUAL_SIZE, GradientStyle_LINEAR, GradientStyle_RADIAL }; sal_uInt16 nAngles[] = { 0, 0, 0, 0, 0, 15, 30, 45, 60, 75, 90, 120, 135, 160, 180, 0, 0, 0, 0, 0 }; sal_uInt16 nBorders[] = { 0, 0, 0, 0, 0, 1, 10, 100, 10, 1, 0, 0, 0, 0, 0, 1, 10, 20, 10, 1, 0, 0, 0, 0, 0 }; DemoWin::clearRects(rDev, aRegions); assert(aRegions.size() <= SAL_N_ELEMENTS(nStartCols)); assert(aRegions.size() <= SAL_N_ELEMENTS(nEndCols)); assert(aRegions.size() <= SAL_N_ELEMENTS(eStyles)); assert(aRegions.size() <= SAL_N_ELEMENTS(nAngles)); assert(aRegions.size() <= SAL_N_ELEMENTS(nBorders)); for (size_t i = 0; i < aRegions.size(); i++) { Rectangle aSub = aRegions[i]; Gradient aGradient; aGradient.SetStartColor(Color(nStartCols[i])); aGradient.SetEndColor(Color(nEndCols[i])); aGradient.SetStyle(eStyles[i]); aGradient.SetAngle(nAngles[i]); aGradient.SetBorder(nBorders[i]); rDev.DrawGradient(aSub, aGradient); } } else { Gradient aGradient; aGradient.SetStartColor(COL_YELLOW); aGradient.SetEndColor(COL_RED); // aGradient.SetAngle(45); aGradient.SetStyle(GradientStyle_RECT); aGradient.SetBorder(r.GetSize().Width()/20); rDev.DrawGradient(r, aGradient); } } }; struct DrawBitmap : public RegionRenderer { virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &rCtx) SAL_OVERRIDE { Bitmap aBitmap(rCtx.mpDemoWin->maIntroBW); aBitmap.Scale(r.GetSize(), BMP_SCALE_BESTQUALITY); rDev.DrawBitmap(r.TopLeft(), aBitmap); } }; struct DrawBitmapEx : public RegionRenderer { DrawCheckered maCheckered; virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &rCtx) SAL_OVERRIDE { maCheckered.RenderRegion(rDev, r, rCtx); BitmapEx aBitmap(rCtx.mpDemoWin->maIntro); aBitmap.Scale(r.GetSize(), BMP_SCALE_BESTQUALITY); AlphaMask aSemiTransp(aBitmap.GetSizePixel()); aSemiTransp.Erase(64); rDev.DrawBitmapEx(r.TopLeft(), BitmapEx(aBitmap.GetBitmap(), aSemiTransp)); } }; struct DrawPolyPolygons : public RegionRenderer { virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &) SAL_OVERRIDE { struct { double nX, nY; } aPoints[] = { { 0.1, 0.1 }, { 0.9, 0.9 }, #ifdef FIXME_SELF_INTERSECTING_WORKING { 0.9, 0.1 }, { 0.1, 0.9 }, { 0.1, 0.1 } #else { 0.1, 0.9 }, { 0.5, 0.5 }, { 0.9, 0.1 }, { 0.1, 0.1 } #endif }; tools::PolyPolygon aPolyPoly; // Render 4x polygons & aggregate into another PolyPolygon for (int x = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { Rectangle aSubRect(r); aSubRect.Move(x * r.GetWidth()/3, y * r.GetHeight()/3); aSubRect.SetSize(Size(r.GetWidth()/2, r.GetHeight()/4)); Polygon aPoly(SAL_N_ELEMENTS(aPoints)); for (size_t v = 0; v < SAL_N_ELEMENTS(aPoints); v++) { aPoly.SetPoint(Point(aSubRect.Left() + aSubRect.GetWidth() * aPoints[v].nX, aSubRect.Top() + aSubRect.GetHeight() * aPoints[v].nY), v); } rDev.SetLineColor(Color(COL_YELLOW)); rDev.SetFillColor(Color(COL_BLACK)); rDev.DrawPolygon(aPoly); // now move and add to the polypolygon aPoly.Move(0, r.GetHeight()/2); aPolyPoly.Insert(aPoly); } } rDev.SetLineColor(Color(COL_LIGHTRED)); rDev.SetFillColor(Color(COL_GREEN)); rDev.DrawTransparent(aPolyPoly, 50); } }; struct DrawToVirtualDevice : public RegionRenderer { virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &rCtx) SAL_OVERRIDE { // avoid infinite recursion if (rCtx.mbVDev) return; VirtualDevice aNested(rDev); aNested.SetOutputSizePixel(r.GetSize()); Rectangle aWhole(Point(0,0), r.GetSize()); // mini me rCtx.mpDemoWin->drawToDevice(aNested, true); Bitmap aBitmap(aNested.GetBitmap(Point(0,0),aWhole.GetSize())); rDev.DrawBitmap(r.TopLeft(), aBitmap); } }; struct DrawIcons : public RegionRenderer { std::vector maIcons; DrawIcons() { const char *pNames[] = { "cmd/lc_openurl.png", "cmd/lc_newdoc.png", "cmd/lc_save.png", "cmd/lc_saveas.png", "cmd/lc_sendmail.png", "cmd/lc_editdoc.png", "cmd/lc_print.png", "cmd/lc_printpreview.png", "cmd/lc_cut.png", "cmd/lc_copy.png", "cmd/lc_paste.png", "cmd/lc_formatpaintbrush.png", "cmd/lc_undo.png", "cmd/lc_redo.png", }; for (size_t i = 0; i < SAL_N_ELEMENTS(pNames); i++) maIcons.push_back(BitmapEx(OUString::createFromAscii(pNames[i]))); } virtual void RenderRegion(OutputDevice &rDev, Rectangle r, const RenderContext &) SAL_OVERRIDE { Rectangle p(r); for (size_t i = 0; i < maIcons.size(); i++) { Size aSize(maIcons[i].GetSizePixel()); rDev.DrawBitmapEx(p.TopLeft(), maIcons[i]); p.Move(aSize.Width(), 0); if (p.Left() >= r.Right()) break; } } }; void drawToDevice(OutputDevice &rDev, bool bVdev) { RenderContext aCtx; aCtx.mbVDev = bVdev; aCtx.mpDemoWin = this; Rectangle aWholeWin(Point(0,0), rDev.GetOutputSizePixel()); drawBackground(rDev, aWholeWin); if (mnSelectedRenderer >= 0) { aCtx.meStyle = RENDER_EXPANDED; maRenderers[mnSelectedRenderer]->RenderRegion(rDev, aWholeWin, aCtx); } else { aCtx.meStyle = RENDER_THUMB; std::vector aRegions(DemoWin::partition(rDev, mnSegmentsX, mnSegmentsY)); DemoWin::clearRects(rDev, aRegions); for (size_t i = 0; i < maRenderers.size(); i++) maRenderers[i]->RenderRegion(rDev, aRegions[i], aCtx); } } }; IMPL_LINK_NOARG(DemoWin,BounceTimerCb) { mpButton->Check(mnBounceX>0); mpButton->SetPressed(mnBounceY>0); Point aCur = mpButtonWin->GetPosPixel(); static const int nMovePix = 10; aCur.Move(mnBounceX * nMovePix, mnBounceX * nMovePix); Size aWinSize = GetSizePixel(); if (aCur.X() <= 0 || aCur.X() >= aWinSize.Width()) mnBounceX *= -1; if (aCur.Y() <= 0 || aCur.Y() >= aWinSize.Height()) mnBounceX *= -1; mpButtonWin->SetPosPixel(aCur); // All smoke and mirrors to test sub-region invalidation underneath Rectangle aRect(aCur, mpButtonWin->GetSizePixel()); Invalidate(aRect); return 0; } void DemoWin::MouseButtonDown( const MouseEvent& rMEvt ) { // click to zoom out if (mnSelectedRenderer >= 0) { mnSelectedRenderer = -1; Invalidate(); return; } // click on a region to zoom into it std::vector aRegions(partition(*this, mnSegmentsX, mnSegmentsY)); for (size_t i = 0; i < aRegions.size(); i++) { if (aRegions[i].IsInside(rMEvt.GetPosPixel())) { mnSelectedRenderer = i; Invalidate(); return; } } // otherwise bounce floating windows if (!mpButton) { mpButtonWin = new FloatingWindow(this); mpButton = new PushButton(mpButtonWin); mpButton->SetSymbol(SymbolType::HELP); mpButton->SetText("PushButton demo"); mpButton->SetPosSizePixel(Point(0,0), mpButton->GetOptimalSize()); mpButton->Show(); mpButtonWin->SetPosSizePixel(Point(0,0), mpButton->GetOptimalSize()); mpButtonWin->Show(); mnBounceX = 1; mnBounceX = 1; maBounce.SetTimeoutHdl(LINK(this,DemoWin,BounceTimerCb)); maBounce.SetTimeout(55); maBounce.Start(); } else { maBounce.Stop(); delete mpButtonWin; mpButtonWin = NULL; mpButton = NULL; } } void DemoWin::InitRenderers() { maRenderers.push_back(new DrawRadialLines()); maRenderers.push_back(new DrawText()); maRenderers.push_back(new DrawPoly()); maRenderers.push_back(new DrawEllipse()); maRenderers.push_back(new DrawCheckered()); maRenderers.push_back(new DrawBitmapEx()); maRenderers.push_back(new DrawBitmap()); maRenderers.push_back(new DrawGradient()); maRenderers.push_back(new DrawPolyPolygons()); maRenderers.push_back(new DrawToVirtualDevice()); maRenderers.push_back(new DrawIcons()); maRenderers.push_back(new DrawBitmap()); } class DemoApp : public Application { public: DemoApp() {} virtual int Main() SAL_OVERRIDE { DemoWin aMainWin; aMainWin.SetText( "Interactive VCL demo" ); aMainWin.Show(); Application::Execute(); return 0; } protected: uno::Reference xMSF; void Init() SAL_OVERRIDE { try { uno::Reference xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext(); xMSF = uno::Reference ( xComponentContext->getServiceManager(), uno::UNO_QUERY ); if( !xMSF.is() ) Application::Abort("Bootstrap failure - no service manager"); ::comphelper::setProcessServiceFactory( xMSF ); } catch (const uno::Exception &e) { Application::Abort("Bootstrap exception " + e.Message); } } void DeInit() SAL_OVERRIDE { uno::Reference< lang::XComponent >( comphelper::getProcessComponentContext(), uno::UNO_QUERY_THROW )-> dispose(); ::comphelper::setProcessServiceFactory( NULL ); } }; void vclmain::createApplication() { static DemoApp aApp; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */