LCOV - code coverage report
Current view: top level - sw/source/uibase/misc - swruler.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 75 139 54.0 %
Date: 2015-06-13 12:38:46 Functions: 12 18 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : // FIX fdo#38246 https://bugs.libreoffice.org/show_bug.cgi?id=38246
      11             : // Design proposal: https://wiki.documentfoundation.org/Design/Whiteboards/Comments_Ruler_Control
      12             : // TODO Alpha blend border when it doesn't fit in window
      13             : 
      14             : #include "swruler.hxx"
      15             : 
      16             : #include "viewsh.hxx"
      17             : #include "edtwin.hxx"
      18             : #include "PostItMgr.hxx"
      19             : #include "viewopt.hxx"
      20             : #include <view.hxx>
      21             : #include "cmdid.h"
      22             : #include <sfx2/request.hxx>
      23             : #include <vcl/svapp.hxx>
      24             : #include <vcl/window.hxx>
      25             : #include <vcl/settings.hxx>
      26             : #include "misc.hrc"
      27             : 
      28             : #define CONTROL_BORDER_WIDTH    1
      29             : 
      30             : #define CONTROL_LEFT_OFFSET     6
      31             : #define CONTROL_RIGHT_OFFSET    3
      32             : #define CONTROL_TOP_OFFSET      4
      33             : 
      34             : #define CONTROL_TRIANGLE_WIDTH  4
      35             : #define CONTROL_TRIANGLE_PAD    3
      36             : 
      37             : namespace {
      38             : 
      39             : /**
      40             :  * Draw a little horizontal arrow tip on VirtualDevice.
      41             :  * \param nX left coordinate of arrow
      42             :  * \param nY top coordinate of arrow
      43             :  * \param Color arrow color
      44             :  * \param bPointRight if arrow should point to right. Otherwise, it will point left.
      45             :  */
      46         195 : void ImplDrawArrow(vcl::RenderContext& rRenderContext, long nX, long nY, const Color& rColor, bool bPointRight)
      47             : {
      48         195 :     rRenderContext.SetLineColor();
      49         195 :     rRenderContext.SetFillColor(rColor);
      50         195 :     if (bPointRight)
      51             :     {
      52           0 :         rRenderContext.DrawRect(Rectangle(nX + 0, nY + 0, nX + 0, nY + 6) );
      53           0 :         rRenderContext.DrawRect(Rectangle(nX + 1, nY + 1, nX + 1, nY + 5) );
      54           0 :         rRenderContext.DrawRect(Rectangle(nX + 2, nY + 2, nX + 2, nY + 4) );
      55           0 :         rRenderContext.DrawRect(Rectangle(nX + 3, nY + 3, nX + 3, nY + 3) );
      56             :     }
      57             :     else
      58             :     {
      59         195 :         rRenderContext.DrawRect(Rectangle(nX + 0, nY + 3, nX + 0, nY + 3));
      60         195 :         rRenderContext.DrawRect(Rectangle(nX + 1, nY + 2, nX + 1, nY + 4));
      61         195 :         rRenderContext.DrawRect(Rectangle(nX + 2, nY + 1, nX + 2, nY + 5));
      62         195 :         rRenderContext.DrawRect(Rectangle(nX + 3, nY + 0, nX + 3, nY + 6));
      63             :     }
      64         195 : }
      65             : 
      66             : }
      67             : 
      68             : // Constructor
      69        2761 : SwCommentRuler::SwCommentRuler( SwViewShell* pViewSh, vcl::Window* pParent, SwEditWin* pWin, SvxRulerSupportFlags nRulerFlags,  SfxBindings& rBindings, WinBits nWinStyle)
      70             : : SvxRuler(pParent, pWin, nRulerFlags, rBindings, nWinStyle | WB_HSCROLL)
      71             : , mpViewShell(pViewSh)
      72             : , mpSwWin(pWin)
      73             : , mbIsHighlighted(false)
      74             : , mnFadeRate(0)
      75        2761 : , maVirDev( VclPtr<VirtualDevice>::Create(*this) )
      76             : {
      77             :     // Set fading timeout: 5 x 40ms = 200ms
      78        2761 :     maFadeTimer.SetTimeout(40);
      79        2761 :     maFadeTimer.SetTimeoutHdl( LINK( this, SwCommentRuler, FadeHandler ) );
      80        2761 : }
      81             : 
      82             : // Destructor
      83        8271 : SwCommentRuler::~SwCommentRuler()
      84             : {
      85        2757 :     disposeOnce();
      86        5514 : }
      87             : 
      88        2757 : void SwCommentRuler::dispose()
      89             : {
      90        2757 :     mpSwWin.clear();
      91        2757 :     SvxRuler::dispose();
      92        2757 : }
      93             : 
      94       10575 : void SwCommentRuler::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
      95             : {
      96       10575 :     SvxRuler::Paint(rRenderContext, rRect);
      97             : 
      98             :     // Don't draw if there is not any note
      99       10575 :     if (mpViewShell->GetPostItMgr() && mpViewShell->GetPostItMgr()->HasNotes())
     100         195 :         DrawCommentControl(rRenderContext);
     101       10575 : }
     102             : 
     103         195 : void SwCommentRuler::DrawCommentControl(vcl::RenderContext& rRenderContext)
     104             : {
     105         195 :     const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
     106         195 :     bool bIsCollapsed = ! mpViewShell->GetPostItMgr()->ShowNotes();
     107             : 
     108         195 :     Rectangle aControlRect = GetCommentControlRegion();
     109         195 :     maVirDev->SetOutputSizePixel(aControlRect.GetSize());
     110             : 
     111             :     // Paint comment control background
     112             :     // TODO Check if these are best colors to be used
     113         195 :     Color aBgColor = GetFadedColor( rStyleSettings.GetDarkShadowColor(), rStyleSettings.GetWorkspaceColor() );
     114         195 :     maVirDev->SetFillColor( aBgColor );
     115             : 
     116         195 :     if ( mbIsHighlighted || !bIsCollapsed )
     117             :     {
     118             :         // Draw borders
     119         195 :         maVirDev->SetLineColor( rStyleSettings.GetShadowColor() );
     120             :     }
     121             :     else
     122             :     {
     123             :         // No borders
     124           0 :         maVirDev->SetLineColor();
     125             :     }
     126             : 
     127         195 :     maVirDev->DrawRect( Rectangle( Point(), aControlRect.GetSize() ) );
     128             : 
     129             :     // Label and arrow tip
     130         195 :     OUString aLabel( SW_RESSTR ( STR_COMMENTS_LABEL ) );
     131             :     // Get label and arrow coordinates
     132         195 :     Point aLabelPos;
     133         195 :     Point aArrowPos;
     134             :     bool  bArrowToRight;
     135             :     // TODO Discover why it should be 0 instead of CONTROL_BORDER_WIDTH + CONTROL_TOP_OFFSET
     136         195 :     aLabelPos.Y() = 0;
     137         195 :     aArrowPos.Y() = CONTROL_BORDER_WIDTH + CONTROL_TOP_OFFSET;
     138         195 :     if ( !AllSettings::GetLayoutRTL() )
     139             :     {
     140             :         // LTR
     141         195 :         if ( bIsCollapsed )
     142             :         {
     143             :             // It should draw something like | > Comments  |
     144           0 :             aLabelPos.X() = CONTROL_LEFT_OFFSET + CONTROL_TRIANGLE_WIDTH + CONTROL_TRIANGLE_PAD;
     145           0 :             aArrowPos.X() = CONTROL_LEFT_OFFSET;
     146             :         }
     147             :         else
     148             :         {
     149             :             // It should draw something like | Comments  < |
     150         195 :             aLabelPos.X() = CONTROL_LEFT_OFFSET;
     151         195 :             aArrowPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - CONTROL_TRIANGLE_WIDTH;
     152             :         }
     153         195 :         bArrowToRight = bIsCollapsed;
     154             :     }
     155             :     else
     156             :     {
     157             :         // RTL
     158           0 :         long nLabelWidth = GetTextWidth( aLabel );
     159           0 :         if ( bIsCollapsed )
     160             :         {
     161             :             // It should draw something like |  Comments < |
     162           0 :             aArrowPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - CONTROL_TRIANGLE_WIDTH;
     163           0 :             aLabelPos.X() = aArrowPos.X() - CONTROL_TRIANGLE_PAD - nLabelWidth;
     164             :         }
     165             :         else
     166             :         {
     167             :             // It should draw something like | >  Comments |
     168           0 :             aLabelPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - nLabelWidth;
     169           0 :             aArrowPos.X() = CONTROL_LEFT_OFFSET;
     170             :         }
     171           0 :         bArrowToRight = !bIsCollapsed;
     172             :     }
     173             : 
     174             :     // Draw label
     175         195 :     Color aTextColor = GetFadedColor( rStyleSettings.GetButtonTextColor(), rStyleSettings.GetDarkShadowColor() );
     176         195 :     maVirDev->SetTextColor( aTextColor );
     177             :     // FIXME Expected font size?
     178         195 :     maVirDev->DrawText( aLabelPos, aLabel );
     179             : 
     180             :     // Draw arrow
     181             :     // FIXME consistence of button colors. http://opengrok.libreoffice.org/xref/core/vcl/source/control/button.cxx#785
     182         195 :     Color aArrowColor = GetFadedColor(Color(COL_BLACK), rStyleSettings.GetShadowColor());
     183         195 :     ImplDrawArrow(*maVirDev.get(), aArrowPos.X(), aArrowPos.Y(), aArrowColor, bArrowToRight);
     184             : 
     185             :     // Blit comment control
     186         195 :     rRenderContext.DrawOutDev(aControlRect.TopLeft(), aControlRect.GetSize(), Point(), aControlRect.GetSize(), *maVirDev.get());
     187         195 : }
     188             : 
     189             : // Just accept double-click outside comment control
     190           0 : void SwCommentRuler::Command( const CommandEvent& rCEvt )
     191             : {
     192           0 :     Point aMousePos = rCEvt.GetMousePosPixel();
     193             :     // Ignore command request if it is inside Comment Control
     194           0 :     if ( !mpViewShell->GetPostItMgr()
     195           0 :           || !mpViewShell->GetPostItMgr()->HasNotes()
     196           0 :           || !GetCommentControlRegion().IsInside( aMousePos ) )
     197           0 :         SvxRuler::Command( rCEvt );
     198           0 : }
     199             : 
     200           0 : void SwCommentRuler::MouseMove(const MouseEvent& rMEvt)
     201             : {
     202           0 :     SvxRuler::MouseMove(rMEvt);
     203           0 :     if ( ! mpViewShell->GetPostItMgr() || ! mpViewShell->GetPostItMgr()->HasNotes() )
     204           0 :         return;
     205             : 
     206           0 :     Point aMousePos = rMEvt.GetPosPixel();
     207           0 :     bool  bWasHighlighted = mbIsHighlighted;
     208           0 :     mbIsHighlighted = GetCommentControlRegion().IsInside( aMousePos );
     209           0 :     if ( mbIsHighlighted != bWasHighlighted )
     210             :     {
     211             :         // Set proper help text
     212           0 :         if ( mbIsHighlighted )
     213             :         {
     214             :             // Mouse over comment control
     215           0 :             UpdateCommentHelpText();
     216             :         }
     217             :         else
     218             :         {
     219             :             // Mouse out of comment control
     220             :             // FIXME Should remember previous tooltip text?
     221           0 :             SetQuickHelpText( OUString() );
     222             :         }
     223             :         // Do start fading
     224           0 :         maFadeTimer.Start();
     225             :     }
     226             : }
     227             : 
     228           0 : void SwCommentRuler::MouseButtonDown( const MouseEvent& rMEvt )
     229             : {
     230           0 :     Point   aMousePos = rMEvt.GetPosPixel();
     231           0 :     if ( !rMEvt.IsLeft() || IsTracking() || !GetCommentControlRegion().IsInside( aMousePos ) )
     232             :     {
     233           0 :         SvxRuler::MouseButtonDown(rMEvt);
     234           0 :         return;
     235             :     }
     236             : 
     237             :     // Toggle notes visibility
     238           0 :     SwView &rView = mpSwWin->GetView();
     239           0 :     SfxRequest aRequest( rView.GetViewFrame(), FN_VIEW_NOTES );
     240           0 :     rView.ExecViewOptions( aRequest );
     241             : 
     242             :     // It is inside comment control, so update help text
     243           0 :     UpdateCommentHelpText();
     244             : 
     245           0 :     Invalidate();
     246             : }
     247             : 
     248       27860 : void SwCommentRuler::Update()
     249             : {
     250       27860 :     Rectangle aPreviousControlRect = GetCommentControlRegion();
     251       27860 :     SvxRuler::Update();
     252       27860 :     if (aPreviousControlRect != GetCommentControlRegion())
     253         292 :         Invalidate();
     254       27860 : }
     255             : 
     256           0 : void SwCommentRuler::UpdateCommentHelpText()
     257             : {
     258             :     int nTooltipResId;
     259           0 :     if ( mpViewShell->GetPostItMgr()->ShowNotes() )
     260           0 :         nTooltipResId = STR_HIDE_COMMENTS;
     261             :     else
     262           0 :         nTooltipResId = STR_SHOW_COMMENTS;
     263           0 :     SetQuickHelpText( OUString( SW_RESSTR( nTooltipResId ) ) );
     264           0 : }
     265             : 
     266             : // TODO Make Ruler return its central rectangle instead of margins.
     267       55915 : Rectangle SwCommentRuler::GetCommentControlRegion()
     268             : {
     269       55915 :     long nLeft = 0;
     270       55915 :     SwPostItMgr *pPostItMgr = mpViewShell->GetPostItMgr();
     271             : 
     272             :     //rhbz#1006850 When the SwPostItMgr ctor is called from SwView::SwView it
     273             :     //triggers an update of the uiview, but the result of the ctor hasn't been
     274             :     //set into the mpViewShell yet, so GetPostItMgr is temporarily still NULL
     275       55915 :     if (!pPostItMgr)
     276           0 :         return Rectangle();
     277             : 
     278       55915 :     unsigned long nSidebarWidth = pPostItMgr->GetSidebarWidth(true);
     279             :     //FIXME When the page width is larger then screen, the ruler is misplaced by one pixel
     280       55915 :     if (GetTextRTL())
     281           0 :        nLeft = GetPageOffset() - nSidebarWidth + GetBorderOffset();
     282             :     else
     283       55915 :        nLeft = GetWinOffset() + GetPageOffset() + mpSwWin->LogicToPixel(Size(GetPageWidth(), 0)).Width();
     284       55915 :     long nTop    = 0 + 4; // Ruler::ImplDraw uses RULER_OFF (value: 3px) as offset, and Ruler::ImplFormat adds one extra pixel
     285             :     // Somehow pPostItMgr->GetSidebarBorderWidth() returns border width already doubled
     286       55915 :     long nRight  = nLeft + nSidebarWidth + pPostItMgr->GetSidebarBorderWidth(true);
     287       55915 :     long nBottom = nTop + GetRulerVirHeight() - 3;
     288             : 
     289       55915 :     Rectangle aRect(nLeft, nTop, nRight, nBottom);
     290       55915 :     return aRect;
     291             : }
     292             : 
     293         585 : Color SwCommentRuler::GetFadedColor(const Color &rHighColor, const Color &rLowColor)
     294             : {
     295         585 :     if (!maFadeTimer.IsActive())
     296         585 :         return mbIsHighlighted ? rHighColor : rLowColor;
     297             : 
     298           0 :     Color aColor = rHighColor;
     299           0 :     aColor.Merge(rLowColor, mnFadeRate * 255 / 100.0f);
     300           0 :     return aColor;
     301             : }
     302             : 
     303           0 : IMPL_LINK_NOARG_TYPED(SwCommentRuler, FadeHandler, Timer *, void)
     304             : {
     305           0 :     const int nStep = 25;
     306           0 :     if ( mbIsHighlighted && mnFadeRate < 100 )
     307           0 :         mnFadeRate += nStep;
     308           0 :     else if ( !mbIsHighlighted && mnFadeRate > 0 )
     309           0 :         mnFadeRate -= nStep;
     310             :     else
     311           0 :         return;
     312             : 
     313           0 :     Invalidate();
     314             : 
     315           0 :     if ( mnFadeRate != 0 && mnFadeRate != 100)
     316           0 :         maFadeTimer.Start();
     317         177 : }
     318             : 
     319             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11