CWS-TOOLING: integrate CWS os150
[LibreOffice.git] / sd / source / ui / toolpanel / ControlContainer.cxx
blob5a0001f6265324584c050a0a24ebfda72d2835ad
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
31 #include "taskpane/ControlContainer.hxx"
33 #include "taskpane/TaskPaneTreeNode.hxx"
35 #include <vcl/window.hxx>
36 #include <vcl/svapp.hxx>
38 namespace sd { namespace toolpanel {
41 ControlContainer::ControlContainer (TreeNode* pNode)
42 : mpNode(pNode),
43 mnActiveControlIndex((sal_uInt32)-1),
44 mbMultiSelection(false)
51 ControlContainer::~ControlContainer (void)
53 // Set mpNode to NULL so that no one calls it from now on.
54 mpNode = NULL;
55 DeleteChildren();
61 void ControlContainer::DeleteChildren (void)
63 // Deleting the children may lead to calls back to the container. To
64 // prevent the container from accessing the just deleted children, the
65 // maControlList member is first cleared (by transferring its content to
66 // a local list) before the children are destroyed.
67 ControlList maList;
68 maList.swap(maControlList);
69 ControlList::iterator I;
70 ControlList::iterator Iend (maList.end());
71 for (I=maList.begin(); I!=Iend; ++I)
72 delete *I;
74 if (mpNode != NULL)
75 mpNode->FireStateChangeEvent(EID_ALL_CHILDREN_REMOVED);
80 sal_uInt32 ControlContainer::AddControl (::std::auto_ptr<TreeNode> pControl)
82 ::osl::MutexGuard aGuard (maMutex);
84 pControl->GetWindow()->Show();
85 sal_uInt32 nIndex = maControlList.size();
86 maControlList.push_back (pControl.get());
87 pControl.release();
89 ListHasChanged ();
91 if (mpNode != NULL)
92 mpNode->FireStateChangeEvent(EID_CHILD_ADDED, pControl.get());
94 return nIndex;
100 void ControlContainer::SetExpansionState (
101 sal_uInt32 nIndex,
102 ExpansionState aState)
104 ::osl::MutexGuard aGuard (maMutex);
106 bool bResizeNecessary (false);
108 if (mbMultiSelection)
110 TreeNode* pControl = GetControl(nIndex);
111 switch (aState)
113 case ES_TOGGLE:
114 bResizeNecessary = pControl->Expand( ! pControl->IsExpanded());
115 break;
117 case ES_EXPAND:
118 bResizeNecessary = pControl->Expand(true);
119 break;
121 case ES_COLLAPSE:
122 bResizeNecessary = pControl->Expand(false);
123 break;
126 else
128 // When bExpansionState is true then the control to expand is the
129 // one with the given index. If bExpansionState is false and the
130 // given index points to the active control then then following
131 // control (in cyclic order) it is expanded. When there is only one
132 // control then that is always expanded.
135 // Ignore a call with an invalid index. (The seperate comparison
136 // with -1 is not strictly necessary but it is here just in
137 // case.)
138 if (nIndex>=GetControlCount() || nIndex==(sal_uInt32)-1)
139 break;
141 bool bExpand;
142 switch (aState)
144 default:
145 case ES_TOGGLE:
146 bExpand = ! GetControl(nIndex)->IsExpanded();
147 break;
149 case ES_EXPAND:
150 bExpand = true;
151 break;
153 case ES_COLLAPSE:
154 bExpand = false;
155 break;
157 if (bExpand)
159 // Make the specified control the active one and expand it.
160 mnActiveControlIndex = nIndex;
162 else
164 if (nIndex == mnActiveControlIndex)
166 // We have to determine a new active control since the
167 // current one is about to be collapsed. Choose the
168 // previous one for the last and the next one for all
169 // other.
170 if (mnActiveControlIndex+1 == GetControlCount())
171 mnActiveControlIndex
172 = GetPreviousIndex(mnActiveControlIndex);
173 else
174 mnActiveControlIndex
175 = GetNextIndex (mnActiveControlIndex);
179 // Update the expansion state of all controls.
180 for (sal_uInt32 i=0; i<GetControlCount(); i=GetNextIndex(i))
182 TreeNode* pControl = GetControl(i);
183 bResizeNecessary |= pControl->Expand(i == mnActiveControlIndex);
186 while (false);
189 if (bResizeNecessary && mpNode != NULL)
190 mpNode->RequestResize();
196 void ControlContainer::SetExpansionState (
197 TreeNode* pControl,
198 ExpansionState aState)
200 SetExpansionState (GetControlIndex(pControl), aState);
206 sal_uInt32 ControlContainer::GetControlIndex (TreeNode* pControlToExpand) const
208 sal_uInt32 nIndex;
209 for (nIndex=0; nIndex<GetControlCount(); nIndex++)
211 TreeNode* pControl = GetControl(nIndex);
212 if (pControl == pControlToExpand)
213 break;
215 return nIndex;
221 void ControlContainer::ListHasChanged (void)
228 sal_uInt32 ControlContainer::GetControlCount (void) const
230 return maControlList.size();
236 sal_uInt32 ControlContainer::GetVisibleControlCount (void) const
238 sal_uInt32 nCount (0);
240 sal_uInt32 nIndex;
241 sal_uInt32 nAllCount (maControlList.size());
242 for (nIndex=0; nIndex<nAllCount; nIndex=GetNextIndex(nIndex,true))
244 if (maControlList[nIndex]->GetWindow()->IsVisible())
245 nCount += 1;
248 return nCount;
254 TreeNode* ControlContainer::GetControl (sal_uInt32 nIndex) const
256 if (nIndex<maControlList.size() && nIndex!=(sal_uInt32)-1)
257 return maControlList[nIndex];
258 else
259 return NULL;
265 sal_uInt32 ControlContainer::GetPreviousIndex (
266 sal_uInt32 nIndex,
267 bool bIncludeHidden,
268 bool bCycle) const
270 sal_uInt32 nCandidate (nIndex);
272 while (true)
274 if (nCandidate==0)
275 if ( ! bCycle)
277 // We have reached the head of the list of controls and must
278 // not cycle to its end.
279 nCandidate = maControlList.size();
280 break;
282 else
284 // Cycle to the end of the list.
285 nCandidate = maControlList.size() - 1;
287 else
288 // Go to the regular predecessor.
289 nCandidate -= 1;
291 if (nCandidate == nIndex)
293 // Made one full loop and found no valid control.
294 nCandidate = maControlList.size();
295 break;
297 else if (bIncludeHidden)
299 // Return the candidate index regardless of whether the control
300 // is hidden or not.
301 break;
303 else if (maControlList[nCandidate]->GetWindow()->IsVisible())
305 // Found a visible control.
306 break;
309 // The candidate does not meet our constraints so do one more loop.
312 return nCandidate;
317 sal_uInt32 ControlContainer::GetNextIndex (
318 sal_uInt32 nIndex,
319 bool bIncludeHidden,
320 bool bCycle) const
322 sal_uInt32 nCandidate (nIndex);
324 while (true)
326 // Go to the regular successor.
327 nCandidate += 1;
328 if (nCandidate==maControlList.size())
330 if ( ! bCycle)
332 // We have reached the end of the list of controls and must
333 // not cycle to its head.
334 break;
336 else
338 // Cycle to the head of the list.
339 nCandidate = 0;
343 if (nCandidate == nIndex)
345 // Made one full loop and found no valid control.
346 nCandidate = maControlList.size();
347 break;
349 else if (bIncludeHidden)
351 // Return the candidate index regardless of whether the control
352 // is hidden or not.
353 break;
355 else if (maControlList[nCandidate]->GetWindow()->IsVisible())
357 // Found a visible control.
358 break;
361 // The candidate does not meet our constraints so do one more loop.
364 return nCandidate;
370 void ControlContainer::SetMultiSelection (bool bFlag)
372 mbMultiSelection = bFlag;
378 void ControlContainer::SetVisibilityState (
379 sal_uInt32 nControlIndex,
380 VisibilityState aState)
382 TreeNode* pControl = GetControl (nControlIndex);
383 if (pControl != NULL)
385 bool bShow;
386 switch (aState)
388 default:
389 case VS_TOGGLE:
390 bShow = ! pControl->IsShowing();
391 break;
392 case VS_SHOW:
393 bShow = true;
394 break;
395 case VS_HIDE:
396 bShow = false;
397 break;
400 bool bControlWasExpanded = pControl->IsExpanded();
401 if (bShow != pControl->IsShowing())
403 pControl->Show (bShow);
405 if (bShow)
407 // If we just turned on the first control then expand it, too.
408 // If we turned on another control collapse it.
409 if (GetVisibleControlCount() == 1)
410 SetExpansionState (nControlIndex, ES_EXPAND);
411 else
412 SetExpansionState (nControlIndex, ES_COLLAPSE);
414 else
416 if (GetVisibleControlCount() > 0)
418 if (bControlWasExpanded)
420 // We turned off an expanded control. Make sure that
421 // one of the still visible ones is expanded.
422 sal_uInt32 nIndex = GetNextIndex(
423 nControlIndex,
424 false,
425 false);
426 if (nIndex == GetControlCount())
427 nIndex = GetPreviousIndex(
428 nControlIndex,
429 false,
430 false);
431 SetExpansionState (nIndex, ES_EXPAND);
436 if (mpNode != NULL)
437 mpNode->RequestResize();
445 } } // end of namespace ::sd::toolpanel