1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #define _TASKBAR_CXX
32 
33 #include <tools/list.hxx>
34 #include <tools/debug.hxx>
35 #include <vcl/help.hxx>
36 #include <svtools/taskbar.hxx>
37 
38 // =======================================================================
39 
40 TaskButtonBar::TaskButtonBar( Window* pParent, WinBits nWinStyle ) :
41 	ToolBox( pParent, nWinStyle | WB_3DLOOK )
42 {
43 	SetAlign( WINDOWALIGN_BOTTOM );
44 	SetButtonType( BUTTON_SYMBOLTEXT );
45 }
46 
47 // -----------------------------------------------------------------------
48 
49 TaskButtonBar::~TaskButtonBar()
50 {
51 }
52 
53 // -----------------------------------------------------------------------
54 
55 void TaskButtonBar::RequestHelp( const HelpEvent& rHEvt )
56 {
57 	ToolBox::RequestHelp( rHEvt );
58 }
59 
60 // =======================================================================
61 
62 WindowArrange::WindowArrange()
63 {
64 	mpWinList = new List;
65 }
66 
67 // -----------------------------------------------------------------------
68 
69 WindowArrange::~WindowArrange()
70 {
71 	delete mpWinList;
72 }
73 
74 // -----------------------------------------------------------------------
75 
76 static sal_uInt16 ImplCeilSqareRoot( sal_uInt16 nVal )
77 {
78 	sal_uInt16 i;
79 
80 	// Ueberlauf verhindern
81 	if ( nVal > 0xFE * 0xFE )
82 		return 0xFE;
83 
84 	for ( i=0; i*i < nVal; i++ )
85 		{}
86 
87 	return i;
88 }
89 
90 // -----------------------------------------------------------------------
91 
92 static void ImplPosSizeWindow( Window* pWindow,
93 							   long nX, long nY, long nWidth, long nHeight )
94 {
95 	if ( nWidth < 32 )
96 		nWidth = 32;
97 	if ( nHeight < 24 )
98 		nHeight = 24;
99 	pWindow->SetPosSizePixel( nX, nY, nWidth, nHeight );
100 }
101 
102 // -----------------------------------------------------------------------
103 
104 void WindowArrange::ImplTile( const Rectangle& rRect )
105 {
106 	sal_uInt16 nCount = (sal_uInt16)mpWinList->Count();
107 	if ( nCount < 3 )
108 	{
109 		ImplVert( rRect );
110 		return;
111 	}
112 
113 	sal_uInt16		i;
114 	sal_uInt16		j;
115 	sal_uInt16		nCols;
116 	sal_uInt16		nRows;
117 	sal_uInt16		nActRows;
118 	sal_uInt16		nOffset;
119 	long		nOverWidth;
120 	long		nOverHeight;
121 	Window* 	pWindow;
122 	long		nX = rRect.Left();
123 	long		nY = rRect.Top();
124 	long		nWidth = rRect.GetWidth();
125 	long		nHeight = rRect.GetHeight();
126 	long		nRectY = nY;
127 	long		nRectWidth = nWidth;
128 	long		nRectHeight = nHeight;
129 	long		nTempWidth;
130 	long		nTempHeight;
131 
132 	nCols	= ImplCeilSqareRoot( nCount );
133 	nOffset = (nCols*nCols) - nCount;
134 	if ( nOffset >= nCols )
135 	{
136 		nRows	 = nCols -1;
137 		nOffset = nOffset - nCols;
138 	}
139 	else
140 		nRows = nCols;
141 
142 	nWidth /= nCols;
143 	if ( nWidth < 1 )
144 		nWidth = 1;
145 	nOverWidth = nRectWidth-(nWidth*nCols);
146 
147 	pWindow = (Window*)mpWinList->First();
148 	for ( i = 0; i < nCols; i++ )
149 	{
150 		if ( i < nOffset )
151 			nActRows = nRows - 1;
152 		else
153 			nActRows = nRows;
154 
155 		nTempWidth = nWidth;
156 		if ( nOverWidth > 0 )
157 		{
158 			nTempWidth++;
159 			nOverWidth--;
160 		}
161 
162 		nHeight = nRectHeight / nActRows;
163 		if ( nHeight < 1 )
164 			nHeight = 1;
165 		nOverHeight = nRectHeight-(nHeight*nActRows);
166 		for ( j = 0; j < nActRows; j++ )
167 		{
168 			// Ueberhang verteilen
169 			nTempHeight = nHeight;
170 			if ( nOverHeight > 0 )
171 			{
172 				nTempHeight++;
173 				nOverHeight--;
174 			}
175 			ImplPosSizeWindow( pWindow, nX, nY, nTempWidth, nTempHeight );
176 			nY += nTempHeight;
177 
178 			pWindow = (Window*)mpWinList->Next();
179 			if ( !pWindow )
180 				break;
181 		}
182 
183 		nX += nWidth;
184 		nY = nRectY;
185 
186 		if ( !pWindow )
187 			break;
188 	}
189 }
190 
191 // -----------------------------------------------------------------------
192 
193 void WindowArrange::ImplHorz( const Rectangle& rRect )
194 {
195 	long		nCount = (long)mpWinList->Count();
196 	long		nX = rRect.Left();
197 	long		nY = rRect.Top();
198 	long		nWidth = rRect.GetWidth();
199 	long		nHeight = rRect.GetHeight();
200 	long		nRectHeight = nHeight;
201 	long		nOver;
202 	long		nTempHeight;
203 	Window* 	pWindow;
204 
205 	nHeight /= nCount;
206 	if ( nHeight < 1 )
207 		nHeight = 1;
208 	nOver = nRectHeight - (nCount*nHeight);
209 	pWindow = (Window*)mpWinList->First();
210 	while ( pWindow )
211 	{
212 		nTempHeight = nHeight;
213 		if ( nOver > 0 )
214 		{
215 			nTempHeight++;
216 			nOver--;
217 		}
218 		ImplPosSizeWindow( pWindow, nX, nY, nWidth, nTempHeight );
219 		nY += nTempHeight;
220 
221 		pWindow = (Window*)mpWinList->Next();
222 	}
223 }
224 
225 // -----------------------------------------------------------------------
226 
227 void WindowArrange::ImplVert( const Rectangle& rRect )
228 {
229 	long		nCount = (long)mpWinList->Count();
230 	long		nX = rRect.Left();
231 	long		nY = rRect.Top();
232 	long		nWidth = rRect.GetWidth();
233 	long		nHeight = rRect.GetHeight();
234 	long		nRectWidth = nWidth;
235 	long		nOver;
236 	long		nTempWidth;
237 	Window* 	pWindow;
238 
239 	nWidth /= nCount;
240 	if ( nWidth < 1 )
241 		nWidth = 1;
242 	nOver = nRectWidth - (nCount*nWidth);
243 	pWindow = (Window*)mpWinList->First();
244 	while ( pWindow )
245 	{
246 		nTempWidth = nWidth;
247 		if ( nOver > 0 )
248 		{
249 			nTempWidth++;
250 			nOver--;
251 		}
252 		ImplPosSizeWindow( pWindow, nX, nY, nTempWidth, nHeight );
253 		nX += nTempWidth;
254 
255 		pWindow = (Window*)mpWinList->Next();
256 	}
257 }
258 
259 // -----------------------------------------------------------------------
260 
261 void WindowArrange::ImplCascade( const Rectangle& rRect )
262 {
263 	long		nX = rRect.Left();
264 	long		nY = rRect.Top();
265 	long		nWidth = rRect.GetWidth();
266 	long		nHeight = rRect.GetHeight();
267 	long		nRectWidth = nWidth;
268 	long		nRectHeight = nHeight;
269 	long		nOff;
270 	long		nCascadeWins;
271 	sal_Int32	nLeftBorder;
272 	sal_Int32	nTopBorder;
273 	sal_Int32	nRightBorder;
274 	sal_Int32	nBottomBorder;
275 	long		nStartOverWidth;
276 	long		nStartOverHeight;
277 	long		nOverWidth = 0;
278 	long		nOverHeight = 0;
279 	long		nTempX;
280 	long		nTempY;
281 	long		nTempWidth;
282 	long		nTempHeight;
283 	long		i;
284 	Window* 	pWindow;
285 	Window* 	pTempWindow;
286 
287 	// Border-Fenster suchen um den Versatz zu ermitteln
288 	pTempWindow = (Window*)mpWinList->First();
289 	pTempWindow->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
290 	while ( !nTopBorder )
291 	{
292 		Window* pBrdWin = pTempWindow->GetWindow( WINDOW_REALPARENT );
293 		if ( !pBrdWin || (pBrdWin->GetWindow( WINDOW_CLIENT ) != pTempWindow) )
294 			break;
295 		pTempWindow = pBrdWin;
296 		pTempWindow->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
297 	}
298 	if ( !nTopBorder )
299 		nTopBorder = 22;
300 	nOff = nTopBorder;
301 
302 	nCascadeWins = nRectHeight / 3 / nOff;
303 	if ( !nCascadeWins )
304 		nCascadeWins = 1;
305 	nWidth	 -= nCascadeWins*nOff;
306 	nHeight  -= nCascadeWins*nOff;
307 	if ( nWidth < 1 )
308 		nWidth = 1;
309 	if ( nHeight < 1 )
310 		nHeight = 1;
311 
312 	nStartOverWidth = nRectWidth-(nWidth+(nCascadeWins*nOff));
313 	nStartOverHeight = nRectHeight-(nHeight+(nCascadeWins*nOff));
314 
315 	i = 0;
316 	pWindow = (Window*)mpWinList->First();
317 	while ( pWindow )
318 	{
319 		if ( !i )
320 		{
321 			nOverWidth = nStartOverWidth;
322 			nOverHeight = nStartOverHeight;
323 		}
324 
325 		// Position
326 		nTempX = nX + (i*nOff);
327 		nTempY = nY + (i*nOff);
328 
329 		// Ueberhang verteilen
330 		nTempWidth = nWidth;
331 		if ( nOverWidth > 0 )
332 		{
333 			nTempWidth++;
334 			nOverWidth--;
335 		}
336 		nTempHeight = nHeight;
337 		if ( nOverHeight > 0 )
338 		{
339 			nTempHeight++;
340 			nOverHeight--;
341 		}
342 
343 		ImplPosSizeWindow( pWindow, nTempX, nTempY, nTempWidth, nTempHeight );
344 
345 		if ( i < nCascadeWins )
346 			i++;
347 		else
348 			i = 0;
349 
350 		pWindow = (Window*)mpWinList->Next();
351 	}
352 }
353 
354 // -----------------------------------------------------------------------
355 
356 void WindowArrange::Arrange( sal_uInt16 nType, const Rectangle& rRect )
357 {
358 	if ( !mpWinList->Count() )
359 		return;
360 
361 	switch ( nType )
362 	{
363 		case WINDOWARRANGE_TILE:
364 			ImplTile( rRect );
365 			break;
366 		case WINDOWARRANGE_HORZ:
367 			ImplHorz( rRect );
368 			break;
369 		case WINDOWARRANGE_VERT:
370 			ImplVert( rRect );
371 			break;
372 		case WINDOWARRANGE_CASCADE:
373 			ImplCascade( rRect );
374 			break;
375 	}
376 }
377 
378