Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : : #include "layout.hxx"
21 : :
22 : : #include "bastypes.hxx"
23 : :
24 : : #include <boost/make_shared.hpp>
25 : :
26 : : namespace basctl
27 : : {
28 : :
29 : : namespace
30 : : {
31 : : // the thickness of the splitting lines
32 : : static int const nSplitThickness = 3;
33 : : } // namespace
34 : :
35 : : // ctor for derived classes
36 : : // pParent: the parent window (BasicIDEShell)
37 : 0 : Layout::Layout (Window* pParent) :
38 : : Window(pParent, WB_CLIPCHILDREN),
39 : : pChild(0),
40 : : bFirstSize(true),
41 : : aLeftSide(this, SplittedSide::Left),
42 : 0 : aBottomSide(this, SplittedSide::Bottom)
43 : : {
44 : 0 : SetBackground(GetSettings().GetStyleSettings().GetWindowColor());
45 : :
46 : 0 : Font aFont = GetFont();
47 : 0 : Size aSz = aFont.GetSize();
48 : 0 : aSz.Height() *= 1.5;
49 : 0 : aFont.SetSize(aSz);
50 : 0 : aFont.SetWeight(WEIGHT_BOLD);
51 : 0 : aFont.SetColor(GetSettings().GetStyleSettings().GetWindowTextColor());
52 : 0 : SetFont(aFont);
53 : 0 : }
54 : :
55 : : // virtual dtor
56 : 0 : Layout::~Layout()
57 : 0 : { }
58 : :
59 : : // called by Window when resized
60 : 0 : void Layout::Resize()
61 : : {
62 : 0 : if (IsVisible())
63 : 0 : ArrangeWindows();
64 : 0 : }
65 : :
66 : : // ArrangeWindows() -- arranges the child windows
67 : 0 : void Layout::ArrangeWindows ()
68 : : {
69 : 0 : Size const aSize = GetOutputSizePixel();
70 : 0 : int const nWidth = aSize.Width(), nHeight = aSize.Height();
71 : 0 : if (!nWidth || !nHeight) // empty size
72 : 0 : return;
73 : 0 : if (bFirstSize)
74 : : {
75 : 0 : this->OnFirstSize(nWidth, nHeight); // virtual
76 : 0 : bFirstSize = false;
77 : : }
78 : :
79 : : // sides
80 : 0 : aBottomSide.ArrangeIn(Rectangle(Point(0, 0), aSize));
81 : 0 : aLeftSide.ArrangeIn(Rectangle(Point(0, 0), Size(nWidth, nHeight - aBottomSide.GetSize())));
82 : : // child in the middle
83 : : pChild->SetPosSizePixel(
84 : 0 : Point(aLeftSide.GetSize(), 0),
85 : 0 : Size(nWidth - aLeftSide.GetSize(), nHeight - aBottomSide.GetSize())
86 : 0 : );
87 : : }
88 : :
89 : 0 : void Layout::DockaWindow (DockingWindow*)
90 : : {
91 : 0 : ArrangeWindows();
92 : 0 : }
93 : :
94 : 0 : void Layout::Activating (IDEBaseWindow& rIdeWindow)
95 : : {
96 : : // first activation
97 : 0 : pChild = &rIdeWindow;
98 : 0 : ArrangeWindows();
99 : 0 : Show();
100 : 0 : pChild->Activating();
101 : 0 : }
102 : :
103 : 0 : void Layout::Deactivating ()
104 : : {
105 : 0 : if (pChild)
106 : 0 : pChild->Deactivating();
107 : 0 : Hide();
108 : 0 : pChild = 0;
109 : 0 : }
110 : :
111 : : // virtual
112 : 0 : void Layout::DataChanged (DataChangedEvent const& rDCEvt)
113 : : {
114 : 0 : Window::DataChanged(rDCEvt);
115 : 0 : if (rDCEvt.GetType() == DATACHANGED_SETTINGS && (rDCEvt.GetFlags() & SETTINGS_STYLE))
116 : : {
117 : 0 : bool bInvalidate = false;
118 : 0 : Color aColor = GetSettings().GetStyleSettings().GetWindowColor();
119 : 0 : if (aColor != rDCEvt.GetOldSettings()->GetStyleSettings().GetWindowColor())
120 : : {
121 : 0 : SetBackground(Wallpaper(aColor));
122 : 0 : bInvalidate = true;
123 : : }
124 : 0 : aColor = GetSettings().GetStyleSettings().GetWindowTextColor();
125 : 0 : if (aColor != rDCEvt.GetOldSettings()->GetStyleSettings().GetWindowTextColor())
126 : : {
127 : 0 : Font aFont(GetFont());
128 : 0 : aFont.SetColor(aColor);
129 : 0 : SetFont(aFont);
130 : 0 : bInvalidate = true;
131 : : }
132 : 0 : if (bInvalidate)
133 : 0 : Invalidate();
134 : : }
135 : 0 : }
136 : :
137 : : //
138 : : // SplittedSide
139 : : // ============
140 : : //
141 : :
142 : : // ctor
143 : 0 : Layout::SplittedSide::SplittedSide (Layout* pParent, Side eSide) :
144 : : rLayout(*pParent),
145 : : bFirstArrange(true),
146 : : bVertical(eSide == Left || eSide == Right),
147 : : bLower(eSide == Left || eSide == Top),
148 : : nSize(0),
149 : : nLastPos(0),
150 : 0 : aSplitter(pParent, bVertical ? WB_HSCROLL : WB_VSCROLL)
151 : : {
152 : 0 : InitSplitter(aSplitter);
153 : 0 : }
154 : :
155 : :
156 : : // Add() -- adds a new window to the side (after construction)
157 : 0 : void Layout::SplittedSide::Add (BasicDockingWindow* pWin, Size const& rSize)
158 : : {
159 : 0 : int const nSize1 = (bVertical ? rSize.Width() : rSize.Height()) + nSplitThickness;
160 : 0 : int const nSize2 = bVertical ? rSize.Height() : rSize.Width();
161 : : // nSize
162 : 0 : if (nSize1 > nSize)
163 : 0 : nSize = nSize1;
164 : : // window
165 : 0 : vWindows.push_back(pWin);
166 : : // split line
167 : 0 : if (vWindows.size() > 1)
168 : : {
169 : : vSplitters.push_back(boost::make_shared<Splitter>(
170 : : &rLayout, bVertical ? WB_VSCROLL : WB_HSCROLL
171 : 0 : ));
172 : 0 : Splitter& rSplitter = *vSplitters.back();
173 : 0 : rSplitter.SetSplitPosPixel(nLastPos - nSplitThickness);
174 : 0 : InitSplitter(rSplitter);
175 : : }
176 : : // nLastPos
177 : 0 : nLastPos += nSize2 + nSplitThickness;
178 : 0 : }
179 : :
180 : : // creating a Point or a Size object
181 : : // The coordinate order depends on bVertical (reversed if true).
182 : 0 : inline Size Layout::SplittedSide::MakeSize (int A, int B) const
183 : : {
184 : 0 : return bVertical ? Size(B, A) : Size(A, B);
185 : : }
186 : 0 : inline Point Layout::SplittedSide::MakePoint (int A, int B) const
187 : : {
188 : 0 : return bVertical ? Point(B, A) : Point(A, B);
189 : : }
190 : :
191 : : // IsEmpty() -- are there no windows docked in this strip?
192 : 0 : bool Layout::SplittedSide::IsEmpty () const
193 : : {
194 : 0 : for (unsigned i = 0; i != vWindows.size(); ++i)
195 : 0 : if (vWindows[i]->IsVisible() && !vWindows[i]->IsFloatingMode())
196 : 0 : return false;
197 : 0 : return true;
198 : : }
199 : :
200 : : // GetSize() -- returns the width or height of the strip (depending on the direction)
201 : 0 : int Layout::SplittedSide::GetSize () const
202 : : {
203 : 0 : return IsEmpty() ? 0 : nSize;
204 : : }
205 : :
206 : : // Arrange() -- arranges the docking windows
207 : : // rRect: the available space
208 : 0 : void Layout::SplittedSide::ArrangeIn (Rectangle const& rRect)
209 : : {
210 : : // saving the rectangle
211 : 0 : aRect = rRect;
212 : :
213 : : // the length of the side
214 : 0 : int const nLength = bVertical ? aRect.GetSize().Height() : aRect.GetSize().Width();
215 : 0 : int const nOtherSize = bVertical ? aRect.GetSize().Width() : aRect.GetSize().Height();
216 : : // bVertical ? horizontal pozition : vertical pozition
217 : 0 : int const nPos1 = (bVertical ? aRect.Left() : aRect.Top()) +
218 : 0 : (bLower ? 0 : nOtherSize - (nSize - nSplitThickness));
219 : : // bVertical ? vertical position : horizontal position
220 : 0 : int const nPos2 = bVertical ? aRect.Top() : aRect.Left();
221 : :
222 : : // main line
223 : : {
224 : : // shown if any of the windows is docked
225 : 0 : if (!IsEmpty())
226 : : {
227 : 0 : aSplitter.Show();
228 : : // split position
229 : 0 : aSplitter.SetSplitPosPixel((bLower ? nSize : nPos1) - nSplitThickness);
230 : : // the actual position and size
231 : : aSplitter.SetPosSizePixel(
232 : 0 : MakePoint(nPos2, aSplitter.GetSplitPosPixel()),
233 : : MakeSize(nLength, nSplitThickness)
234 : 0 : );
235 : : // dragging rectangle
236 : 0 : aSplitter.SetDragRectPixel(aRect);
237 : : }
238 : : else
239 : 0 : aSplitter.Hide();
240 : : }
241 : :
242 : : // positioning separator lines and windows
243 : 0 : bool bPrevDocked = false; // is the previous window docked?
244 : 0 : int nStartPos = nPos2; // window position in the strip
245 : 0 : for (unsigned i = 0; i != vWindows.size(); ++i)
246 : : {
247 : : // window
248 : 0 : BasicDockingWindow& rWin = *vWindows[i];
249 : 0 : bool const bDocked = rWin.IsVisible() && !rWin.IsFloatingMode();
250 : : // The window is docked between nStartPos and nEndPos along.
251 : 0 : int const nEndPos = i == vWindows.size() - 1 ?
252 : 0 : nPos2 + nLength : vSplitters[i]->GetSplitPosPixel();
253 : : rWin.ResizeIfDocking(
254 : : MakePoint(nStartPos, nPos1),
255 : 0 : MakeSize(nEndPos - nStartPos, nSize - nSplitThickness)
256 : 0 : );
257 : : // splitting line before the window
258 : 0 : if (i > 0)
259 : : {
260 : 0 : Splitter& rSplit = *vSplitters[i - 1];
261 : : // If neither of two adjacent windows are docked,
262 : : // the splitting line is hidden.
263 : 0 : if (bDocked || bPrevDocked)
264 : : {
265 : 0 : rSplit.Show();
266 : : // the actual pozition and size of the line
267 : : rSplit.SetPosSizePixel(
268 : 0 : MakePoint(nStartPos - nSplitThickness, nPos1),
269 : 0 : MakeSize(nSplitThickness, nSize - nSplitThickness)
270 : 0 : );
271 : : // the dragging rectangle
272 : : rSplit.SetDragRectPixel(Rectangle(
273 : 0 : MakePoint(bVertical ? aRect.Top() : aRect.Left(), nPos1),
274 : 0 : MakeSize(nLength, nSize - nSplitThickness)
275 : 0 : ));
276 : : }
277 : : else
278 : 0 : rSplit.Hide();
279 : : }
280 : : // next
281 : 0 : bPrevDocked = bDocked;
282 : 0 : nStartPos = nEndPos + nSplitThickness;
283 : : }
284 : :
285 : : // first arrange
286 : 0 : bFirstArrange = false;
287 : 0 : }
288 : :
289 : 0 : IMPL_LINK(Layout::SplittedSide, SplitHdl, Splitter*, pSplitter)
290 : : {
291 : : // checking margins
292 : 0 : CheckMarginsFor(pSplitter);
293 : : // nSize has to be changed?
294 : 0 : if (pSplitter == &aSplitter)
295 : : {
296 : 0 : if (bLower)
297 : 0 : nSize = pSplitter->GetSplitPosPixel();
298 : : else
299 : 0 : nSize = (bVertical ? aRect.Right() : aRect.Bottom()) + 1 - pSplitter->GetSplitPosPixel();
300 : : }
301 : : // arranging windows
302 : 0 : rLayout.ArrangeWindows();
303 : :
304 : 0 : return 0;
305 : : }
306 : :
307 : 0 : void Layout::SplittedSide::CheckMarginsFor (Splitter* pSplitter)
308 : : {
309 : : // The splitter line cannot be closer to the edges than nMargin pixels.
310 : : static int const nMargin = 16;
311 : : // Checking margins:
312 : 0 : if (int const nLength = pSplitter->IsHorizontal() ?
313 : 0 : aRect.GetWidth() : aRect.GetHeight()
314 : : ) {
315 : : // bounds
316 : 0 : int const nLower = (pSplitter->IsHorizontal() ? aRect.Left() : aRect.Top()) + nMargin;
317 : 0 : int const nUpper = nLower + nLength - 2*nMargin;
318 : : // split position
319 : 0 : int const nPos = pSplitter->GetSplitPosPixel();
320 : : // checking bounds
321 : 0 : if (nPos < nLower)
322 : 0 : pSplitter->SetSplitPosPixel(nLower);
323 : 0 : if (nPos > nUpper)
324 : 0 : pSplitter->SetSplitPosPixel(nUpper);
325 : : }
326 : 0 : }
327 : :
328 : 0 : void Layout::SplittedSide::InitSplitter (Splitter& rSplitter)
329 : : {
330 : : // link
331 : 0 : rSplitter.SetSplitHdl(LINK(this, SplittedSide, SplitHdl));
332 : : // color
333 : 0 : Color aColor = rLayout.GetSettings().GetStyleSettings().GetShadowColor();
334 : 0 : rSplitter.SetLineColor(aColor);
335 : 0 : rSplitter.SetFillColor(aColor);
336 : 0 : }
337 : :
338 : :
339 : : } // namespace basctl
340 : :
341 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|