bump product version to 4.1.6.2
[LibreOffice.git] / sd / source / ui / toolpanel / ControlContainer.cxx
blob25c3cf30ce673fccd5566e0c9d93b8b641b7eca0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "taskpane/ControlContainer.hxx"
23 #include "taskpane/TaskPaneTreeNode.hxx"
25 #include <vcl/window.hxx>
26 #include <vcl/svapp.hxx>
28 namespace sd { namespace toolpanel {
31 ControlContainer::ControlContainer (TreeNode* pNode)
32 : mpNode(pNode),
33 mnActiveControlIndex((sal_uInt32)-1),
34 mbMultiSelection(false)
41 ControlContainer::~ControlContainer (void)
43 // Set mpNode to NULL so that no one calls it from now on.
44 mpNode = NULL;
45 DeleteChildren();
51 void ControlContainer::DeleteChildren (void)
53 // Deleting the children may lead to calls back to the container. To
54 // prevent the container from accessing the just deleted children, the
55 // maControlList member is first cleared (by transferring its content to
56 // a local list) before the children are destroyed.
57 ControlList maList;
58 maList.swap(maControlList);
59 ControlList::iterator I;
60 ControlList::iterator Iend (maList.end());
61 for (I=maList.begin(); I!=Iend; ++I)
62 delete *I;
64 if (mpNode != NULL)
65 mpNode->FireStateChangeEvent(EID_ALL_CHILDREN_REMOVED);
70 sal_uInt32 ControlContainer::AddControl (::std::auto_ptr<TreeNode> pControl)
72 ::osl::MutexGuard aGuard (maMutex);
74 pControl->GetWindow()->Show();
75 sal_uInt32 nIndex = maControlList.size();
76 maControlList.push_back (pControl.get());
77 pControl.release();
79 ListHasChanged ();
81 if (mpNode != NULL)
82 mpNode->FireStateChangeEvent(EID_CHILD_ADDED, pControl.get());
84 return nIndex;
90 void ControlContainer::SetExpansionState (
91 sal_uInt32 nIndex,
92 ExpansionState aState)
94 ::osl::MutexGuard aGuard (maMutex);
96 bool bResizeNecessary (false);
98 if (mbMultiSelection)
100 TreeNode* pControl = GetControl(nIndex);
101 switch (aState)
103 case ES_TOGGLE:
104 bResizeNecessary = pControl->Expand( ! pControl->IsExpanded());
105 break;
107 case ES_EXPAND:
108 bResizeNecessary = pControl->Expand(true);
109 break;
111 case ES_COLLAPSE:
112 bResizeNecessary = pControl->Expand(false);
113 break;
116 else
118 // When bExpansionState is true then the control to expand is the
119 // one with the given index. If bExpansionState is false and the
120 // given index points to the active control then then following
121 // control (in cyclic order) it is expanded. When there is only one
122 // control then that is always expanded.
125 // Ignore a call with an invalid index. (The separate comparison
126 // with -1 is not strictly necessary but it is here just in
127 // case.)
128 if (nIndex>=GetControlCount() || nIndex==(sal_uInt32)-1)
129 break;
131 bool bExpand;
132 switch (aState)
134 default:
135 case ES_TOGGLE:
136 bExpand = ! GetControl(nIndex)->IsExpanded();
137 break;
139 case ES_EXPAND:
140 bExpand = true;
141 break;
143 case ES_COLLAPSE:
144 bExpand = false;
145 break;
147 if (bExpand)
149 // Make the specified control the active one and expand it.
150 mnActiveControlIndex = nIndex;
152 else
154 if (nIndex == mnActiveControlIndex)
156 // We have to determine a new active control since the
157 // current one is about to be collapsed. Choose the
158 // previous one for the last and the next one for all
159 // other.
160 if (mnActiveControlIndex+1 == GetControlCount())
161 mnActiveControlIndex
162 = GetPreviousIndex(mnActiveControlIndex);
163 else
164 mnActiveControlIndex
165 = GetNextIndex (mnActiveControlIndex);
169 // Update the expansion state of all controls.
170 for (sal_uInt32 i=0; i<GetControlCount(); i=GetNextIndex(i))
172 TreeNode* pControl = GetControl(i);
173 bResizeNecessary |= pControl->Expand(i == mnActiveControlIndex);
176 while (false);
179 if (bResizeNecessary && mpNode != NULL)
180 mpNode->RequestResize();
186 void ControlContainer::SetExpansionState (
187 TreeNode* pControl,
188 ExpansionState aState)
190 SetExpansionState (GetControlIndex(pControl), aState);
196 sal_uInt32 ControlContainer::GetControlIndex (TreeNode* pControlToExpand) const
198 sal_uInt32 nIndex;
199 for (nIndex=0; nIndex<GetControlCount(); nIndex++)
201 TreeNode* pControl = GetControl(nIndex);
202 if (pControl == pControlToExpand)
203 break;
205 return nIndex;
211 void ControlContainer::ListHasChanged (void)
218 sal_uInt32 ControlContainer::GetControlCount (void) const
220 return maControlList.size();
226 sal_uInt32 ControlContainer::GetVisibleControlCount (void) const
228 sal_uInt32 nCount (0);
230 sal_uInt32 nIndex;
231 sal_uInt32 nAllCount (maControlList.size());
232 for (nIndex=0; nIndex<nAllCount; nIndex=GetNextIndex(nIndex,true))
234 if (maControlList[nIndex]->GetWindow()->IsVisible())
235 nCount += 1;
238 return nCount;
244 TreeNode* ControlContainer::GetControl (sal_uInt32 nIndex) const
246 if (nIndex<maControlList.size() && nIndex!=(sal_uInt32)-1)
247 return maControlList[nIndex];
248 else
249 return NULL;
255 sal_uInt32 ControlContainer::GetPreviousIndex (
256 sal_uInt32 nIndex,
257 bool bIncludeHidden,
258 bool bCycle) const
260 sal_uInt32 nCandidate (nIndex);
262 while (true)
264 if (nCandidate==0)
265 if ( ! bCycle)
267 // We have reached the head of the list of controls and must
268 // not cycle to its end.
269 nCandidate = maControlList.size();
270 break;
272 else
274 // Cycle to the end of the list.
275 nCandidate = maControlList.size() - 1;
277 else
278 // Go to the regular predecessor.
279 nCandidate -= 1;
281 if (nCandidate == nIndex)
283 // Made one full loop and found no valid control.
284 nCandidate = maControlList.size();
285 break;
287 else if (bIncludeHidden)
289 // Return the candidate index regardless of whether the control
290 // is hidden or not.
291 break;
293 else if (maControlList[nCandidate]->GetWindow()->IsVisible())
295 // Found a visible control.
296 break;
299 // The candidate does not meet our constraints so do one more loop.
302 return nCandidate;
307 sal_uInt32 ControlContainer::GetNextIndex (
308 sal_uInt32 nIndex,
309 bool bIncludeHidden,
310 bool bCycle) const
312 sal_uInt32 nCandidate (nIndex);
314 while (true)
316 // Go to the regular successor.
317 nCandidate += 1;
318 if (nCandidate==maControlList.size())
320 if ( ! bCycle)
322 // We have reached the end of the list of controls and must
323 // not cycle to its head.
324 break;
326 else
328 // Cycle to the head of the list.
329 nCandidate = 0;
333 if (nCandidate == nIndex)
335 // Made one full loop and found no valid control.
336 nCandidate = maControlList.size();
337 break;
339 else if (bIncludeHidden)
341 // Return the candidate index regardless of whether the control
342 // is hidden or not.
343 break;
345 else if (maControlList[nCandidate]->GetWindow()->IsVisible())
347 // Found a visible control.
348 break;
351 // The candidate does not meet our constraints so do one more loop.
354 return nCandidate;
360 void ControlContainer::SetMultiSelection (bool bFlag)
362 mbMultiSelection = bFlag;
368 void ControlContainer::SetVisibilityState (
369 sal_uInt32 nControlIndex,
370 VisibilityState aState)
372 TreeNode* pControl = GetControl (nControlIndex);
373 if (pControl != NULL)
375 bool bShow;
376 switch (aState)
378 default:
379 case VS_TOGGLE:
380 bShow = ! pControl->IsShowing();
381 break;
382 case VS_SHOW:
383 bShow = true;
384 break;
385 case VS_HIDE:
386 bShow = false;
387 break;
390 bool bControlWasExpanded = pControl->IsExpanded();
391 if (bShow != pControl->IsShowing())
393 pControl->Show (bShow);
395 if (bShow)
397 // If we just turned on the first control then expand it, too.
398 // If we turned on another control collapse it.
399 if (GetVisibleControlCount() == 1)
400 SetExpansionState (nControlIndex, ES_EXPAND);
401 else
402 SetExpansionState (nControlIndex, ES_COLLAPSE);
404 else
406 if (GetVisibleControlCount() > 0)
408 if (bControlWasExpanded)
410 // We turned off an expanded control. Make sure that
411 // one of the still visible ones is expanded.
412 sal_uInt32 nIndex = GetNextIndex(
413 nControlIndex,
414 false,
415 false);
416 if (nIndex == GetControlCount())
417 nIndex = GetPreviousIndex(
418 nControlIndex,
419 false,
420 false);
421 SetExpansionState (nIndex, ES_EXPAND);
426 if (mpNode != NULL)
427 mpNode->RequestResize();
435 } } // end of namespace ::sd::toolpanel
437 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */