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 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "taskpane/ScrollPanel.hxx"
22 :
23 : #include "taskpane/ControlContainer.hxx"
24 : #include "TaskPaneFocusManager.hxx"
25 : #include "taskpane/TitledControl.hxx"
26 : #include "AccessibleScrollPanel.hxx"
27 :
28 : #include <vcl/svapp.hxx>
29 : #include <svtools/valueset.hxx>
30 :
31 : namespace sd { namespace toolpanel {
32 :
33 0 : ScrollPanel::ScrollPanel (
34 : ::Window& i_rParentWindow)
35 : : Control (&i_rParentWindow, WB_DIALOGCONTROL),
36 : TreeNode(NULL),
37 : maScrollWindow(this, WB_DIALOGCONTROL),
38 : maVerticalScrollBar(this, WB_VERT),
39 : maHorizontalScrollBar(this, WB_HORZ),
40 : maScrollBarFiller(this),
41 : maScrollWindowFiller(&maScrollWindow),
42 : mbIsRearrangePending(true),
43 : mbIsLayoutPending(true),
44 : mnChildrenWidth(0),
45 : mnVerticalBorder(2),
46 : mnVerticalGap(3),
47 0 : mnHorizontalBorder(2)
48 : {
49 0 : Construct();
50 0 : }
51 :
52 0 : void ScrollPanel::Construct()
53 : {
54 0 : SetAccessibleName (::rtl::OUString("Sub Task Panel"));
55 0 : mpControlContainer->SetMultiSelection (true);
56 :
57 0 : SetBorderStyle (WINDOW_BORDER_NORMAL);
58 0 : SetMapMode (MapMode(MAP_PIXEL));
59 :
60 : // To reduce flickering during repaints make the container windows
61 : // transparent and rely on their children to paint the whole area.
62 0 : SetBackground(Wallpaper());
63 0 : maScrollWindow.SetBackground(Wallpaper());
64 : maScrollWindowFiller.SetBackground(
65 0 : Application::GetSettings().GetStyleSettings().GetWindowColor());
66 :
67 0 : maScrollWindow.Show();
68 :
69 : // Initialize the scroll bars.
70 : maVerticalScrollBar.SetScrollHdl (
71 0 : LINK(this, ScrollPanel, ScrollBarHandler));
72 0 : maVerticalScrollBar.EnableDrag (sal_True);
73 : maHorizontalScrollBar.SetScrollHdl (
74 0 : LINK(this, ScrollPanel, ScrollBarHandler));
75 0 : maHorizontalScrollBar.EnableDrag (sal_True);
76 0 : }
77 :
78 :
79 :
80 :
81 0 : ScrollPanel::~ScrollPanel (void)
82 : {
83 0 : sal_uInt32 nCount = mpControlContainer->GetControlCount();
84 0 : for (sal_uInt32 nIndex=0; nIndex<nCount; nIndex++)
85 : {
86 0 : TreeNode* pNode = mpControlContainer->GetControl(nIndex);
87 0 : TreeNode* pControl = pNode;
88 : // When the node has been created as TitledControl then use its
89 : // control instead of pNode directly.
90 0 : TitledControl* pTitledControl = dynamic_cast<TitledControl*>(pNode);
91 0 : if (pTitledControl != NULL)
92 0 : pControl = pTitledControl->GetControl();
93 :
94 : // Remove this object as listener from the control.
95 0 : if (pControl != NULL && pControl->GetWindow()!=NULL)
96 : {
97 0 : pControl->GetWindow()->RemoveEventListener(
98 0 : LINK(this,ScrollPanel,WindowEventListener));
99 : }
100 : }
101 0 : mpControlContainer->DeleteChildren();
102 0 : }
103 :
104 :
105 :
106 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
107 0 : TitledControl* ScrollPanel::AddControl (
108 : ::std::auto_ptr<TreeNode> pControl,
109 : const String& rTitle,
110 : const rtl::OString& rHelpId)
111 : {
112 : // We are interested only in the title. The control itself is
113 : // managed by the content object.
114 : TitledControl* pTitledControl = new TitledControl(
115 : this,
116 : pControl,
117 : rTitle,
118 0 : TitledControlStandardClickHandler(GetControlContainer(), ControlContainer::ES_TOGGLE),
119 0 : TitleBar::TBT_SUB_CONTROL_HEADLINE);
120 0 : pTitledControl->GetTitleBar()->SetHelpId(rHelpId);
121 :
122 0 : AddControl(::std::auto_ptr<TreeNode>(pTitledControl));
123 :
124 0 : return pTitledControl;
125 : }
126 : SAL_WNODEPRECATED_DECLARATIONS_POP
127 :
128 :
129 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
130 0 : void ScrollPanel::AddControl (::std::auto_ptr<TreeNode> pControl)
131 : {
132 0 : if (pControl.get() != NULL)
133 : {
134 : // Add a window event listener which does two things:
135 : // 1. Listen for controls being shown or hidden so that the layout
136 : // can be adapted.
137 : // 2. Track selection changes in order to make the selected elements
138 : // visible.
139 0 : const Link aWindowListener(LINK(this,ScrollPanel,WindowEventListener));
140 : OSL_ASSERT(pControl->GetWindow()!=NULL);
141 0 : pControl->GetWindow()->AddEventListener(aWindowListener);
142 :
143 0 : TitledControl* pTitledControl = dynamic_cast<TitledControl*>(pControl.get());
144 0 : if (pTitledControl != NULL)
145 : {
146 : OSL_ASSERT(pTitledControl->GetControl()!=NULL);
147 : OSL_ASSERT(pTitledControl->GetControl()->GetWindow()!=NULL);
148 0 : pTitledControl->GetControl()->GetWindow()->AddEventListener(aWindowListener);
149 : }
150 :
151 0 : FocusManager& rFocusManager (FocusManager::Instance());
152 0 : int nControlCount (mpControlContainer->GetControlCount());
153 : // Replace the old links for cycling between first and last child by
154 : // current ones.
155 0 : if (nControlCount > 0)
156 : {
157 0 : ::Window* pFirst = mpControlContainer->GetControl(0)->GetWindow();
158 0 : ::Window* pLast = mpControlContainer->GetControl(nControlCount-1)->GetWindow();
159 0 : rFocusManager.RemoveLinks(pFirst,pLast);
160 0 : rFocusManager.RemoveLinks(pLast,pFirst);
161 :
162 0 : rFocusManager.RegisterLink(pFirst,pControl->GetWindow(), KEY_UP);
163 0 : rFocusManager.RegisterLink(pControl->GetWindow(),pFirst, KEY_DOWN);
164 : }
165 :
166 :
167 : // Add a down link only for the first control so that when entering
168 : // the sub tool panel the focus is set to the first control.
169 0 : if (nControlCount == 0)
170 0 : rFocusManager.RegisterDownLink(GetParent(), pControl->GetWindow());
171 0 : rFocusManager.RegisterUpLink(pControl->GetWindow(), GetParent());
172 :
173 0 : pControl->GetWindow()->SetParent(&maScrollWindow);
174 0 : mpControlContainer->AddControl (pControl);
175 0 : mpControlContainer->SetExpansionState(
176 0 : mpControlContainer->GetControlCount()-1,
177 0 : ControlContainer::ES_EXPAND);
178 : }
179 0 : }
180 : SAL_WNODEPRECATED_DECLARATIONS_POP
181 :
182 :
183 :
184 0 : void ScrollPanel::Paint (const Rectangle& rRect)
185 : {
186 0 : if (mbIsRearrangePending)
187 0 : Rearrange();
188 0 : if (mbIsLayoutPending)
189 0 : LayoutChildren();
190 0 : ::Window::Paint (rRect);
191 :
192 : // Paint the outer border and the space between every two children.
193 0 : Color aOriginalLineColor (maScrollWindow.GetLineColor());
194 0 : Color aOriginalFillColor (maScrollWindow.GetFillColor());
195 :
196 0 : maScrollWindow.SetLineColor ();
197 : maScrollWindow.SetFillColor (
198 0 : GetSettings().GetStyleSettings().GetWindowColor());
199 :
200 0 : Size aSize (maScrollWindow.GetOutputSizePixel());
201 : // Paint left and right vertical border.
202 : Rectangle aVerticalArea (
203 : Point(0,0),
204 0 : Size(mnHorizontalBorder,aSize.Height()));
205 0 : maScrollWindow.DrawRect (aVerticalArea);
206 0 : aVerticalArea.Right() += mnHorizontalBorder + mnChildrenWidth - 1;
207 0 : aVerticalArea.Left() = aVerticalArea.Right() + mnHorizontalBorder;
208 0 : maScrollWindow.DrawRect (aVerticalArea);
209 :
210 : // Paint horizontal stripes.
211 : Rectangle aStripeArea (
212 : Point (mnHorizontalBorder,0),
213 0 : Size(mnChildrenWidth,0));
214 0 : StripeList::const_iterator iStripe;
215 0 : for (iStripe=maStripeList.begin(); iStripe!=maStripeList.end(); ++iStripe)
216 : {
217 0 : aStripeArea.Top() = iStripe->first;
218 0 : aStripeArea.Bottom() = iStripe->second;
219 0 : if (aStripeArea.Bottom() < 0)
220 0 : continue;
221 0 : if (aStripeArea.Top() >= aSize.Height())
222 0 : break;
223 0 : maScrollWindow.DrawRect (aStripeArea);
224 : }
225 :
226 0 : maScrollWindow.SetLineColor (aOriginalLineColor);
227 0 : maScrollWindow.SetFillColor (aOriginalFillColor);
228 0 : }
229 :
230 :
231 :
232 :
233 0 : void ScrollPanel::Resize (void)
234 : {
235 0 : ::Window::Resize();
236 0 : mbIsRearrangePending = true;
237 0 : mbIsLayoutPending = true;
238 0 : }
239 :
240 :
241 :
242 :
243 0 : void ScrollPanel::RequestResize (void)
244 : {
245 0 : mbIsRearrangePending = true;
246 0 : mbIsLayoutPending = true;
247 0 : Invalidate();
248 0 : }
249 :
250 :
251 :
252 :
253 0 : Size ScrollPanel::GetPreferredSize (void)
254 : {
255 0 : return GetRequiredSize();
256 : }
257 :
258 :
259 :
260 :
261 0 : sal_Int32 ScrollPanel::GetPreferredWidth (sal_Int32 )
262 : {
263 0 : return GetPreferredSize().Width();
264 : }
265 :
266 :
267 :
268 :
269 0 : sal_Int32 ScrollPanel::GetPreferredHeight (sal_Int32 )
270 : {
271 0 : return GetPreferredSize().Height();
272 : }
273 :
274 :
275 :
276 :
277 0 : bool ScrollPanel::IsResizable (void)
278 : {
279 0 : return true;
280 : }
281 :
282 :
283 :
284 :
285 0 : ::Window* ScrollPanel::GetWindow (void)
286 : {
287 0 : return this;
288 : }
289 :
290 :
291 :
292 :
293 0 : sal_Int32 ScrollPanel::GetMinimumWidth (void)
294 : {
295 0 : return TreeNode::GetMinimumWidth();
296 : }
297 :
298 :
299 :
300 :
301 0 : void ScrollPanel::ExpandControl (
302 : TreeNode* pControl,
303 : bool bExpansionState)
304 : {
305 : // Toggle expand status.
306 0 : pControl->Expand (bExpansionState);
307 :
308 0 : Rearrange ();
309 0 : Invalidate ();
310 0 : }
311 :
312 :
313 :
314 :
315 0 : bool ScrollPanel::IsVerticalScrollBarVisible (void) const
316 : {
317 0 : return maVerticalScrollBar.IsReallyVisible();
318 : }
319 :
320 :
321 :
322 :
323 0 : bool ScrollPanel::IsHorizontalScrollBarVisible (void) const
324 : {
325 0 : return maHorizontalScrollBar.IsReallyVisible();
326 : }
327 :
328 :
329 :
330 :
331 0 : ScrollBar& ScrollPanel::GetVerticalScrollBar (void)
332 : {
333 0 : return maVerticalScrollBar;
334 : }
335 :
336 :
337 :
338 :
339 0 : ScrollBar& ScrollPanel::GetHorizontalScrollBar (void)
340 : {
341 0 : return maHorizontalScrollBar;
342 : }
343 :
344 :
345 :
346 :
347 : /** This control shows an expansion bar for every control and in a
348 : separate area below that expansion area it shows all controls each
349 : with its title bar. When there is not enough space then show a
350 : scroll bar in the control area.
351 : */
352 0 : void ScrollPanel::Rearrange (void)
353 : {
354 0 : Size aRequiredSize (GetRequiredSize());
355 0 : if (aRequiredSize.Width()>0 && aRequiredSize.Height()>0)
356 : {
357 0 : Size aAvailableSize (SetupScrollBars (aRequiredSize));
358 : maScrollWindow.SetPosSizePixel(
359 : Point(0,0),
360 0 : aAvailableSize);
361 :
362 : // Make the children at least as wide as the sub tool panel.
363 0 : if (aRequiredSize.Width() < aAvailableSize.Width())
364 0 : aRequiredSize.Width() = aAvailableSize.Width();
365 0 : mnChildrenWidth = -2*mnHorizontalBorder;
366 0 : if (maHorizontalScrollBar.IsVisible())
367 0 : mnChildrenWidth += aRequiredSize.Width();
368 : else
369 0 : mnChildrenWidth += aAvailableSize.Width();
370 :
371 0 : sal_Int32 nChildrenHeight (LayoutChildren());
372 : maVerticalScrollBar.SetRangeMax (
373 0 : nChildrenHeight + mnVerticalBorder);
374 :
375 0 : mbIsRearrangePending = false;
376 : }
377 0 : }
378 :
379 :
380 :
381 :
382 0 : Size ScrollPanel::GetRequiredSize (void)
383 : {
384 : // First determine the width of the children. This is the maximum of
385 : // the current window width and the individual minimum widths of the
386 : // children.
387 0 : int nChildrenWidth (GetSizePixel().Width());
388 0 : unsigned int nCount = mpControlContainer->GetControlCount();
389 : unsigned int nIndex;
390 0 : for (nIndex=0; nIndex<nCount; nIndex++)
391 : {
392 0 : TreeNode* pChild = mpControlContainer->GetControl (nIndex);
393 0 : int nMinimumWidth (pChild->GetMinimumWidth());
394 0 : if (nMinimumWidth > nChildrenWidth)
395 0 : nChildrenWidth = nMinimumWidth;
396 : }
397 :
398 : // Determine the accumulated width of all children when scaled to the
399 : // minimum width.
400 0 : nChildrenWidth -= 2*mnHorizontalBorder;
401 : Size aTotalSize (nChildrenWidth,
402 0 : 2*mnVerticalBorder + (nCount-1) * mnVerticalGap);
403 0 : for (nIndex=0; nIndex<nCount; nIndex++)
404 : {
405 0 : TreeNode* pChild = mpControlContainer->GetControl (nIndex);
406 0 : sal_Int32 nHeight = pChild->GetPreferredHeight(nChildrenWidth);
407 0 : aTotalSize.Height() += nHeight;
408 : }
409 :
410 0 : return aTotalSize;
411 : }
412 :
413 :
414 :
415 :
416 0 : sal_Int32 ScrollPanel::LayoutChildren (void)
417 : {
418 0 : maStripeList.clear();
419 :
420 0 : Point aPosition (maScrollOffset);
421 0 : aPosition.X() += mnHorizontalBorder;
422 : maStripeList.push_back( ::std::pair<int,int>(
423 0 : aPosition.Y(),
424 0 : aPosition.Y() + mnVerticalBorder - 1));
425 0 : aPosition.Y() += mnVerticalBorder;
426 :
427 : // Place the controls one over the other.
428 0 : unsigned int nCount (mpControlContainer->GetControlCount());
429 0 : for (unsigned int nIndex=0; nIndex<nCount; nIndex++)
430 : {
431 0 : if (nIndex > 0)
432 : {
433 : maStripeList.push_back( ::std::pair<int,int>(
434 0 : aPosition.Y(),
435 0 : aPosition.Y() + mnVerticalGap - 1));
436 0 : aPosition.Y() += mnVerticalGap;
437 : }
438 0 : TreeNode* pChild = mpControlContainer->GetControl (nIndex);
439 0 : int nControlHeight = pChild->GetPreferredHeight(mnChildrenWidth);
440 0 : pChild->GetWindow()->SetPosSizePixel(
441 : aPosition,
442 0 : Size(mnChildrenWidth, nControlHeight));
443 0 : aPosition.Y() += nControlHeight;
444 : }
445 :
446 : // If the children do not cover their parent window completely
447 : // (regarding the height) we put a filler below that is responsible for
448 : // painting the remaining space.
449 0 : int nWindowHeight = maScrollWindow.GetSizePixel().Height();
450 0 : if (aPosition.Y() < nWindowHeight)
451 : {
452 : maScrollWindowFiller.SetPosSizePixel (
453 : aPosition,
454 0 : Size(mnChildrenWidth, nWindowHeight-aPosition.Y()));
455 : maStripeList.push_back( ::std::pair<int,int>(
456 0 : aPosition.Y(),
457 0 : nWindowHeight-1));
458 : // maScrollWindowFiller.Show();
459 0 : aPosition.Y() = nWindowHeight;
460 : }
461 : else
462 0 : maScrollWindowFiller.Hide();
463 :
464 0 : aPosition.Y() += mnVerticalBorder;
465 0 : mbIsLayoutPending = false;
466 :
467 0 : return aPosition.Y()-maScrollOffset.Y();
468 : }
469 :
470 :
471 :
472 :
473 0 : Size ScrollPanel::SetupScrollBars (const Size& rRequiredSize)
474 : {
475 0 : Size aWindowSize (GetSizePixel());
476 : Size aScrollBarSize (
477 0 : maVerticalScrollBar.GetSizePixel().Width(),
478 0 : maHorizontalScrollBar.GetSizePixel().Height());
479 0 : Size aRemainingSize (aWindowSize);
480 :
481 : // Determine which scroll bars have to be shown.
482 0 : bool bShowHorizontal = false;
483 0 : if (rRequiredSize.Width() > aWindowSize.Width())
484 0 : bShowHorizontal = true;
485 0 : bool bShowVertical = false;
486 0 : if (rRequiredSize.Height() > aWindowSize.Height())
487 0 : bShowVertical = true;
488 : // Showing one scroll bar may reduce the available size so that the
489 : // other one has to be shown as well.
490 0 : if (bShowHorizontal && ! bShowVertical)
491 : {
492 0 : if ((rRequiredSize.Height() + aScrollBarSize.Height())
493 0 : > aWindowSize.Height())
494 0 : bShowVertical = true;
495 : }
496 0 : else if (bShowVertical && ! bShowHorizontal)
497 : {
498 0 : if (GetMinimumWidth() + aScrollBarSize.Width() > aWindowSize.Width())
499 0 : bShowHorizontal = true;
500 : }
501 :
502 : // Setup the scroll bars.
503 0 : aRemainingSize.Width()
504 0 : = SetupVerticalScrollBar (bShowVertical, rRequiredSize.Height());
505 0 : aRemainingSize.Height()
506 0 : = SetupHorizontalScrollBar (bShowHorizontal, rRequiredSize.Width());
507 :
508 : // Place the filler.
509 0 : if (bShowHorizontal && bShowVertical)
510 : {
511 : maScrollBarFiller.SetPosSizePixel (
512 0 : Point(aWindowSize.Width(), aWindowSize.Height()),
513 0 : aScrollBarSize);
514 0 : maScrollBarFiller.Show();
515 : }
516 : else
517 0 : maScrollBarFiller.Hide();
518 :
519 :
520 0 : return aRemainingSize;
521 : }
522 :
523 :
524 :
525 :
526 0 : sal_Int32 ScrollPanel::SetupVerticalScrollBar (bool bShow, sal_Int32 nRange)
527 : {
528 : Size aScrollBarSize (
529 0 : maVerticalScrollBar.GetSizePixel().Width(),
530 0 : maHorizontalScrollBar.GetSizePixel().Height());
531 0 : Size aWindowSize (GetOutputSizePixel());
532 0 : sal_Int32 nRemainingWidth (aWindowSize.Width());
533 :
534 : // Setup the verical scroll bar.
535 0 : if (bShow)
536 : {
537 0 : int nWidth = aScrollBarSize.Width();
538 0 : int nHeight = aWindowSize.Height();
539 : maVerticalScrollBar.SetPosSizePixel(
540 0 : Point(aWindowSize.Width()-nWidth,0),
541 0 : Size(nWidth, nHeight));
542 0 : maVerticalScrollBar.Show();
543 :
544 : // Set the scroll bar range and thumb size.
545 0 : maVerticalScrollBar.SetRangeMin (0);
546 : maVerticalScrollBar.SetRangeMax (
547 0 : nRange + 2*mnVerticalBorder);
548 0 : maVerticalScrollBar.SetVisibleSize (aWindowSize.Height());
549 : // Make page size approx. 10% of visible area.
550 0 : maVerticalScrollBar.SetLineSize (aWindowSize.Height()/10);
551 : // Make page size approx. 100% of visible area.
552 0 : maVerticalScrollBar.SetPageSize (aWindowSize.Height());
553 : // Make sure that thumb is inside the valid range.
554 0 : maVerticalScrollBar.SetThumbPos(-maScrollOffset.Y());
555 0 : long nMinPos = maVerticalScrollBar.GetRangeMin();
556 0 : if (maVerticalScrollBar.GetThumbPos() < nMinPos)
557 0 : maVerticalScrollBar.SetThumbPos(nMinPos);
558 0 : long nMaxPos = maVerticalScrollBar.GetRangeMax()
559 0 : - maVerticalScrollBar.GetVisibleSize();
560 0 : if (maVerticalScrollBar.GetThumbPos() >= nMaxPos)
561 0 : maVerticalScrollBar.SetThumbPos(nMaxPos);
562 : // Set offset to match thumb pos.
563 0 : maScrollOffset.Y() = -maVerticalScrollBar.GetThumbPos();
564 :
565 0 : nRemainingWidth -= aScrollBarSize.Width();
566 : }
567 : else
568 : {
569 0 : maVerticalScrollBar.Hide();
570 0 : maScrollOffset.Y() = 0;
571 : }
572 :
573 0 : return nRemainingWidth;
574 : }
575 :
576 :
577 :
578 :
579 0 : sal_Int32 ScrollPanel::SetupHorizontalScrollBar (bool bShow, sal_Int32 nRange)
580 : {
581 : Size aScrollBarSize (
582 0 : maVerticalScrollBar.GetSizePixel().Width(),
583 0 : maHorizontalScrollBar.GetSizePixel().Height());
584 0 : Size aWindowSize (GetOutputSizePixel());
585 0 : sal_Int32 nRemainingHeight (aWindowSize.Height());
586 :
587 : // Setup the horizontal scroll bar.
588 0 : if (bShow)
589 : {
590 0 : int nHeight = aScrollBarSize.Height();
591 0 : int nWidth = GetOutputSizePixel().Width();
592 : maHorizontalScrollBar.SetPosSizePixel(
593 0 : Point(0, aWindowSize.Height()-nHeight),
594 0 : Size(nWidth,nHeight));
595 0 : maHorizontalScrollBar.Show();
596 :
597 : // Set the scroll bar range and thumb size.
598 0 : maHorizontalScrollBar.SetRangeMin (0);
599 : maHorizontalScrollBar.SetRangeMax (
600 0 : nRange + 2*mnHorizontalBorder);
601 0 : maHorizontalScrollBar.SetVisibleSize (aWindowSize.Width());
602 : // Make page size approx. 5% of visible area.
603 0 : maHorizontalScrollBar.SetLineSize (aWindowSize.Width()/20+1);
604 : // Make page size approx. 50% of visible area.
605 0 : maHorizontalScrollBar.SetPageSize (aWindowSize.Width()/2+1);
606 : // Make sure that thumb is inside the valid range.
607 0 : maHorizontalScrollBar.SetThumbPos(-maScrollOffset.X());
608 0 : long nMinPos = maHorizontalScrollBar.GetRangeMin();
609 0 : if (maHorizontalScrollBar.GetThumbPos() < nMinPos)
610 0 : maHorizontalScrollBar.SetThumbPos(nMinPos);
611 0 : long nMaxPos = maHorizontalScrollBar.GetRangeMax()
612 0 : - maHorizontalScrollBar.GetVisibleSize();
613 0 : if (maHorizontalScrollBar.GetThumbPos() >= nMaxPos)
614 0 : maHorizontalScrollBar.SetThumbPos(nMaxPos);
615 : // Set offset to match thumb pos.
616 0 : maScrollOffset.X() = -maHorizontalScrollBar.GetThumbPos();
617 :
618 0 : nRemainingHeight -= aScrollBarSize.Height();
619 : }
620 : else
621 : {
622 0 : maHorizontalScrollBar.Hide();
623 0 : maScrollOffset.X() = 0;
624 : }
625 :
626 0 : return nRemainingHeight;
627 : }
628 :
629 :
630 0 : IMPL_LINK_NOARG(ScrollPanel, ScrollBarHandler)
631 : {
632 0 : maScrollOffset.X() -= maHorizontalScrollBar.GetDelta();
633 0 : maScrollOffset.Y() -= maVerticalScrollBar.GetDelta();
634 :
635 : // Scrolling is done by moving the child windows up or down.
636 0 : mbIsLayoutPending = true;
637 0 : Invalidate();
638 : // LayoutChildren();
639 :
640 0 : return 0;
641 : }
642 :
643 :
644 :
645 :
646 0 : long ScrollPanel::Notify( NotifyEvent& rNEvt )
647 : {
648 0 : long nRet = sal_False;
649 0 : if( rNEvt.GetType() == EVENT_COMMAND )
650 : {
651 : // note: dynamic_cast is not possible as GetData() returns a void*
652 0 : CommandEvent* pCmdEvent = reinterpret_cast< CommandEvent* >(rNEvt.GetData());
653 : DBG_ASSERT( pCmdEvent!=0 &&
654 : ( pCmdEvent->IsMouseEvent() == sal_True ||
655 : pCmdEvent->IsMouseEvent() == sal_False ),
656 : "Invalid CommandEvent" );
657 0 : if (pCmdEvent)
658 0 : switch (pCmdEvent->GetCommand())
659 : {
660 : case COMMAND_WHEEL:
661 : case COMMAND_STARTAUTOSCROLL:
662 : case COMMAND_AUTOSCROLL:
663 : {
664 0 : nRet = HandleScrollCommand (*pCmdEvent, &maHorizontalScrollBar, &maVerticalScrollBar);
665 0 : break;
666 : }
667 : }
668 : }
669 :
670 0 : if( ! nRet )
671 0 : nRet = ::Window::Notify( rNEvt );
672 :
673 0 : return nRet;
674 : }
675 :
676 :
677 :
678 :
679 : ::com::sun::star::uno::Reference<
680 0 : ::com::sun::star::accessibility::XAccessible> ScrollPanel::CreateAccessibleObject (
681 : const ::com::sun::star::uno::Reference<
682 : ::com::sun::star::accessibility::XAccessible>& )
683 : {
684 : return new ::accessibility::AccessibleScrollPanel (
685 : *this,
686 : "Scroll Panel",
687 0 : "Scroll Panel");
688 : }
689 :
690 :
691 :
692 :
693 0 : void ScrollPanel::MakeRectangleVisible (
694 : Rectangle& aRectangle,
695 : ::Window* pWindow)
696 : {
697 0 : if (maVerticalScrollBar.IsVisible() && aRectangle.GetWidth()>0 && aRectangle.GetHeight()>0)
698 : {
699 0 : const Rectangle aRelativeBox (pWindow->GetWindowExtentsRelative(&maScrollWindow));
700 :
701 : aRectangle.Move(
702 0 : -maScrollOffset.X() + aRelativeBox.Left(),
703 0 : -maScrollOffset.Y() + aRelativeBox.Top());
704 :
705 0 : const int nVisibleHeight (maVerticalScrollBar.GetVisibleSize());
706 0 : const int nVisibleTop (maVerticalScrollBar.GetThumbPos());
707 0 : if (aRectangle.Bottom() >= nVisibleTop+nVisibleHeight)
708 0 : maVerticalScrollBar.DoScroll(aRectangle.Bottom() - nVisibleHeight);
709 0 : else if (aRectangle.Top() < nVisibleTop)
710 0 : maVerticalScrollBar.DoScroll(aRectangle.Top());
711 : }
712 0 : }
713 :
714 :
715 :
716 :
717 0 : IMPL_LINK(ScrollPanel,WindowEventListener,VclSimpleEvent*,pEvent)
718 : {
719 0 : VclWindowEvent* pWindowEvent = dynamic_cast<VclWindowEvent*>(pEvent);
720 0 : if (pWindowEvent != NULL)
721 : {
722 0 : switch (pWindowEvent->GetId())
723 : {
724 : case VCLEVENT_WINDOW_KEYUP:
725 : case VCLEVENT_WINDOW_MOUSEBUTTONUP:
726 : {
727 : // Make the currently selected item visible.
728 0 : ValueSet* pControl = dynamic_cast<ValueSet*>(pWindowEvent->GetWindow());
729 0 : if (pControl != NULL)
730 : {
731 : // Get the bounding box of the currently selected item
732 : // and enlarge this so that the selection frame is
733 : // inside as well.
734 0 : Rectangle aBox (pControl->GetItemRect(pControl->GetSelectItemId()));
735 0 : aBox.Top()-=4;
736 0 : aBox.Bottom()+=4;
737 :
738 0 : MakeRectangleVisible(aBox, pControl);
739 : }
740 : }
741 0 : break;
742 :
743 : case VCLEVENT_WINDOW_MOUSEBUTTONDOWN:
744 : {
745 : // Make the item under the mouse visible. We need this case
746 : // for right clicks that open context menus. For these we
747 : // only get the mouse down event. The following mouse up
748 : // event is sent to the context menu.
749 0 : ValueSet* pControl = dynamic_cast<ValueSet*>(pWindowEvent->GetWindow());
750 0 : if (pControl != NULL)
751 : {
752 : // Get the bounding box of the item at the mouse
753 : // position and enlarge this so that the selection frame
754 : // is inside as well.
755 : MouseEvent* pMouseEvent
756 0 : = reinterpret_cast<MouseEvent*>(pWindowEvent->GetData());
757 0 : if (pMouseEvent != NULL)
758 : {
759 0 : Point aPosition (pMouseEvent->GetPosPixel());
760 0 : Rectangle aBox (pControl->GetItemRect(pControl->GetItemId(aPosition)));
761 0 : aBox.Top()-=4;
762 0 : aBox.Bottom()+=4;
763 :
764 0 : MakeRectangleVisible(aBox, pControl);
765 : }
766 : }
767 : }
768 0 : break;
769 :
770 :
771 : case VCLEVENT_WINDOW_GETFOCUS:
772 : {
773 : // Move title bars into the visible area when they get the
774 : // focus (::Window wise their enclosing TitledControl gets
775 : // the focus.)
776 0 : TitledControl* pTitledControl = dynamic_cast<TitledControl*>(pWindowEvent->GetWindow());
777 0 : if (pTitledControl!=NULL && pTitledControl->GetTitleBar()!=NULL)
778 : {
779 0 : ::Window* pTitleBarWindow = pTitledControl->GetTitleBar()->GetWindow();
780 0 : Rectangle aBox(pTitleBarWindow->GetPosPixel(),pTitleBarWindow->GetSizePixel());
781 : MakeRectangleVisible(
782 : aBox,
783 0 : pTitleBarWindow);
784 : }
785 : }
786 0 : break;
787 :
788 : case VCLEVENT_WINDOW_SHOW:
789 : case VCLEVENT_WINDOW_HIDE:
790 : case VCLEVENT_WINDOW_ACTIVATE:
791 : case VCLEVENT_WINDOW_RESIZE:
792 : // Rearrange the children of the scroll panel when one of
793 : // the children changes its size or visibility.
794 0 : RequestResize();
795 0 : break;
796 : }
797 : }
798 0 : return 0;
799 : }
800 :
801 :
802 :
803 :
804 : } } // end of namespace ::sd::toolpanel
805 :
806 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|