xref: /AOO41X/main/vcl/source/window/split.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9f62ea84SAndrew Rist  * distributed with this work for additional information
6*9f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*9f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*9f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist  * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
17*9f62ea84SAndrew Rist  * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*9f62ea84SAndrew Rist  *************************************************************/
21*9f62ea84SAndrew Rist 
22*9f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <tools/rc.h>
28cdf0e10cSrcweir #include <tools/poly.hxx>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <vcl/event.hxx>
31cdf0e10cSrcweir #include <vcl/split.hxx>
32cdf0e10cSrcweir #include <vcl/svapp.hxx>
33cdf0e10cSrcweir #include <vcl/syswin.hxx>
34cdf0e10cSrcweir #include <vcl/taskpanelist.hxx>
35cdf0e10cSrcweir #include <vcl/gradient.hxx>
36cdf0e10cSrcweir #include <vcl/lineinfo.hxx>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include <rtl/instance.hxx>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include <window.h>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir namespace
43cdf0e10cSrcweir {
44cdf0e10cSrcweir     struct ImplBlackWall
45cdf0e10cSrcweir         : public rtl::StaticWithInit<Wallpaper, ImplBlackWall> {
46cdf0e10cSrcweir         Wallpaper operator () () {
47cdf0e10cSrcweir             return Wallpaper(COL_BLACK);
48cdf0e10cSrcweir         }
49cdf0e10cSrcweir     };
50cdf0e10cSrcweir     struct ImplWhiteWall
51cdf0e10cSrcweir         : public rtl::StaticWithInit<Wallpaper, ImplWhiteWall> {
52cdf0e10cSrcweir         Wallpaper operator () () {
53cdf0e10cSrcweir             return Wallpaper(COL_LIGHTGRAY);
54cdf0e10cSrcweir         }
55cdf0e10cSrcweir     };
56cdf0e10cSrcweir }
57cdf0e10cSrcweir 
58cdf0e10cSrcweir // =======================================================================
59cdf0e10cSrcweir 
60cdf0e10cSrcweir void Splitter::ImplInitSplitterData()
61cdf0e10cSrcweir {
62cdf0e10cSrcweir     ImplGetWindowImpl()->mbSplitter        = sal_True;
63cdf0e10cSrcweir 	mpRefWin		  = NULL;
64cdf0e10cSrcweir 	mnSplitPos		  = 0;
65cdf0e10cSrcweir 	mnLastSplitPos	  = 0;
66cdf0e10cSrcweir 	mnStartSplitPos   = 0;
67cdf0e10cSrcweir 	mbDragFull		  = sal_False;
68cdf0e10cSrcweir     mbKbdSplitting    = sal_False;
69cdf0e10cSrcweir     mbInKeyEvent      = 0;
70cdf0e10cSrcweir     mnKeyboardStepSize = SPLITTER_DEFAULTSTEPSIZE;
71cdf0e10cSrcweir }
72cdf0e10cSrcweir 
73cdf0e10cSrcweir // -----------------------------------------------------------------------
74cdf0e10cSrcweir 
75cdf0e10cSrcweir void Splitter::ImplInit( Window* pParent, WinBits nWinStyle )
76cdf0e10cSrcweir {
77cdf0e10cSrcweir 	Window::ImplInit( pParent, nWinStyle, NULL );
78cdf0e10cSrcweir 
79cdf0e10cSrcweir 	mpRefWin = pParent;
80cdf0e10cSrcweir 
81cdf0e10cSrcweir 	const StyleSettings& rSettings = GetSettings().GetStyleSettings();
82cdf0e10cSrcweir 	long nA = rSettings.GetScrollBarSize();
83cdf0e10cSrcweir 	long nB = rSettings.GetSplitSize();
84cdf0e10cSrcweir 
85cdf0e10cSrcweir 	PointerStyle ePointerStyle;
86cdf0e10cSrcweir 
87cdf0e10cSrcweir 	if ( nWinStyle & WB_HSCROLL )
88cdf0e10cSrcweir 	{
89cdf0e10cSrcweir 		ePointerStyle = POINTER_HSPLIT;
90cdf0e10cSrcweir 		mbHorzSplit = sal_True;
91cdf0e10cSrcweir 		SetSizePixel( Size( nB, nA ) );
92cdf0e10cSrcweir 	}
93cdf0e10cSrcweir 	else
94cdf0e10cSrcweir 	{
95cdf0e10cSrcweir 		ePointerStyle = POINTER_VSPLIT;
96cdf0e10cSrcweir 		mbHorzSplit = sal_False;
97cdf0e10cSrcweir 		SetSizePixel( Size( nA, nB ) );
98cdf0e10cSrcweir 	}
99cdf0e10cSrcweir 
100cdf0e10cSrcweir 	SetPointer( Pointer( ePointerStyle ) );
101cdf0e10cSrcweir 
102cdf0e10cSrcweir     if( GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
103cdf0e10cSrcweir 	    SetBackground( ImplWhiteWall::get() );
104cdf0e10cSrcweir     else
105cdf0e10cSrcweir 	    SetBackground( ImplBlackWall::get() );
106cdf0e10cSrcweir 
107cdf0e10cSrcweir     TaskPaneList *pTList = GetSystemWindow()->GetTaskPaneList();
108cdf0e10cSrcweir     pTList->AddWindow( this );
109cdf0e10cSrcweir }
110cdf0e10cSrcweir 
111cdf0e10cSrcweir // -----------------------------------------------------------------------
112cdf0e10cSrcweir 
113cdf0e10cSrcweir void Splitter::ImplSplitMousePos( Point& rPos )
114cdf0e10cSrcweir {
115cdf0e10cSrcweir 	if ( mbHorzSplit )
116cdf0e10cSrcweir 	{
117cdf0e10cSrcweir 		if ( rPos.X() > maDragRect.Right()-1 )
118cdf0e10cSrcweir 			rPos.X() = maDragRect.Right()-1;
119cdf0e10cSrcweir 		if ( rPos.X() < maDragRect.Left()+1 )
120cdf0e10cSrcweir 			rPos.X() = maDragRect.Left()+1;
121cdf0e10cSrcweir 	}
122cdf0e10cSrcweir 	else
123cdf0e10cSrcweir 	{
124cdf0e10cSrcweir 		if ( rPos.Y() > maDragRect.Bottom()-1 )
125cdf0e10cSrcweir 			rPos.Y() = maDragRect.Bottom()-1;
126cdf0e10cSrcweir 		if ( rPos.Y() < maDragRect.Top()+1 )
127cdf0e10cSrcweir 			rPos.Y() = maDragRect.Top()+1;
128cdf0e10cSrcweir 	}
129cdf0e10cSrcweir }
130cdf0e10cSrcweir 
131cdf0e10cSrcweir // -----------------------------------------------------------------------
132cdf0e10cSrcweir 
133cdf0e10cSrcweir void Splitter::ImplDrawSplitter()
134cdf0e10cSrcweir {
135cdf0e10cSrcweir 	Rectangle aInvRect( maDragRect );
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 	if ( mbHorzSplit )
138cdf0e10cSrcweir 	{
139cdf0e10cSrcweir 		aInvRect.Left() 	= maDragPos.X() - 1;
140cdf0e10cSrcweir 		aInvRect.Right()	= maDragPos.X() + 1;
141cdf0e10cSrcweir 	}
142cdf0e10cSrcweir 	else
143cdf0e10cSrcweir 	{
144cdf0e10cSrcweir 		aInvRect.Top()		= maDragPos.Y() - 1;
145cdf0e10cSrcweir 		aInvRect.Bottom()	= maDragPos.Y() + 1;
146cdf0e10cSrcweir 	}
147cdf0e10cSrcweir 
148cdf0e10cSrcweir 	mpRefWin->InvertTracking( mpRefWin->PixelToLogic(aInvRect), SHOWTRACK_SPLIT );
149cdf0e10cSrcweir }
150cdf0e10cSrcweir 
151cdf0e10cSrcweir // -----------------------------------------------------------------------
152cdf0e10cSrcweir 
153cdf0e10cSrcweir Splitter::Splitter( Window* pParent, WinBits nStyle ) :
154cdf0e10cSrcweir 	Window( WINDOW_SPLITTER )
155cdf0e10cSrcweir {
156cdf0e10cSrcweir 	ImplInitSplitterData();
157cdf0e10cSrcweir 	ImplInit( pParent, nStyle );
158cdf0e10cSrcweir }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir // -----------------------------------------------------------------------
161cdf0e10cSrcweir 
162cdf0e10cSrcweir Splitter::Splitter( Window* pParent, const ResId& rResId ) :
163cdf0e10cSrcweir 	Window( WINDOW_SPLITTER )
164cdf0e10cSrcweir {
165cdf0e10cSrcweir 	ImplInitSplitterData();
166cdf0e10cSrcweir 	rResId.SetRT( RSC_SPLITTER );
167cdf0e10cSrcweir 	WinBits nStyle = ImplInitRes( rResId );
168cdf0e10cSrcweir 	ImplInit( pParent, nStyle );
169cdf0e10cSrcweir 	ImplLoadRes( rResId );
170cdf0e10cSrcweir 
171cdf0e10cSrcweir 	if ( !(nStyle & WB_HIDE) )
172cdf0e10cSrcweir 		Show();
173cdf0e10cSrcweir }
174cdf0e10cSrcweir 
175cdf0e10cSrcweir // -----------------------------------------------------------------------
176cdf0e10cSrcweir 
177cdf0e10cSrcweir Splitter::~Splitter()
178cdf0e10cSrcweir {
179cdf0e10cSrcweir     TaskPaneList *pTList = GetSystemWindow()->GetTaskPaneList();
180cdf0e10cSrcweir     pTList->RemoveWindow( this );
181cdf0e10cSrcweir }
182cdf0e10cSrcweir 
183cdf0e10cSrcweir // -----------------------------------------------------------------------
184cdf0e10cSrcweir 
185cdf0e10cSrcweir void Splitter::SetKeyboardStepSize( long nStepSize )
186cdf0e10cSrcweir {
187cdf0e10cSrcweir     mnKeyboardStepSize = nStepSize;
188cdf0e10cSrcweir }
189cdf0e10cSrcweir 
190cdf0e10cSrcweir // -----------------------------------------------------------------------
191cdf0e10cSrcweir 
192cdf0e10cSrcweir long Splitter::GetKeyboardStepSize() const
193cdf0e10cSrcweir {
194cdf0e10cSrcweir     return mnKeyboardStepSize;
195cdf0e10cSrcweir }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir // -----------------------------------------------------------------------
198cdf0e10cSrcweir 
199cdf0e10cSrcweir Splitter* Splitter::ImplFindSibling()
200cdf0e10cSrcweir {
201cdf0e10cSrcweir     // look for another splitter with the same parent but different orientation
202cdf0e10cSrcweir     Window *pWin = GetParent()->GetWindow( WINDOW_FIRSTCHILD );
203cdf0e10cSrcweir     Splitter *pSplitter = NULL;
204cdf0e10cSrcweir     while( pWin )
205cdf0e10cSrcweir     {
206cdf0e10cSrcweir         if( pWin->ImplIsSplitter() )
207cdf0e10cSrcweir         {
208cdf0e10cSrcweir             pSplitter = (Splitter*) pWin;
209cdf0e10cSrcweir             if( pSplitter != this && IsHorizontal() != pSplitter->IsHorizontal() )
210cdf0e10cSrcweir                 return pSplitter;
211cdf0e10cSrcweir         }
212cdf0e10cSrcweir         pWin = pWin->GetWindow( WINDOW_NEXT );
213cdf0e10cSrcweir     }
214cdf0e10cSrcweir     return NULL;
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
217cdf0e10cSrcweir // -----------------------------------------------------------------------
218cdf0e10cSrcweir 
219cdf0e10cSrcweir sal_Bool Splitter::ImplSplitterActive()
220cdf0e10cSrcweir {
221cdf0e10cSrcweir     // is splitter in document or at scrollbar handle ?
222cdf0e10cSrcweir 
223cdf0e10cSrcweir     sal_Bool bActive = sal_True;
224cdf0e10cSrcweir 	const StyleSettings& rSettings = GetSettings().GetStyleSettings();
225cdf0e10cSrcweir 	long nA = rSettings.GetScrollBarSize();
226cdf0e10cSrcweir 	long nB = rSettings.GetSplitSize();
227cdf0e10cSrcweir 
228cdf0e10cSrcweir     Size aSize = GetOutputSize();
229cdf0e10cSrcweir 	if ( mbHorzSplit )
230cdf0e10cSrcweir 	{
231cdf0e10cSrcweir         if( aSize.Width() == nB && aSize.Height() == nA )
232cdf0e10cSrcweir             bActive = sal_False;
233cdf0e10cSrcweir 	}
234cdf0e10cSrcweir 	else
235cdf0e10cSrcweir 	{
236cdf0e10cSrcweir         if( aSize.Width() == nA && aSize.Height() == nB )
237cdf0e10cSrcweir             bActive = sal_False;
238cdf0e10cSrcweir 	}
239cdf0e10cSrcweir     return bActive;
240cdf0e10cSrcweir }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir // -----------------------------------------------------------------------
243cdf0e10cSrcweir 
244cdf0e10cSrcweir void Splitter::MouseButtonDown( const MouseEvent& rMEvt )
245cdf0e10cSrcweir {
246cdf0e10cSrcweir 	if ( rMEvt.GetClicks() == 2 )
247cdf0e10cSrcweir 	{
248cdf0e10cSrcweir 		if ( mnLastSplitPos != mnSplitPos )
249cdf0e10cSrcweir 		{
250cdf0e10cSrcweir 			StartSplit();
251cdf0e10cSrcweir 			Point aPos = rMEvt.GetPosPixel();
252cdf0e10cSrcweir 			if ( mbHorzSplit )
253cdf0e10cSrcweir 				aPos.X() = mnLastSplitPos;
254cdf0e10cSrcweir 			else
255cdf0e10cSrcweir 				aPos.Y() = mnLastSplitPos;
256cdf0e10cSrcweir 			ImplSplitMousePos( aPos );
257cdf0e10cSrcweir 			Splitting( aPos );
258cdf0e10cSrcweir 			ImplSplitMousePos( aPos );
259cdf0e10cSrcweir 			long nTemp = mnSplitPos;
260cdf0e10cSrcweir 			if ( mbHorzSplit )
261cdf0e10cSrcweir 				SetSplitPosPixel( aPos.X() );
262cdf0e10cSrcweir 			else
263cdf0e10cSrcweir 				SetSplitPosPixel( aPos.Y() );
264cdf0e10cSrcweir 			mnLastSplitPos = nTemp;
265cdf0e10cSrcweir 			Split();
266cdf0e10cSrcweir 			EndSplit();
267cdf0e10cSrcweir 		}
268cdf0e10cSrcweir 	}
269cdf0e10cSrcweir 	else
270cdf0e10cSrcweir 		StartDrag();
271cdf0e10cSrcweir }
272cdf0e10cSrcweir 
273cdf0e10cSrcweir // -----------------------------------------------------------------------
274cdf0e10cSrcweir 
275cdf0e10cSrcweir void Splitter::Tracking( const TrackingEvent& rTEvt )
276cdf0e10cSrcweir {
277cdf0e10cSrcweir 	if ( rTEvt.IsTrackingEnded() )
278cdf0e10cSrcweir 	{
279cdf0e10cSrcweir 		if ( !mbDragFull )
280cdf0e10cSrcweir 			ImplDrawSplitter();
281cdf0e10cSrcweir 
282cdf0e10cSrcweir 		if ( !rTEvt.IsTrackingCanceled() )
283cdf0e10cSrcweir 		{
284cdf0e10cSrcweir 			long nNewPos;
285cdf0e10cSrcweir 			if ( mbHorzSplit )
286cdf0e10cSrcweir 				nNewPos = maDragPos.X();
287cdf0e10cSrcweir 			else
288cdf0e10cSrcweir 				nNewPos = maDragPos.Y();
289cdf0e10cSrcweir 			if ( nNewPos != mnStartSplitPos )
290cdf0e10cSrcweir 			{
291cdf0e10cSrcweir 				SetSplitPosPixel( nNewPos );
292cdf0e10cSrcweir 				mnLastSplitPos = 0;
293cdf0e10cSrcweir 				Split();
294cdf0e10cSrcweir 			}
295cdf0e10cSrcweir 			EndSplit();
296cdf0e10cSrcweir 		}
297cdf0e10cSrcweir 		else if ( mbDragFull )
298cdf0e10cSrcweir 		{
299cdf0e10cSrcweir 			SetSplitPosPixel( mnStartSplitPos );
300cdf0e10cSrcweir 			Split();
301cdf0e10cSrcweir 		}
302cdf0e10cSrcweir 		mnStartSplitPos = 0;
303cdf0e10cSrcweir 	}
304cdf0e10cSrcweir 	else
305cdf0e10cSrcweir 	{
306cdf0e10cSrcweir 		//Point aNewPos = mpRefWin->ScreenToOutputPixel( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
307cdf0e10cSrcweir 		Point aNewPos = mpRefWin->NormalizedScreenToOutputPixel( OutputToNormalizedScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
308cdf0e10cSrcweir 		ImplSplitMousePos( aNewPos );
309cdf0e10cSrcweir 		Splitting( aNewPos );
310cdf0e10cSrcweir 		ImplSplitMousePos( aNewPos );
311cdf0e10cSrcweir 
312cdf0e10cSrcweir 		if ( mbHorzSplit )
313cdf0e10cSrcweir 		{
314cdf0e10cSrcweir 			if ( aNewPos.X() == maDragPos.X() )
315cdf0e10cSrcweir 				return;
316cdf0e10cSrcweir 		}
317cdf0e10cSrcweir 		else
318cdf0e10cSrcweir 		{
319cdf0e10cSrcweir 			if ( aNewPos.Y() == maDragPos.Y() )
320cdf0e10cSrcweir 				return;
321cdf0e10cSrcweir 		}
322cdf0e10cSrcweir 
323cdf0e10cSrcweir 		if ( mbDragFull )
324cdf0e10cSrcweir 		{
325cdf0e10cSrcweir 			maDragPos = aNewPos;
326cdf0e10cSrcweir 			long nNewPos;
327cdf0e10cSrcweir 			if ( mbHorzSplit )
328cdf0e10cSrcweir 				nNewPos = maDragPos.X();
329cdf0e10cSrcweir 			else
330cdf0e10cSrcweir 				nNewPos = maDragPos.Y();
331cdf0e10cSrcweir 			if ( nNewPos != mnSplitPos )
332cdf0e10cSrcweir 			{
333cdf0e10cSrcweir 				SetSplitPosPixel( nNewPos );
334cdf0e10cSrcweir 				mnLastSplitPos = 0;
335cdf0e10cSrcweir 				Split();
336cdf0e10cSrcweir 			}
337cdf0e10cSrcweir 
338cdf0e10cSrcweir 			GetParent()->Update();
339cdf0e10cSrcweir 		}
340cdf0e10cSrcweir 		else
341cdf0e10cSrcweir 		{
342cdf0e10cSrcweir 			ImplDrawSplitter();
343cdf0e10cSrcweir 			maDragPos = aNewPos;
344cdf0e10cSrcweir 			ImplDrawSplitter();
345cdf0e10cSrcweir 		}
346cdf0e10cSrcweir 	}
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
349cdf0e10cSrcweir // -----------------------------------------------------------------------
350cdf0e10cSrcweir 
351cdf0e10cSrcweir void Splitter::ImplKbdTracking( KeyCode aKeyCode )
352cdf0e10cSrcweir {
353cdf0e10cSrcweir     sal_uInt16 nCode = aKeyCode.GetCode();
354cdf0e10cSrcweir 	if ( nCode == KEY_ESCAPE || nCode == KEY_RETURN )
355cdf0e10cSrcweir 	{
356cdf0e10cSrcweir         if( !mbKbdSplitting )
357cdf0e10cSrcweir             return;
358cdf0e10cSrcweir         else
359cdf0e10cSrcweir             mbKbdSplitting = sal_False;
360cdf0e10cSrcweir 
361cdf0e10cSrcweir 		if ( nCode != KEY_ESCAPE )
362cdf0e10cSrcweir 		{
363cdf0e10cSrcweir 			long nNewPos;
364cdf0e10cSrcweir 			if ( mbHorzSplit )
365cdf0e10cSrcweir 				nNewPos = maDragPos.X();
366cdf0e10cSrcweir 			else
367cdf0e10cSrcweir 				nNewPos = maDragPos.Y();
368cdf0e10cSrcweir 			if ( nNewPos != mnStartSplitPos )
369cdf0e10cSrcweir 			{
370cdf0e10cSrcweir 				SetSplitPosPixel( nNewPos );
371cdf0e10cSrcweir 				mnLastSplitPos = 0;
372cdf0e10cSrcweir 				Split();
373cdf0e10cSrcweir 			}
374cdf0e10cSrcweir 		}
375cdf0e10cSrcweir 		else
376cdf0e10cSrcweir 		{
377cdf0e10cSrcweir 			SetSplitPosPixel( mnStartSplitPos );
378cdf0e10cSrcweir 			Split();
379cdf0e10cSrcweir 			EndSplit();
380cdf0e10cSrcweir 		}
381cdf0e10cSrcweir 		mnStartSplitPos = 0;
382cdf0e10cSrcweir 	}
383cdf0e10cSrcweir 	else
384cdf0e10cSrcweir 	{
385cdf0e10cSrcweir 		Point aNewPos;
386cdf0e10cSrcweir         Size aSize = mpRefWin->GetOutputSize();
387cdf0e10cSrcweir         Point aPos = GetPosPixel();
388cdf0e10cSrcweir         // depending on the position calc allows continous moves or snaps to row/columns
389cdf0e10cSrcweir         // continous mode is active when position is at the origin or end of the splitter
390cdf0e10cSrcweir         // otherwise snap mode is active
391cdf0e10cSrcweir         // default here is snap, holding shift sets continous mode
392cdf0e10cSrcweir         if( mbHorzSplit )
393cdf0e10cSrcweir             aNewPos = Point( ImplSplitterActive() ? aPos.X() : mnSplitPos, aKeyCode.IsShift() ? 0 : aSize.Height()/2);
394cdf0e10cSrcweir         else
395cdf0e10cSrcweir             aNewPos = Point( aKeyCode.IsShift() ? 0 : aSize.Width()/2, ImplSplitterActive() ? aPos.Y() : mnSplitPos );
396cdf0e10cSrcweir 
397cdf0e10cSrcweir         Point aOldWindowPos = GetPosPixel();
398cdf0e10cSrcweir 
399cdf0e10cSrcweir         int maxiter = 500;  // avoid endless loop
400cdf0e10cSrcweir         int delta=0;
401cdf0e10cSrcweir         int delta_step = mbHorzSplit  ? aSize.Width()/10 : aSize.Height()/10;
402cdf0e10cSrcweir 
403cdf0e10cSrcweir         // use the specified step size if it was set
404cdf0e10cSrcweir         if( mnKeyboardStepSize != SPLITTER_DEFAULTSTEPSIZE )
405cdf0e10cSrcweir             delta_step = mnKeyboardStepSize;
406cdf0e10cSrcweir 
407cdf0e10cSrcweir         while( maxiter-- && aOldWindowPos == GetPosPixel() )
408cdf0e10cSrcweir         {
409cdf0e10cSrcweir             // inc/dec position until application performs changes
410cdf0e10cSrcweir             // thus a single key press really moves the splitter
411cdf0e10cSrcweir             if( aKeyCode.IsShift() )
412cdf0e10cSrcweir                 delta++;
413cdf0e10cSrcweir             else
414cdf0e10cSrcweir                 delta += delta_step;
415cdf0e10cSrcweir 
416cdf0e10cSrcweir             switch( nCode )
417cdf0e10cSrcweir             {
418cdf0e10cSrcweir             case KEY_LEFT:
419cdf0e10cSrcweir                 aNewPos.X()-=delta;
420cdf0e10cSrcweir                 break;
421cdf0e10cSrcweir             case KEY_RIGHT:
422cdf0e10cSrcweir                 aNewPos.X()+=delta;
423cdf0e10cSrcweir                 break;
424cdf0e10cSrcweir             case KEY_UP:
425cdf0e10cSrcweir                 aNewPos.Y()-=delta;
426cdf0e10cSrcweir                 break;
427cdf0e10cSrcweir             case KEY_DOWN:
428cdf0e10cSrcweir                 aNewPos.Y()+=delta;
429cdf0e10cSrcweir                 break;
430cdf0e10cSrcweir             default:
431cdf0e10cSrcweir                 maxiter = 0;    // leave loop
432cdf0e10cSrcweir                 break;
433cdf0e10cSrcweir             }
434cdf0e10cSrcweir 		    ImplSplitMousePos( aNewPos );
435cdf0e10cSrcweir 		    Splitting( aNewPos );
436cdf0e10cSrcweir 		    ImplSplitMousePos( aNewPos );
437cdf0e10cSrcweir 
438cdf0e10cSrcweir 		    if ( mbHorzSplit )
439cdf0e10cSrcweir 		    {
440cdf0e10cSrcweir 			    if ( aNewPos.X() == maDragPos.X() )
441cdf0e10cSrcweir 				    continue;
442cdf0e10cSrcweir 		    }
443cdf0e10cSrcweir 		    else
444cdf0e10cSrcweir 		    {
445cdf0e10cSrcweir 			    if ( aNewPos.Y() == maDragPos.Y() )
446cdf0e10cSrcweir 				    continue;
447cdf0e10cSrcweir 		    }
448cdf0e10cSrcweir 
449cdf0e10cSrcweir 			maDragPos = aNewPos;
450cdf0e10cSrcweir 			long nNewPos;
451cdf0e10cSrcweir 			if ( mbHorzSplit )
452cdf0e10cSrcweir 				nNewPos = maDragPos.X();
453cdf0e10cSrcweir 			else
454cdf0e10cSrcweir 				nNewPos = maDragPos.Y();
455cdf0e10cSrcweir 			if ( nNewPos != mnSplitPos )
456cdf0e10cSrcweir 			{
457cdf0e10cSrcweir 				SetSplitPosPixel( nNewPos );
458cdf0e10cSrcweir 				mnLastSplitPos = 0;
459cdf0e10cSrcweir 				Split();
460cdf0e10cSrcweir 			}
461cdf0e10cSrcweir 			GetParent()->Update();
462cdf0e10cSrcweir         }
463cdf0e10cSrcweir 	}
464cdf0e10cSrcweir }
465cdf0e10cSrcweir 
466cdf0e10cSrcweir // -----------------------------------------------------------------------
467cdf0e10cSrcweir 
468cdf0e10cSrcweir void Splitter::StartSplit()
469cdf0e10cSrcweir {
470cdf0e10cSrcweir 	maStartSplitHdl.Call( this );
471cdf0e10cSrcweir }
472cdf0e10cSrcweir 
473cdf0e10cSrcweir // -----------------------------------------------------------------------
474cdf0e10cSrcweir 
475cdf0e10cSrcweir void Splitter::Split()
476cdf0e10cSrcweir {
477cdf0e10cSrcweir 	maSplitHdl.Call( this );
478cdf0e10cSrcweir }
479cdf0e10cSrcweir 
480cdf0e10cSrcweir // -----------------------------------------------------------------------
481cdf0e10cSrcweir 
482cdf0e10cSrcweir void Splitter::EndSplit()
483cdf0e10cSrcweir {
484cdf0e10cSrcweir 	if ( maEndSplitHdl.IsSet() )
485cdf0e10cSrcweir 		maEndSplitHdl.Call( this );
486cdf0e10cSrcweir }
487cdf0e10cSrcweir 
488cdf0e10cSrcweir // -----------------------------------------------------------------------
489cdf0e10cSrcweir 
490cdf0e10cSrcweir void Splitter::Splitting( Point& /* rSplitPos */ )
491cdf0e10cSrcweir {
492cdf0e10cSrcweir }
493cdf0e10cSrcweir 
494cdf0e10cSrcweir // -----------------------------------------------------------------------
495cdf0e10cSrcweir 
496cdf0e10cSrcweir void Splitter::SetDragRectPixel( const Rectangle& rDragRect, Window* _pRefWin )
497cdf0e10cSrcweir {
498cdf0e10cSrcweir 	maDragRect = rDragRect;
499cdf0e10cSrcweir 	if ( !_pRefWin )
500cdf0e10cSrcweir 		mpRefWin = GetParent();
501cdf0e10cSrcweir 	else
502cdf0e10cSrcweir 		mpRefWin = _pRefWin;
503cdf0e10cSrcweir }
504cdf0e10cSrcweir 
505cdf0e10cSrcweir // -----------------------------------------------------------------------
506cdf0e10cSrcweir 
507cdf0e10cSrcweir void Splitter::SetSplitPosPixel( long nNewPos )
508cdf0e10cSrcweir {
509cdf0e10cSrcweir 	mnSplitPos = nNewPos;
510cdf0e10cSrcweir }
511cdf0e10cSrcweir 
512cdf0e10cSrcweir // -----------------------------------------------------------------------
513cdf0e10cSrcweir 
514cdf0e10cSrcweir void Splitter::SetLastSplitPosPixel( long nNewPos )
515cdf0e10cSrcweir {
516cdf0e10cSrcweir 	mnLastSplitPos = nNewPos;
517cdf0e10cSrcweir }
518cdf0e10cSrcweir 
519cdf0e10cSrcweir // -----------------------------------------------------------------------
520cdf0e10cSrcweir 
521cdf0e10cSrcweir void Splitter::StartDrag()
522cdf0e10cSrcweir {
523cdf0e10cSrcweir 	if ( IsTracking() )
524cdf0e10cSrcweir 		return;
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 	StartSplit();
527cdf0e10cSrcweir 
528cdf0e10cSrcweir 	// Tracking starten
529cdf0e10cSrcweir 	StartTracking();
530cdf0e10cSrcweir 
531cdf0e10cSrcweir 	// Start-Positon ermitteln
532cdf0e10cSrcweir 	maDragPos = mpRefWin->GetPointerPosPixel();
533cdf0e10cSrcweir 	ImplSplitMousePos( maDragPos );
534cdf0e10cSrcweir 	Splitting( maDragPos );
535cdf0e10cSrcweir 	ImplSplitMousePos( maDragPos );
536cdf0e10cSrcweir 	if ( mbHorzSplit )
537cdf0e10cSrcweir 		mnStartSplitPos = maDragPos.X();
538cdf0e10cSrcweir 	else
539cdf0e10cSrcweir 		mnStartSplitPos = maDragPos.Y();
540cdf0e10cSrcweir 
541cdf0e10cSrcweir 	mbDragFull = (Application::GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SPLIT) != 0;
542cdf0e10cSrcweir 	if ( !mbDragFull )
543cdf0e10cSrcweir 		ImplDrawSplitter();
544cdf0e10cSrcweir }
545cdf0e10cSrcweir 
546cdf0e10cSrcweir 
547cdf0e10cSrcweir // -----------------------------------------------------------------------
548cdf0e10cSrcweir 
549cdf0e10cSrcweir void Splitter::ImplStartKbdSplitting()
550cdf0e10cSrcweir {
551cdf0e10cSrcweir     if( mbKbdSplitting )
552cdf0e10cSrcweir         return;
553cdf0e10cSrcweir 
554cdf0e10cSrcweir     mbKbdSplitting = sal_True;
555cdf0e10cSrcweir 
556cdf0e10cSrcweir 	StartSplit();
557cdf0e10cSrcweir 
558cdf0e10cSrcweir 	// determine start position
559cdf0e10cSrcweir     // because we have no mouse position we take either the position
560cdf0e10cSrcweir     // of the splitter window or the last split position
561cdf0e10cSrcweir     // the other coordinate is just the center of the reference window
562cdf0e10cSrcweir     Size aSize = mpRefWin->GetOutputSize();
563cdf0e10cSrcweir     Point aPos = GetPosPixel();
564cdf0e10cSrcweir     if( mbHorzSplit )
565cdf0e10cSrcweir         maDragPos = Point( ImplSplitterActive() ? aPos.X() : mnSplitPos, aSize.Height()/2 );
566cdf0e10cSrcweir     else
567cdf0e10cSrcweir         maDragPos = Point( aSize.Width()/2, ImplSplitterActive() ? aPos.Y() : mnSplitPos );
568cdf0e10cSrcweir 	ImplSplitMousePos( maDragPos );
569cdf0e10cSrcweir 	Splitting( maDragPos );
570cdf0e10cSrcweir 	ImplSplitMousePos( maDragPos );
571cdf0e10cSrcweir 	if ( mbHorzSplit )
572cdf0e10cSrcweir 		mnStartSplitPos = maDragPos.X();
573cdf0e10cSrcweir 	else
574cdf0e10cSrcweir 		mnStartSplitPos = maDragPos.Y();
575cdf0e10cSrcweir }
576cdf0e10cSrcweir 
577cdf0e10cSrcweir // -----------------------------------------------------------------------
578cdf0e10cSrcweir 
579cdf0e10cSrcweir void Splitter::ImplRestoreSplitter()
580cdf0e10cSrcweir {
581cdf0e10cSrcweir     // set splitter in the center of the ref window
582cdf0e10cSrcweir     StartSplit();
583cdf0e10cSrcweir     Size aSize = mpRefWin->GetOutputSize();
584cdf0e10cSrcweir     Point aPos = Point( aSize.Width()/2 , aSize.Height()/2);
585cdf0e10cSrcweir     if ( mnLastSplitPos != mnSplitPos && mnLastSplitPos > 5 )
586cdf0e10cSrcweir     {
587cdf0e10cSrcweir         // restore last pos if it was a useful position (>5)
588cdf0e10cSrcweir 	    if ( mbHorzSplit )
589cdf0e10cSrcweir 		    aPos.X() = mnLastSplitPos;
590cdf0e10cSrcweir 	    else
591cdf0e10cSrcweir 		    aPos.Y() = mnLastSplitPos;
592cdf0e10cSrcweir     }
593cdf0e10cSrcweir 
594cdf0e10cSrcweir     ImplSplitMousePos( aPos );
595cdf0e10cSrcweir     Splitting( aPos );
596cdf0e10cSrcweir     ImplSplitMousePos( aPos );
597cdf0e10cSrcweir     long nTemp = mnSplitPos;
598cdf0e10cSrcweir     if ( mbHorzSplit )
599cdf0e10cSrcweir 	    SetSplitPosPixel( aPos.X() );
600cdf0e10cSrcweir     else
601cdf0e10cSrcweir 	    SetSplitPosPixel( aPos.Y() );
602cdf0e10cSrcweir     mnLastSplitPos = nTemp;
603cdf0e10cSrcweir     Split();
604cdf0e10cSrcweir 	EndSplit();
605cdf0e10cSrcweir }
606cdf0e10cSrcweir 
607cdf0e10cSrcweir 
608cdf0e10cSrcweir // -----------------------------------------------------------------------
609cdf0e10cSrcweir 
610cdf0e10cSrcweir void Splitter::GetFocus()
611cdf0e10cSrcweir {
612cdf0e10cSrcweir     if( !ImplSplitterActive() )
613cdf0e10cSrcweir         ImplRestoreSplitter();
614cdf0e10cSrcweir 
615cdf0e10cSrcweir     Invalidate();
616cdf0e10cSrcweir }
617cdf0e10cSrcweir 
618cdf0e10cSrcweir // -----------------------------------------------------------------------
619cdf0e10cSrcweir 
620cdf0e10cSrcweir void Splitter::LoseFocus()
621cdf0e10cSrcweir {
622cdf0e10cSrcweir     if( mbKbdSplitting )
623cdf0e10cSrcweir     {
624cdf0e10cSrcweir         KeyCode aReturnKey( KEY_RETURN );
625cdf0e10cSrcweir         ImplKbdTracking( aReturnKey );
626cdf0e10cSrcweir         mbKbdSplitting = sal_False;
627cdf0e10cSrcweir     }
628cdf0e10cSrcweir     Invalidate();
629cdf0e10cSrcweir }
630cdf0e10cSrcweir 
631cdf0e10cSrcweir // -----------------------------------------------------------------------
632cdf0e10cSrcweir 
633cdf0e10cSrcweir void Splitter::KeyInput( const KeyEvent& rKEvt )
634cdf0e10cSrcweir {
635cdf0e10cSrcweir     if( mbInKeyEvent )
636cdf0e10cSrcweir         return;
637cdf0e10cSrcweir 
638cdf0e10cSrcweir     mbInKeyEvent = 1;
639cdf0e10cSrcweir 
640cdf0e10cSrcweir     Splitter *pSibling = ImplFindSibling();
641cdf0e10cSrcweir     KeyCode aKeyCode = rKEvt.GetKeyCode();
642cdf0e10cSrcweir     sal_uInt16 nCode = aKeyCode.GetCode();
643cdf0e10cSrcweir     switch ( nCode )
644cdf0e10cSrcweir     {
645cdf0e10cSrcweir         case KEY_UP:
646cdf0e10cSrcweir         case KEY_DOWN:
647cdf0e10cSrcweir             if( !mbHorzSplit )
648cdf0e10cSrcweir             {
649cdf0e10cSrcweir                 ImplStartKbdSplitting();
650cdf0e10cSrcweir                 ImplKbdTracking( aKeyCode );
651cdf0e10cSrcweir             }
652cdf0e10cSrcweir             else
653cdf0e10cSrcweir             {
654cdf0e10cSrcweir                 if( pSibling )
655cdf0e10cSrcweir                 {
656cdf0e10cSrcweir                     pSibling->GrabFocus();
657cdf0e10cSrcweir                     pSibling->KeyInput( rKEvt );
658cdf0e10cSrcweir                 }
659cdf0e10cSrcweir             }
660cdf0e10cSrcweir             break;
661cdf0e10cSrcweir         case KEY_RIGHT:
662cdf0e10cSrcweir         case KEY_LEFT:
663cdf0e10cSrcweir             if( mbHorzSplit )
664cdf0e10cSrcweir             {
665cdf0e10cSrcweir                 ImplStartKbdSplitting();
666cdf0e10cSrcweir                 ImplKbdTracking( aKeyCode );
667cdf0e10cSrcweir             }
668cdf0e10cSrcweir             else
669cdf0e10cSrcweir             {
670cdf0e10cSrcweir                 if( pSibling )
671cdf0e10cSrcweir                 {
672cdf0e10cSrcweir                     pSibling->GrabFocus();
673cdf0e10cSrcweir                     pSibling->KeyInput( rKEvt );
674cdf0e10cSrcweir                 }
675cdf0e10cSrcweir             }
676cdf0e10cSrcweir             break;
677cdf0e10cSrcweir 
678cdf0e10cSrcweir         case KEY_DELETE:
679cdf0e10cSrcweir             if( ImplSplitterActive() )
680cdf0e10cSrcweir             {
681cdf0e10cSrcweir                 if( mbKbdSplitting )
682cdf0e10cSrcweir                 {
683cdf0e10cSrcweir                     KeyCode aKey( KEY_ESCAPE );
684cdf0e10cSrcweir                     ImplKbdTracking( aKey );
685cdf0e10cSrcweir                 }
686cdf0e10cSrcweir 
687cdf0e10cSrcweir 			    StartSplit();
688cdf0e10cSrcweir 			    Point aPos;
689cdf0e10cSrcweir 			    if ( mbHorzSplit )
690cdf0e10cSrcweir 				    aPos.X() = 0;
691cdf0e10cSrcweir 			    else
692cdf0e10cSrcweir 				    aPos.Y() = 0;
693cdf0e10cSrcweir 			    ImplSplitMousePos( aPos );
694cdf0e10cSrcweir 			    Splitting( aPos );
695cdf0e10cSrcweir 			    ImplSplitMousePos( aPos );
696cdf0e10cSrcweir 			    long nTemp = mnSplitPos;
697cdf0e10cSrcweir 			    if ( mbHorzSplit )
698cdf0e10cSrcweir 				    SetSplitPosPixel( aPos.X() );
699cdf0e10cSrcweir 			    else
700cdf0e10cSrcweir 				    SetSplitPosPixel( aPos.Y() );
701cdf0e10cSrcweir 			    mnLastSplitPos = nTemp;
702cdf0e10cSrcweir 			    Split();
703cdf0e10cSrcweir 				EndSplit();
704cdf0e10cSrcweir 
705cdf0e10cSrcweir                 // Shift-Del deletes both splitters
706cdf0e10cSrcweir                 if( aKeyCode.IsShift() && pSibling )
707cdf0e10cSrcweir                     pSibling->KeyInput( rKEvt );
708cdf0e10cSrcweir 
709cdf0e10cSrcweir                 GrabFocusToDocument();
710cdf0e10cSrcweir             }
711cdf0e10cSrcweir             break;
712cdf0e10cSrcweir 
713cdf0e10cSrcweir         case KEY_ESCAPE:
714cdf0e10cSrcweir             if( mbKbdSplitting )
715cdf0e10cSrcweir                 ImplKbdTracking( aKeyCode );
716cdf0e10cSrcweir             else
717cdf0e10cSrcweir                 GrabFocusToDocument();
718cdf0e10cSrcweir             break;
719cdf0e10cSrcweir 
720cdf0e10cSrcweir         case KEY_RETURN:
721cdf0e10cSrcweir             ImplKbdTracking( aKeyCode );
722cdf0e10cSrcweir             GrabFocusToDocument();
723cdf0e10cSrcweir             break;
724cdf0e10cSrcweir         default:    // let any key input fix the splitter
725cdf0e10cSrcweir             Window::KeyInput( rKEvt );
726cdf0e10cSrcweir             GrabFocusToDocument();
727cdf0e10cSrcweir             break;
728cdf0e10cSrcweir     }
729cdf0e10cSrcweir     mbInKeyEvent = 0;
730cdf0e10cSrcweir }
731cdf0e10cSrcweir 
732cdf0e10cSrcweir // -----------------------------------------------------------------------
733cdf0e10cSrcweir 
734cdf0e10cSrcweir long Splitter::Notify( NotifyEvent& rNEvt )
735cdf0e10cSrcweir {
736cdf0e10cSrcweir     return Window::Notify( rNEvt );
737cdf0e10cSrcweir }
738cdf0e10cSrcweir 
739cdf0e10cSrcweir // -----------------------------------------------------------------------
740cdf0e10cSrcweir 
741cdf0e10cSrcweir void Splitter::DataChanged( const DataChangedEvent& rDCEvt )
742cdf0e10cSrcweir {
743cdf0e10cSrcweir     Window::DataChanged( rDCEvt );
744cdf0e10cSrcweir     if( rDCEvt.GetType() == DATACHANGED_SETTINGS )
745cdf0e10cSrcweir     {
746cdf0e10cSrcweir         Color oldFaceColor = ((AllSettings *) rDCEvt.GetData())->GetStyleSettings().GetFaceColor();
747cdf0e10cSrcweir         Color newFaceColor = Application::GetSettings().GetStyleSettings().GetFaceColor();
748cdf0e10cSrcweir         if( oldFaceColor.IsDark() != newFaceColor.IsDark() )
749cdf0e10cSrcweir         {
750cdf0e10cSrcweir             if( newFaceColor.IsDark() )
751cdf0e10cSrcweir 	            SetBackground( ImplWhiteWall::get() );
752cdf0e10cSrcweir             else
753cdf0e10cSrcweir 	            SetBackground( ImplBlackWall::get() );
754cdf0e10cSrcweir         }
755cdf0e10cSrcweir     }
756cdf0e10cSrcweir }
757cdf0e10cSrcweir 
758cdf0e10cSrcweir // -----------------------------------------------------------------------
759cdf0e10cSrcweir 
760cdf0e10cSrcweir void Splitter::Paint( const Rectangle& rPaintRect )
761cdf0e10cSrcweir {
762cdf0e10cSrcweir     if( HasFocus() || mbKbdSplitting )
763cdf0e10cSrcweir     {
764cdf0e10cSrcweir         Color oldFillCol = GetFillColor();
765cdf0e10cSrcweir         Color oldLineCol = GetLineColor();
766cdf0e10cSrcweir 
767cdf0e10cSrcweir         SetLineColor();
768cdf0e10cSrcweir         SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
769cdf0e10cSrcweir         DrawRect( rPaintRect );
770cdf0e10cSrcweir 
771cdf0e10cSrcweir         Color aSelectionBorderCol( GetSettings().GetStyleSettings().GetActiveColor() );
772cdf0e10cSrcweir         SetFillColor( aSelectionBorderCol );
773cdf0e10cSrcweir         SetLineColor();
774cdf0e10cSrcweir 
775cdf0e10cSrcweir 	    Polygon aPoly( rPaintRect );
776cdf0e10cSrcweir 		PolyPolygon aPolyPoly( aPoly );
777cdf0e10cSrcweir 		DrawTransparent( aPolyPoly, 85 );
778cdf0e10cSrcweir 
779cdf0e10cSrcweir         SetLineColor( aSelectionBorderCol );
780cdf0e10cSrcweir         SetFillColor();
781cdf0e10cSrcweir 
782cdf0e10cSrcweir         if( mbKbdSplitting )
783cdf0e10cSrcweir         {
784cdf0e10cSrcweir             LineInfo aInfo( LINE_DASH );
785cdf0e10cSrcweir             //aInfo.SetDashLen( 2 );
786cdf0e10cSrcweir             //aInfo.SetDashCount( 1 );
787cdf0e10cSrcweir             aInfo.SetDistance( 1 );
788cdf0e10cSrcweir             aInfo.SetDotLen( 2 );
789cdf0e10cSrcweir             aInfo.SetDotCount( 1 );
790cdf0e10cSrcweir 
791cdf0e10cSrcweir             DrawPolyLine( aPoly, aInfo );
792cdf0e10cSrcweir         }
793cdf0e10cSrcweir         else
794cdf0e10cSrcweir             DrawRect( rPaintRect );
795cdf0e10cSrcweir 
796cdf0e10cSrcweir         SetFillColor( oldFillCol);
797cdf0e10cSrcweir         SetLineColor( oldLineCol);
798cdf0e10cSrcweir     }
799cdf0e10cSrcweir     else
800cdf0e10cSrcweir     {
801cdf0e10cSrcweir         Window::Paint( rPaintRect );
802cdf0e10cSrcweir     }
803cdf0e10cSrcweir }
804