Files
libreoffice/sw/source/ui/misc/swruler.cxx
Rodolfo Ribeiro Gomes e047a967b0 fdo#38246 Comment control on Writer ruler feature
It follows the directions from design team available at
https://wiki.documentfoundation.org/Design/Whiteboards/Comments_Ruler_Control.
It misses some fancy stuff though (like animated/delayed highlight and fading border).
Some work should be done with (svtools) Ruler also for a cleaner implementation.

Change-Id: Ib065043d05fe56fbfe6d00e0bb654966f046129b
Signed-off-by: Rodolfo Ribeiro Gomes <rodolforg@gmail.com>
2013-03-11 10:08:30 +01:00

264 lines
9.0 KiB
C++

/* -*- 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.freedesktop.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
// TODO Delayed highlight fading when user moves mouse over and out the control
#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 "misc.hrc"
#define CONTROL_BORDER_WIDTH 1
#define CONTROL_LEFT_OFFSET 6
#define CONTROL_RIGHT_OFFSET 3
#define CONTROL_TOP_OFFSET 4
#define CONTROL_BOTTOM_OFFSET 4
#define CONTROL_TRIANGLE_WIDTH 4
#define CONTROL_TRIANGLE_HEIGHT 7
#define CONTROL_TRIANGLE_PAD 3
// Constructor
SwCommentRuler::SwCommentRuler( ViewShell* 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)
, maVirDev( *this )
{
}
// Destructor
SwCommentRuler::~SwCommentRuler()
{
}
void SwCommentRuler::Paint( const Rectangle& rRect )
{
SvxRuler::Paint( rRect );
// Don't draw if there is not any note
if ( 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
if ( mbIsHighlighted )
maVirDev.SetFillColor( rStyleSettings.GetDarkShadowColor() );
else
maVirDev.SetFillColor( rStyleSettings.GetWorkspaceColor() );
if ( mbIsHighlighted || !bIsCollapsed )
{
// Draw borders
maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
}
else
{
// No borders
maVirDev.SetLineColor();
}
maVirDev.DrawRect( Rectangle( Point(), aControlRect.GetSize() ) );
String 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
const Color &rTextColor = mbIsHighlighted ? rStyleSettings.GetButtonTextColor() : rStyleSettings.GetDeactiveTextColor();
maVirDev.SetTextColor( rTextColor );
// 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
const Color &rArrowColor = mbIsHighlighted ? Color( COL_BLACK ) : rStyleSettings.GetShadowColor();
ImplDrawArrow ( aArrowPos.X(), aArrowPos.Y(), rArrowColor, 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;
// TODO Delay 0.1s to highlight and 0.2s to "lowlight"
Point aMousePos = rMEvt.GetPosPixel();
bool bWasHighlighted = mbIsHighlighted;
mbIsHighlighted = GetCommentControlRegion().IsInside( aMousePos );
if ( mbIsHighlighted != bWasHighlighted )
{
// Repaint for highlight changes make effect
Invalidate();
// Set proper help text
if ( mbIsHighlighted )
{
// Mouse over comment control
UpdateCommentHelpText();
}
else
{
// Mouse out of comment control
// FIXME Should remember previous tooltip text?
SetQuickHelpText( String() );
}
}
}
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 ) ) );
}
// NOTE: If sometime ahead SwSidebar moves from page right side due RTL layout,
// change how this rectangle is used by callers
// TODO Make Ruler return its central rectangle instead of margins.
Rectangle SwCommentRuler::GetCommentControlRegion()
{
SwPostItMgr *pPostItMgr = mpViewShell->GetPostItMgr();
//FIXME When the page width is larger then screen, the ruler is misplaced by one pixel
long 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+ pPostItMgr->GetSidebarWidth(true) + pPostItMgr->GetSidebarBorderWidth(true);
long nBottom = nTop + GetRulerVirHeight() - 3;
Rectangle aRect(nLeft, nTop, nRight, nBottom);
return aRect;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */