summaryrefslogtreecommitdiff
path: root/sw/source/uibase/misc/swruler.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/uibase/misc/swruler.cxx')
-rw-r--r--sw/source/uibase/misc/swruler.cxx302
1 files changed, 302 insertions, 0 deletions
diff --git a/sw/source/uibase/misc/swruler.cxx b/sw/source/uibase/misc/swruler.cxx
new file mode 100644
index 000000000000..1ba770fd6a42
--- /dev/null
+++ b/sw/source/uibase/misc/swruler.cxx
@@ -0,0 +1,302 @@
+/* -*- 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/.
+ */
+
+// FIX fdo#38246 https://bugs.libreoffice.org/show_bug.cgi?id=38246
+// Design proposal: https://wiki.documentfoundation.org/Design/Whiteboards/Comments_Ruler_Control
+// TODO Alpha blend border when it doesn't fit in window
+
+#include "swruler.hxx"
+
+#include "viewsh.hxx"
+#include "edtwin.hxx"
+#include "PostItMgr.hxx"
+#include "viewopt.hxx"
+#include <view.hxx>
+#include "cmdid.h"
+#include <sfx2/request.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/settings.hxx>
+#include "misc.hrc"
+
+#define CONTROL_BORDER_WIDTH 1
+
+#define CONTROL_LEFT_OFFSET 6
+#define CONTROL_RIGHT_OFFSET 3
+#define CONTROL_TOP_OFFSET 4
+
+#define CONTROL_TRIANGLE_WIDTH 4
+#define CONTROL_TRIANGLE_PAD 3
+
+// Constructor
+SwCommentRuler::SwCommentRuler( SwViewShell* pViewSh, Window* pParent, SwEditWin* pWin, sal_uInt16 nRulerFlags, SfxBindings& rBindings, WinBits nWinStyle)
+: SvxRuler(pParent, pWin, nRulerFlags, rBindings, nWinStyle | WB_HSCROLL)
+, mpViewShell(pViewSh)
+, mpSwWin(pWin)
+, mbIsHighlighted(false)
+, mnFadeRate(0)
+, maVirDev( *this )
+{
+ // Set fading timeout: 5 x 40ms = 200ms
+ maFadeTimer.SetTimeout(40);
+ maFadeTimer.SetTimeoutHdl( LINK( this, SwCommentRuler, FadeHandler ) );
+}
+
+// Destructor
+SwCommentRuler::~SwCommentRuler()
+{
+}
+
+void SwCommentRuler::Paint( const Rectangle& rRect )
+{
+ SvxRuler::Paint( rRect );
+ // Don't draw if there is not any note
+ if ( mpViewShell->GetPostItMgr()
+ && mpViewShell->GetPostItMgr()->HasNotes() )
+ DrawCommentControl();
+}
+
+void SwCommentRuler::DrawCommentControl()
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ bool bIsCollapsed = ! mpViewShell->GetPostItMgr()->ShowNotes();
+
+ Rectangle aControlRect = GetCommentControlRegion();
+ maVirDev.SetOutputSizePixel( aControlRect.GetSize() );
+
+ // Paint comment control background
+ // TODO Check if these are best colors to be used
+ Color aBgColor = GetFadedColor( rStyleSettings.GetDarkShadowColor(), rStyleSettings.GetWorkspaceColor() );
+ maVirDev.SetFillColor( aBgColor );
+
+ if ( mbIsHighlighted || !bIsCollapsed )
+ {
+ // Draw borders
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ }
+ else
+ {
+ // No borders
+ maVirDev.SetLineColor();
+ }
+
+ maVirDev.DrawRect( Rectangle( Point(), aControlRect.GetSize() ) );
+
+ // Label and arrow tip
+ OUString aLabel( SW_RESSTR ( STR_COMMENTS_LABEL ) );
+ // Get label and arrow coordinates
+ Point aLabelPos;
+ Point aArrowPos;
+ bool bArrowToRight;
+ // TODO Discover why it should be 0 instead of CONTROL_BORDER_WIDTH + CONTROL_TOP_OFFSET
+ aLabelPos.Y() = 0;
+ aArrowPos.Y() = CONTROL_BORDER_WIDTH + CONTROL_TOP_OFFSET;
+ if ( !Application::GetSettings().GetLayoutRTL() )
+ {
+ // LTR
+ if ( bIsCollapsed )
+ {
+ // It should draw something like | > Comments |
+ aLabelPos.X() = CONTROL_LEFT_OFFSET + CONTROL_TRIANGLE_WIDTH + CONTROL_TRIANGLE_PAD;
+ aArrowPos.X() = CONTROL_LEFT_OFFSET;
+ }
+ else
+ {
+ // It should draw something like | Comments < |
+ aLabelPos.X() = CONTROL_LEFT_OFFSET;
+ aArrowPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - CONTROL_TRIANGLE_WIDTH;
+ }
+ bArrowToRight = bIsCollapsed;
+ }
+ else
+ {
+ // RTL
+ long nLabelWidth = GetTextWidth( aLabel );
+ if ( bIsCollapsed )
+ {
+ // It should draw something like | Comments < |
+ aArrowPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - CONTROL_TRIANGLE_WIDTH;
+ aLabelPos.X() = aArrowPos.X() - CONTROL_TRIANGLE_PAD - nLabelWidth;
+ }
+ else
+ {
+ // It should draw something like | > Comments |
+ aLabelPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - nLabelWidth;
+ aArrowPos.X() = CONTROL_LEFT_OFFSET;
+ }
+ bArrowToRight = !bIsCollapsed;
+ }
+
+ // Draw label
+ Color aTextColor = GetFadedColor( rStyleSettings.GetButtonTextColor(), rStyleSettings.GetDarkShadowColor() );
+ maVirDev.SetTextColor( aTextColor );
+ // FIXME Expected font size?
+ maVirDev.DrawText( aLabelPos, aLabel );
+
+ // Draw arrow
+ // FIXME consistence of button colors. http://opengrok.libreoffice.org/xref/core/vcl/source/control/button.cxx#785
+ Color aArrowColor = GetFadedColor( Color( COL_BLACK ), rStyleSettings.GetShadowColor() );
+ ImplDrawArrow ( aArrowPos.X(), aArrowPos.Y(), aArrowColor, bArrowToRight );
+
+ // Blit comment control
+ DrawOutDev( aControlRect.TopLeft(), aControlRect.GetSize(), Point(), aControlRect.GetSize(), maVirDev );
+}
+
+void SwCommentRuler::ImplDrawArrow(long nX, long nY, const Color& rColor, bool bPointRight)
+{
+ maVirDev.SetLineColor();
+ maVirDev.SetFillColor( rColor );
+ if ( bPointRight )
+ {
+ maVirDev.DrawRect( Rectangle( nX+0, nY+0, nX+0, nY+6 ) );
+ maVirDev.DrawRect( Rectangle( nX+1, nY+1, nX+1, nY+5 ) );
+ maVirDev.DrawRect( Rectangle( nX+2, nY+2, nX+2, nY+4 ) );
+ maVirDev.DrawRect( Rectangle( nX+3, nY+3, nX+3, nY+3 ) );
+ }
+ else
+ {
+ maVirDev.DrawRect( Rectangle( nX+0, nY+3, nX+0, nY+3 ) );
+ maVirDev.DrawRect( Rectangle( nX+1, nY+2, nX+1, nY+4 ) );
+ maVirDev.DrawRect( Rectangle( nX+2, nY+1, nX+2, nY+5 ) );
+ maVirDev.DrawRect( Rectangle( nX+3, nY+0, nX+3, nY+6 ) );
+ }
+}
+
+// Just accept double-click outside comment control
+void SwCommentRuler::Command( const CommandEvent& rCEvt )
+{
+ Point aMousePos = rCEvt.GetMousePosPixel();
+ // Ignore command request if it is inside Comment Control
+ if ( !mpViewShell->GetPostItMgr()
+ || !mpViewShell->GetPostItMgr()->HasNotes()
+ || !GetCommentControlRegion().IsInside( aMousePos ) )
+ SvxRuler::Command( rCEvt );
+}
+
+void SwCommentRuler::MouseMove(const MouseEvent& rMEvt)
+{
+ SvxRuler::MouseMove(rMEvt);
+ if ( ! mpViewShell->GetPostItMgr() || ! mpViewShell->GetPostItMgr()->HasNotes() )
+ return;
+
+ Point aMousePos = rMEvt.GetPosPixel();
+ bool bWasHighlighted = mbIsHighlighted;
+ mbIsHighlighted = GetCommentControlRegion().IsInside( aMousePos );
+ if ( mbIsHighlighted != bWasHighlighted )
+ {
+ // Set proper help text
+ if ( mbIsHighlighted )
+ {
+ // Mouse over comment control
+ UpdateCommentHelpText();
+ }
+ else
+ {
+ // Mouse out of comment control
+ // FIXME Should remember previous tooltip text?
+ SetQuickHelpText( OUString() );
+ }
+ // Do start fading
+ maFadeTimer.Start();
+ }
+}
+
+void SwCommentRuler::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ Point aMousePos = rMEvt.GetPosPixel();
+ if ( !rMEvt.IsLeft() || IsTracking() || !GetCommentControlRegion().IsInside( aMousePos ) )
+ {
+ SvxRuler::MouseButtonDown(rMEvt);
+ return;
+ }
+
+ // Toggle notes visibility
+ SwView &rView = mpSwWin->GetView();
+ SfxRequest aRequest( rView.GetViewFrame(), FN_VIEW_NOTES );
+ rView.ExecViewOptions( aRequest );
+
+ // It is inside comment control, so update help text
+ UpdateCommentHelpText();
+
+ Invalidate();
+}
+
+void SwCommentRuler::Update()
+{
+ Rectangle aPreviousControlRect = GetCommentControlRegion();
+ SvxRuler::Update();
+ if (aPreviousControlRect != GetCommentControlRegion())
+ Invalidate();
+}
+
+void SwCommentRuler::UpdateCommentHelpText()
+{
+ int nTooltipResId;
+ if ( mpViewShell->GetPostItMgr()->ShowNotes() )
+ nTooltipResId = STR_HIDE_COMMENTS;
+ else
+ nTooltipResId = STR_SHOW_COMMENTS;
+ SetQuickHelpText( OUString( SW_RESSTR( nTooltipResId ) ) );
+}
+
+// TODO Make Ruler return its central rectangle instead of margins.
+Rectangle SwCommentRuler::GetCommentControlRegion()
+{
+ long nLeft = 0;
+ SwPostItMgr *pPostItMgr = mpViewShell->GetPostItMgr();
+
+ //rhbz#1006850 When the SwPostItMgr ctor is called from SwView::SwView it
+ //triggers an update of the uiview, but the result of the ctor hasn't been
+ //set into the mpViewShell yet, so GetPostItMgr is temporarily still NULL
+ if (!pPostItMgr)
+ return Rectangle();
+
+ unsigned long nSidebarWidth = pPostItMgr->GetSidebarWidth(true);
+ //FIXME When the page width is larger then screen, the ruler is misplaced by one pixel
+ if (GetTextRTL())
+ nLeft = GetPageOffset() - nSidebarWidth + GetBorderOffset();
+ else
+ nLeft = GetWinOffset() + GetPageOffset() + mpSwWin->LogicToPixel(Size(GetPageWidth(), 0)).Width();
+ long nTop = 0 + 4; // Ruler::ImplDraw uses RULER_OFF (value: 3px) as offset, and Ruler::ImplFormat adds one extra pixel
+ // Somehow pPostItMgr->GetSidebarBorderWidth() returns border width already doubled
+ long nRight = nLeft + nSidebarWidth + pPostItMgr->GetSidebarBorderWidth(true);
+ long nBottom = nTop + GetRulerVirHeight() - 3;
+
+ Rectangle aRect(nLeft, nTop, nRight, nBottom);
+ return aRect;
+}
+
+Color SwCommentRuler::GetFadedColor(const Color &rHighColor, const Color &rLowColor)
+{
+ if ( ! maFadeTimer.IsActive() )
+ return mbIsHighlighted ? rHighColor : rLowColor;
+
+ Color aColor = rHighColor;
+ aColor.Merge( rLowColor, mnFadeRate * 255/100.f );
+ return aColor;
+}
+
+IMPL_LINK_NOARG(SwCommentRuler, FadeHandler)
+{
+ const int nStep = 25;
+ if ( mbIsHighlighted && mnFadeRate < 100 )
+ mnFadeRate += nStep;
+ else if ( !mbIsHighlighted && mnFadeRate > 0 )
+ mnFadeRate -= nStep;
+ else
+ return 0;
+
+ Invalidate();
+
+ if ( mnFadeRate != 0 && mnFadeRate != 100)
+ maFadeTimer.Start();
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */