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.freedesktop.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 : // TODO Delayed highlight fading when user moves mouse over and out the control
14 :
15 : #include "swruler.hxx"
16 :
17 : #include "viewsh.hxx"
18 : #include "edtwin.hxx"
19 : #include "PostItMgr.hxx"
20 : #include "viewopt.hxx"
21 : #include <view.hxx>
22 : #include "cmdid.h"
23 : #include <sfx2/request.hxx>
24 : #include <vcl/svapp.hxx>
25 : #include <vcl/window.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 : // Constructor
38 793 : SwCommentRuler::SwCommentRuler( ViewShell* pViewSh, Window* pParent, SwEditWin* pWin, sal_uInt16 nRulerFlags, SfxBindings& rBindings, WinBits nWinStyle)
39 : : SvxRuler(pParent, pWin, nRulerFlags, rBindings, nWinStyle | WB_HSCROLL)
40 : , mpViewShell(pViewSh)
41 : , mpSwWin(pWin)
42 : , mbIsHighlighted(false)
43 793 : , maVirDev( *this )
44 : {
45 793 : }
46 :
47 : // Destructor
48 1584 : SwCommentRuler::~SwCommentRuler()
49 : {
50 1584 : }
51 :
52 1144 : void SwCommentRuler::Paint( const Rectangle& rRect )
53 : {
54 1144 : SvxRuler::Paint( rRect );
55 : // Don't draw if there is not any note
56 1144 : if ( mpViewShell->GetPostItMgr()->HasNotes() )
57 15 : DrawCommentControl();
58 1144 : }
59 :
60 15 : void SwCommentRuler::DrawCommentControl()
61 : {
62 15 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
63 15 : bool bIsCollapsed = ! mpViewShell->GetPostItMgr()->ShowNotes();
64 :
65 15 : Rectangle aControlRect = GetCommentControlRegion();
66 15 : maVirDev.SetOutputSizePixel( aControlRect.GetSize() );
67 :
68 : // Paint comment control background
69 : // TODO Check if these are best colors to be used
70 15 : if ( mbIsHighlighted )
71 0 : maVirDev.SetFillColor( rStyleSettings.GetDarkShadowColor() );
72 : else
73 15 : maVirDev.SetFillColor( rStyleSettings.GetWorkspaceColor() );
74 :
75 15 : if ( mbIsHighlighted || !bIsCollapsed )
76 : {
77 : // Draw borders
78 15 : maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
79 : }
80 : else
81 : {
82 : // No borders
83 0 : maVirDev.SetLineColor();
84 : }
85 :
86 15 : maVirDev.DrawRect( Rectangle( Point(), aControlRect.GetSize() ) );
87 :
88 15 : String aLabel( SW_RESSTR ( STR_COMMENTS_LABEL ) );
89 : // Get label and arrow coordinates
90 15 : Point aLabelPos;
91 15 : Point aArrowPos;
92 : bool bArrowToRight;
93 : // TODO Discover why it should be 0 instead of CONTROL_BORDER_WIDTH + CONTROL_TOP_OFFSET
94 15 : aLabelPos.Y() = 0;
95 15 : aArrowPos.Y() = CONTROL_BORDER_WIDTH + CONTROL_TOP_OFFSET;
96 15 : if ( !Application::GetSettings().GetLayoutRTL() )
97 : {
98 : // LTR
99 15 : if ( bIsCollapsed )
100 : {
101 : // It should draw something like | > Comments |
102 0 : aLabelPos.X() = CONTROL_LEFT_OFFSET + CONTROL_TRIANGLE_WIDTH + CONTROL_TRIANGLE_PAD;
103 0 : aArrowPos.X() = CONTROL_LEFT_OFFSET;
104 : }
105 : else
106 : {
107 : // It should draw something like | Comments < |
108 15 : aLabelPos.X() = CONTROL_LEFT_OFFSET;
109 15 : aArrowPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - CONTROL_TRIANGLE_WIDTH;
110 : }
111 15 : bArrowToRight = bIsCollapsed;
112 : }
113 : else
114 : {
115 : // RTL
116 0 : long nLabelWidth = GetTextWidth( aLabel );
117 0 : if ( bIsCollapsed )
118 : {
119 : // It should draw something like | Comments < |
120 0 : aArrowPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - CONTROL_TRIANGLE_WIDTH;
121 0 : aLabelPos.X() = aArrowPos.X() - CONTROL_TRIANGLE_PAD - nLabelWidth;
122 : }
123 : else
124 : {
125 : // It should draw something like | > Comments |
126 0 : aLabelPos.X() = aControlRect.GetSize().Width() - 1 - CONTROL_RIGHT_OFFSET - CONTROL_BORDER_WIDTH - nLabelWidth;
127 0 : aArrowPos.X() = CONTROL_LEFT_OFFSET;
128 : }
129 0 : bArrowToRight = !bIsCollapsed;
130 : }
131 :
132 : // Draw label
133 15 : const Color &rTextColor = mbIsHighlighted ? rStyleSettings.GetButtonTextColor() : rStyleSettings.GetDeactiveTextColor();
134 15 : maVirDev.SetTextColor( rTextColor );
135 : // FIXME Expected font size?
136 15 : maVirDev.DrawText( aLabelPos, aLabel );
137 :
138 : // Draw arrow
139 : // FIXME consistence of button colors. http://opengrok.libreoffice.org/xref/core/vcl/source/control/button.cxx#785
140 15 : const Color &rArrowColor = mbIsHighlighted ? Color( COL_BLACK ) : rStyleSettings.GetShadowColor();
141 15 : ImplDrawArrow ( aArrowPos.X(), aArrowPos.Y(), rArrowColor, bArrowToRight );
142 :
143 : // Blit comment control
144 15 : DrawOutDev( aControlRect.TopLeft(), aControlRect.GetSize(), Point(), aControlRect.GetSize(), maVirDev );
145 15 : }
146 :
147 15 : void SwCommentRuler::ImplDrawArrow(long nX, long nY, const Color& rColor, bool bPointRight)
148 : {
149 15 : maVirDev.SetLineColor();
150 15 : maVirDev.SetFillColor( rColor );
151 15 : if ( bPointRight )
152 : {
153 0 : maVirDev.DrawRect( Rectangle( nX+0, nY+0, nX+0, nY+6 ) );
154 0 : maVirDev.DrawRect( Rectangle( nX+1, nY+1, nX+1, nY+5 ) );
155 0 : maVirDev.DrawRect( Rectangle( nX+2, nY+2, nX+2, nY+4 ) );
156 0 : maVirDev.DrawRect( Rectangle( nX+3, nY+3, nX+3, nY+3 ) );
157 : }
158 : else
159 : {
160 15 : maVirDev.DrawRect( Rectangle( nX+0, nY+3, nX+0, nY+3 ) );
161 15 : maVirDev.DrawRect( Rectangle( nX+1, nY+2, nX+1, nY+4 ) );
162 15 : maVirDev.DrawRect( Rectangle( nX+2, nY+1, nX+2, nY+5 ) );
163 15 : maVirDev.DrawRect( Rectangle( nX+3, nY+0, nX+3, nY+6 ) );
164 : }
165 15 : }
166 :
167 : // Just accept double-click outside comment control
168 0 : void SwCommentRuler::Command( const CommandEvent& rCEvt )
169 : {
170 0 : Point aMousePos = rCEvt.GetMousePosPixel();
171 : // Ignore command request if it is inside Comment Control
172 0 : if ( !mpViewShell->GetPostItMgr()
173 0 : || !mpViewShell->GetPostItMgr()->HasNotes()
174 0 : || !GetCommentControlRegion().IsInside( aMousePos ) )
175 0 : SvxRuler::Command( rCEvt );
176 0 : }
177 :
178 0 : void SwCommentRuler::MouseMove(const MouseEvent& rMEvt)
179 : {
180 0 : SvxRuler::MouseMove(rMEvt);
181 0 : if ( ! mpViewShell->GetPostItMgr() || ! mpViewShell->GetPostItMgr()->HasNotes() )
182 0 : return;
183 : // TODO Delay 0.1s to highlight and 0.2s to "lowlight"
184 0 : Point aMousePos = rMEvt.GetPosPixel();
185 0 : bool bWasHighlighted = mbIsHighlighted;
186 0 : mbIsHighlighted = GetCommentControlRegion().IsInside( aMousePos );
187 0 : if ( mbIsHighlighted != bWasHighlighted )
188 : {
189 : // Repaint for highlight changes make effect
190 0 : Invalidate();
191 : // Set proper help text
192 0 : if ( mbIsHighlighted )
193 : {
194 : // Mouse over comment control
195 0 : UpdateCommentHelpText();
196 : }
197 : else
198 : {
199 : // Mouse out of comment control
200 : // FIXME Should remember previous tooltip text?
201 0 : SetQuickHelpText( String() );
202 : }
203 : }
204 : }
205 :
206 0 : void SwCommentRuler::MouseButtonDown( const MouseEvent& rMEvt )
207 : {
208 0 : Point aMousePos = rMEvt.GetPosPixel();
209 0 : if ( !rMEvt.IsLeft() || IsTracking() || !GetCommentControlRegion().IsInside( aMousePos ) )
210 : {
211 0 : SvxRuler::MouseButtonDown(rMEvt);
212 0 : return;
213 : }
214 :
215 : // Toggle notes visibility
216 0 : SwView &rView = mpSwWin->GetView();
217 0 : SfxRequest aRequest( rView.GetViewFrame(), FN_VIEW_NOTES );
218 0 : rView.ExecViewOptions( aRequest );
219 :
220 : // It is inside comment control, so update help text
221 0 : UpdateCommentHelpText();
222 :
223 0 : Invalidate();
224 : }
225 :
226 3535 : void SwCommentRuler::Update()
227 : {
228 3535 : Rectangle aPreviousControlRect = GetCommentControlRegion();
229 3535 : SvxRuler::Update();
230 3535 : if (aPreviousControlRect != GetCommentControlRegion())
231 991 : Invalidate();
232 3535 : }
233 :
234 0 : void SwCommentRuler::UpdateCommentHelpText()
235 : {
236 : int nTooltipResId;
237 0 : if ( mpViewShell->GetPostItMgr()->ShowNotes() )
238 0 : nTooltipResId = STR_HIDE_COMMENTS;
239 : else
240 0 : nTooltipResId = STR_SHOW_COMMENTS;
241 0 : SetQuickHelpText( OUString( SW_RESSTR( nTooltipResId ) ) );
242 0 : }
243 :
244 : // NOTE: If sometime ahead SwSidebar moves from page right side due RTL layout,
245 : // change how this rectangle is used by callers
246 : // TODO Make Ruler return its central rectangle instead of margins.
247 7085 : Rectangle SwCommentRuler::GetCommentControlRegion()
248 : {
249 7085 : SwPostItMgr *pPostItMgr = mpViewShell->GetPostItMgr();
250 : //FIXME When the page width is larger then screen, the ruler is misplaced by one pixel
251 7085 : long nLeft = GetWinOffset() + GetPageOffset() + mpSwWin->LogicToPixel(Size(GetPageWidth(), 0)).Width();
252 7085 : long nTop = 0 + 4; // Ruler::ImplDraw uses RULER_OFF (value: 3px) as offset, and Ruler::ImplFormat adds one extra pixel
253 : // Somehow pPostItMgr->GetSidebarBorderWidth() returns border width already doubled
254 7085 : long nRight = nLeft+ pPostItMgr->GetSidebarWidth(true) + pPostItMgr->GetSidebarBorderWidth(true);
255 7085 : long nBottom = nTop + GetRulerVirHeight() - 3;
256 :
257 7085 : Rectangle aRect(nLeft, nTop, nRight, nBottom);
258 7085 : return aRect;
259 99 : }
260 :
261 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|