Update ooo320-m1
[ooovba.git] / sd / source / ui / toolpanel / ControlContainer.cxx
blob5bc89932e857693693ec1669b9712e21775b3140
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ControlContainer.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include "taskpane/ControlContainer.hxx"
36 #include "taskpane/TaskPaneTreeNode.hxx"
38 #include <vcl/window.hxx>
39 #include <vcl/svapp.hxx>
41 namespace sd { namespace toolpanel {
44 ControlContainer::ControlContainer (TreeNode* pNode)
45 : mpNode(pNode),
46 mnActiveControlIndex((sal_uInt32)-1),
47 mbMultiSelection(false)
54 ControlContainer::~ControlContainer (void)
56 // Set mpNode to NULL so that no one calls it from now on.
57 mpNode = NULL;
58 DeleteChildren();
64 void ControlContainer::DeleteChildren (void)
66 // Deleting the children may lead to calls back to the container. To
67 // prevent the container from accessing the just deleted children, the
68 // maControlList member is first cleared (by transferring its content to
69 // a local list) before the children are destroyed.
70 ControlList maList;
71 maList.swap(maControlList);
72 ControlList::iterator I;
73 ControlList::iterator Iend (maList.end());
74 for (I=maList.begin(); I!=Iend; ++I)
75 delete *I;
77 if (mpNode != NULL)
78 mpNode->FireStateChangeEvent(EID_ALL_CHILDREN_REMOVED);
83 sal_uInt32 ControlContainer::AddControl (::std::auto_ptr<TreeNode> pControl)
85 ::osl::MutexGuard aGuard (maMutex);
87 pControl->GetWindow()->Show();
88 sal_uInt32 nIndex = maControlList.size();
89 maControlList.push_back (pControl.get());
90 pControl.release();
92 ListHasChanged ();
94 if (mpNode != NULL)
95 mpNode->FireStateChangeEvent(EID_CHILD_ADDED, pControl.get());
97 return nIndex;
103 void ControlContainer::SetExpansionState (
104 UINT32 nIndex,
105 ExpansionState aState)
107 ::osl::MutexGuard aGuard (maMutex);
109 bool bResizeNecessary (false);
111 if (mbMultiSelection)
113 TreeNode* pControl = GetControl(nIndex);
114 switch (aState)
116 case ES_TOGGLE:
117 bResizeNecessary = pControl->Expand( ! pControl->IsExpanded());
118 break;
120 case ES_EXPAND:
121 bResizeNecessary = pControl->Expand(true);
122 break;
124 case ES_COLLAPSE:
125 bResizeNecessary = pControl->Expand(false);
126 break;
129 else
131 // When bExpansionState is true then the control to expand is the
132 // one with the given index. If bExpansionState is false and the
133 // given index points to the active control then then following
134 // control (in cyclic order) it is expanded. When there is only one
135 // control then that is always expanded.
138 // Ignore a call with an invalid index. (The seperate comparison
139 // with -1 is not strictly necessary but it is here just in
140 // case.)
141 if (nIndex>=GetControlCount() || nIndex==(sal_uInt32)-1)
142 break;
144 bool bExpand;
145 switch (aState)
147 default:
148 case ES_TOGGLE:
149 bExpand = ! GetControl(nIndex)->IsExpanded();
150 break;
152 case ES_EXPAND:
153 bExpand = true;
154 break;
156 case ES_COLLAPSE:
157 bExpand = false;
158 break;
160 if (bExpand)
162 // Make the specified control the active one and expand it.
163 mnActiveControlIndex = nIndex;
165 else
167 if (nIndex == mnActiveControlIndex)
169 // We have to determine a new active control since the
170 // current one is about to be collapsed. Choose the
171 // previous one for the last and the next one for all
172 // other.
173 if (mnActiveControlIndex+1 == GetControlCount())
174 mnActiveControlIndex
175 = GetPreviousIndex(mnActiveControlIndex);
176 else
177 mnActiveControlIndex
178 = GetNextIndex (mnActiveControlIndex);
182 // Update the expansion state of all controls.
183 for (UINT32 i=0; i<GetControlCount(); i=GetNextIndex(i))
185 TreeNode* pControl = GetControl(i);
186 bResizeNecessary |= pControl->Expand(i == mnActiveControlIndex);
189 while (false);
192 if (bResizeNecessary && mpNode != NULL)
193 mpNode->RequestResize();
199 void ControlContainer::SetExpansionState (
200 TreeNode* pControl,
201 ExpansionState aState)
203 SetExpansionState (GetControlIndex(pControl), aState);
209 sal_uInt32 ControlContainer::GetControlIndex (TreeNode* pControlToExpand) const
211 sal_uInt32 nIndex;
212 for (nIndex=0; nIndex<GetControlCount(); nIndex++)
214 TreeNode* pControl = GetControl(nIndex);
215 if (pControl == pControlToExpand)
216 break;
218 return nIndex;
224 sal_uInt32 ControlContainer::GetActiveControlIndex (void) const
226 return mnActiveControlIndex;
232 void ControlContainer::ListHasChanged (void)
239 sal_uInt32 ControlContainer::GetControlCount (void) const
241 return maControlList.size();
247 sal_uInt32 ControlContainer::GetVisibleControlCount (void) const
249 sal_uInt32 nCount (0);
251 UINT32 nIndex;
252 sal_uInt32 nAllCount (maControlList.size());
253 for (nIndex=0; nIndex<nAllCount; nIndex=GetNextIndex(nIndex,true))
255 if (maControlList[nIndex]->GetWindow()->IsVisible())
256 nCount += 1;
259 return nCount;
265 TreeNode* ControlContainer::GetControl (sal_uInt32 nIndex) const
267 if (nIndex<maControlList.size() && nIndex!=(sal_uInt32)-1)
268 return maControlList[nIndex];
269 else
270 return NULL;
276 sal_uInt32 ControlContainer::GetPreviousIndex (
277 sal_uInt32 nIndex,
278 bool bIncludeHidden,
279 bool bCycle) const
281 sal_uInt32 nCandidate (nIndex);
283 while (true)
285 if (nCandidate==0)
286 if ( ! bCycle)
288 // We have reached the head of the list of controls and must
289 // not cycle to its end.
290 nCandidate = maControlList.size();
291 break;
293 else
295 // Cycle to the end of the list.
296 nCandidate = maControlList.size() - 1;
298 else
299 // Go to the regular predecessor.
300 nCandidate -= 1;
302 if (nCandidate == nIndex)
304 // Made one full loop and found no valid control.
305 nCandidate = maControlList.size();
306 break;
308 else if (bIncludeHidden)
310 // Return the candidate index regardless of whether the control
311 // is hidden or not.
312 break;
314 else if (maControlList[nCandidate]->GetWindow()->IsVisible())
316 // Found a visible control.
317 break;
320 // The candidate does not meet our constraints so do one more loop.
323 return nCandidate;
328 sal_uInt32 ControlContainer::GetNextIndex (
329 sal_uInt32 nIndex,
330 bool bIncludeHidden,
331 bool bCycle) const
333 sal_uInt32 nCandidate (nIndex);
335 while (true)
337 // Go to the regular successor.
338 nCandidate += 1;
339 if (nCandidate==maControlList.size())
341 if ( ! bCycle)
343 // We have reached the end of the list of controls and must
344 // not cycle to its head.
345 break;
347 else
349 // Cycle to the head of the list.
350 nCandidate = 0;
354 if (nCandidate == nIndex)
356 // Made one full loop and found no valid control.
357 nCandidate = maControlList.size();
358 break;
360 else if (bIncludeHidden)
362 // Return the candidate index regardless of whether the control
363 // is hidden or not.
364 break;
366 else if (maControlList[nCandidate]->GetWindow()->IsVisible())
368 // Found a visible control.
369 break;
372 // The candidate does not meet our constraints so do one more loop.
375 return nCandidate;
381 sal_uInt32 ControlContainer::GetFirstIndex (bool bIncludeHidden)
383 sal_uInt32 nIndex = 0;
385 if (maControlList.size() == 0)
387 // The list is empty so there is no first element.
388 nIndex = maControlList.size();
390 else if ( ! bIncludeHidden
391 && ! maControlList[nIndex]->GetWindow()->IsVisible())
393 // The first element is not visible. Go the next visible one.
394 nIndex = GetNextIndex (nIndex, bIncludeHidden, false);
397 return nIndex;
403 sal_uInt32 ControlContainer::GetLastIndex (bool bIncludeHidden)
405 sal_uInt32 nIndex;
407 if (maControlList.size() == 0)
409 // The list is empty so there is no last element.
410 nIndex = maControlList.size();
412 else
414 nIndex = maControlList.size() - 1;
415 if ( ! bIncludeHidden
416 && ! maControlList[nIndex]->GetWindow()->IsVisible())
418 // The last element is not visible. Go the previous visible one.
419 nIndex = GetPreviousIndex (nIndex, bIncludeHidden, false);
422 return nIndex;
428 void ControlContainer::SetMultiSelection (bool bFlag)
430 mbMultiSelection = bFlag;
436 void ControlContainer::SetVisibilityState (
437 sal_uInt32 nControlIndex,
438 VisibilityState aState)
440 TreeNode* pControl = GetControl (nControlIndex);
441 if (pControl != NULL)
443 bool bShow;
444 switch (aState)
446 default:
447 case VS_TOGGLE:
448 bShow = ! pControl->IsShowing();
449 break;
450 case VS_SHOW:
451 bShow = true;
452 break;
453 case VS_HIDE:
454 bShow = false;
455 break;
458 bool bControlWasExpanded = pControl->IsExpanded();
459 if (bShow != pControl->IsShowing())
461 pControl->Show (bShow);
463 if (bShow)
465 // If we just turned on the first control then expand it, too.
466 // If we turned on another control collapse it.
467 if (GetVisibleControlCount() == 1)
468 SetExpansionState (nControlIndex, ES_EXPAND);
469 else
470 SetExpansionState (nControlIndex, ES_COLLAPSE);
472 else
474 if (GetVisibleControlCount() > 0)
476 if (bControlWasExpanded)
478 // We turned off an expanded control. Make sure that
479 // one of the still visible ones is expanded.
480 sal_uInt32 nIndex = GetNextIndex(
481 nControlIndex,
482 false,
483 false);
484 if (nIndex == GetControlCount())
485 nIndex = GetPreviousIndex(
486 nControlIndex,
487 false,
488 false);
489 SetExpansionState (nIndex, ES_EXPAND);
494 if (mpNode != NULL)
495 mpNode->RequestResize();
503 } } // end of namespace ::sd::toolpanel