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 <strings.hrc>
21 #include <svdata.hxx>
22 #include <brdwin.hxx>
23 #include <window.h>
24
25 #include <vcl/textrectinfo.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/decoview.hxx>
28 #include <vcl/syswin.hxx>
29 #include <vcl/dockwin.hxx>
30 #include <vcl/floatwin.hxx>
31 #include <vcl/help.hxx>
32 #include <vcl/edit.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/toolbox.hxx>
35 #include <vcl/ptrstyle.hxx>
36
37 using namespace ::com::sun::star::uno;
38
39 // useful caption height for title bar buttons
40 #define MIN_CAPTION_HEIGHT 18
41
42 namespace vcl {
43
ImplCalcSymbolRect(tools::Rectangle & rRect)44 void Window::ImplCalcSymbolRect( tools::Rectangle& rRect )
45 {
46 // Add border, not shown in the non-default representation,
47 // as we want to use it for small buttons
48 rRect.AdjustLeft( -1 );
49 rRect.AdjustTop( -1 );
50 rRect.AdjustRight( 1 );
51 rRect.AdjustBottom( 1 );
52
53 // we leave 5% room between the symbol and the button border
54 long nExtraWidth = ((rRect.GetWidth()*50)+500)/1000;
55 long nExtraHeight = ((rRect.GetHeight()*50)+500)/1000;
56 rRect.AdjustLeft(nExtraWidth );
57 rRect.AdjustRight( -nExtraWidth );
58 rRect.AdjustTop(nExtraHeight );
59 rRect.AdjustBottom( -nExtraHeight );
60 }
61
62 } /* namespace vcl */
63
ImplDrawBrdWinSymbol(vcl::RenderContext * pDev,const tools::Rectangle & rRect,SymbolType eSymbol)64 static void ImplDrawBrdWinSymbol( vcl::RenderContext* pDev,
65 const tools::Rectangle& rRect, SymbolType eSymbol )
66 {
67 // we leave 5% room between the symbol and the button border
68 DecorationView aDecoView( pDev );
69 tools::Rectangle aTempRect = rRect;
70 vcl::Window::ImplCalcSymbolRect( aTempRect );
71 aDecoView.DrawSymbol( aTempRect, eSymbol,
72 pDev->GetSettings().GetStyleSettings().GetButtonTextColor() );
73 }
74
ImplDrawBrdWinSymbolButton(vcl::RenderContext * pDev,const tools::Rectangle & rRect,SymbolType eSymbol,DrawButtonFlags nState)75 static void ImplDrawBrdWinSymbolButton( vcl::RenderContext* pDev,
76 const tools::Rectangle& rRect,
77 SymbolType eSymbol, DrawButtonFlags nState )
78 {
79 bool bMouseOver(nState & DrawButtonFlags::Highlight);
80 nState &= ~DrawButtonFlags::Highlight;
81
82 tools::Rectangle aTempRect;
83 vcl::Window *pWin = dynamic_cast< vcl::Window* >(pDev);
84 if( pWin )
85 {
86 if( bMouseOver )
87 {
88 // provide a bright background for selection effect
89 pDev->SetFillColor( pDev->GetSettings().GetStyleSettings().GetWindowColor() );
90 pDev->SetLineColor();
91 pDev->DrawRect( rRect );
92 pWin->DrawSelectionBackground( rRect, 2, bool(nState & DrawButtonFlags::Pressed),
93 true );
94 }
95 aTempRect = rRect;
96 aTempRect.AdjustLeft(3 );
97 aTempRect.AdjustRight( -4 );
98 aTempRect.AdjustTop(3 );
99 aTempRect.AdjustBottom( -4 );
100 }
101 else
102 {
103 DecorationView aDecoView( pDev );
104 aTempRect = aDecoView.DrawButton( rRect, nState|DrawButtonFlags::Flat );
105 }
106 ImplDrawBrdWinSymbol( pDev, aTempRect, eSymbol );
107 }
108
109
~ImplBorderWindowView()110 ImplBorderWindowView::~ImplBorderWindowView()
111 {
112 }
113
MouseMove(const MouseEvent &)114 bool ImplBorderWindowView::MouseMove( const MouseEvent& )
115 {
116 return false;
117 }
118
MouseButtonDown(const MouseEvent &)119 bool ImplBorderWindowView::MouseButtonDown( const MouseEvent& )
120 {
121 return false;
122 }
123
Tracking(const TrackingEvent &)124 bool ImplBorderWindowView::Tracking( const TrackingEvent& )
125 {
126 return false;
127 }
128
RequestHelp(const Point &,tools::Rectangle &)129 OUString ImplBorderWindowView::RequestHelp( const Point&, tools::Rectangle& )
130 {
131 return OUString();
132 }
133
GetMenuRect() const134 tools::Rectangle ImplBorderWindowView::GetMenuRect() const
135 {
136 return tools::Rectangle();
137 }
138
ImplInitTitle(ImplBorderFrameData * pData)139 void ImplBorderWindowView::ImplInitTitle(ImplBorderFrameData* pData)
140 {
141 ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
142
143 if ( !(pBorderWindow->GetStyle() & (WB_MOVEABLE | WB_POPUP)) ||
144 (pData->mnTitleType == BorderWindowTitleType::NONE) )
145 {
146 pData->mnTitleType = BorderWindowTitleType::NONE;
147 pData->mnTitleHeight = 0;
148 }
149 else
150 {
151 const StyleSettings& rStyleSettings = pData->mpOutDev->GetSettings().GetStyleSettings();
152 if (pData->mnTitleType == BorderWindowTitleType::Tearoff)
153 pData->mnTitleHeight = ToolBox::ImplGetDragWidth(*pData->mpBorderWindow, false) + 2;
154 else
155 {
156 if (pData->mnTitleType == BorderWindowTitleType::Small)
157 {
158 pBorderWindow->SetPointFont(*pBorderWindow, rStyleSettings.GetFloatTitleFont() );
159 pData->mnTitleHeight = rStyleSettings.GetFloatTitleHeight();
160 }
161 else // pData->mnTitleType == BorderWindowTitleType::Normal
162 {
163 // FIXME RenderContext
164 pBorderWindow->SetPointFont(*pBorderWindow, rStyleSettings.GetTitleFont());
165 pData->mnTitleHeight = rStyleSettings.GetTitleHeight();
166 }
167 long nTextHeight = pBorderWindow->GetTextHeight();
168 if (nTextHeight > pData->mnTitleHeight)
169 pData->mnTitleHeight = nTextHeight;
170 }
171 }
172 }
173
ImplHitTest(ImplBorderFrameData const * pData,const Point & rPos)174 BorderWindowHitTest ImplBorderWindowView::ImplHitTest( ImplBorderFrameData const * pData, const Point& rPos )
175 {
176 ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
177
178 if ( pData->maTitleRect.IsInside( rPos ) )
179 {
180 if ( pData->maCloseRect.IsInside( rPos ) )
181 return BorderWindowHitTest::Close;
182 else if ( pData->maRollRect.IsInside( rPos ) )
183 return BorderWindowHitTest::Roll;
184 else if ( pData->maMenuRect.IsInside( rPos ) )
185 return BorderWindowHitTest::Menu;
186 else if ( pData->maDockRect.IsInside( rPos ) )
187 return BorderWindowHitTest::Dock;
188 else if ( pData->maHideRect.IsInside( rPos ) )
189 return BorderWindowHitTest::Hide;
190 else if ( pData->maHelpRect.IsInside( rPos ) )
191 return BorderWindowHitTest::Help;
192 else
193 return BorderWindowHitTest::Title;
194 }
195
196 if ( (pBorderWindow->GetStyle() & WB_SIZEABLE) &&
197 !pBorderWindow->mbRollUp )
198 {
199 long nSizeWidth = pData->mnNoTitleTop+pData->mnTitleHeight;
200 if ( nSizeWidth < 16 )
201 nSizeWidth = 16;
202
203 // no corner resize for floating toolbars, which would lead to jumps while formatting
204 // setting nSizeWidth = 0 will only return pure left,top,right,bottom
205 if( pBorderWindow->GetStyle() & (WB_OWNERDRAWDECORATION | WB_POPUP) )
206 nSizeWidth = 0;
207
208 if ( rPos.X() < pData->mnLeftBorder )
209 {
210 if ( rPos.Y() < nSizeWidth )
211 return BorderWindowHitTest::TopLeft;
212 else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
213 return BorderWindowHitTest::BottomLeft;
214 else
215 return BorderWindowHitTest::Left;
216 }
217 else if ( rPos.X() >= pData->mnWidth-pData->mnRightBorder )
218 {
219 if ( rPos.Y() < nSizeWidth )
220 return BorderWindowHitTest::TopRight;
221 else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
222 return BorderWindowHitTest::BottomRight;
223 else
224 return BorderWindowHitTest::Right;
225 }
226 else if ( rPos.Y() < pData->mnNoTitleTop )
227 {
228 if ( rPos.X() < nSizeWidth )
229 return BorderWindowHitTest::TopLeft;
230 else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
231 return BorderWindowHitTest::TopRight;
232 else
233 return BorderWindowHitTest::Top;
234 }
235 else if ( rPos.Y() >= pData->mnHeight-pData->mnBottomBorder )
236 {
237 if ( rPos.X() < nSizeWidth )
238 return BorderWindowHitTest::BottomLeft;
239 else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
240 return BorderWindowHitTest::BottomRight;
241 else
242 return BorderWindowHitTest::Bottom;
243 }
244 }
245
246 return BorderWindowHitTest::NONE;
247 }
248
ImplMouseMove(ImplBorderFrameData * pData,const MouseEvent & rMEvt)249 void ImplBorderWindowView::ImplMouseMove( ImplBorderFrameData* pData, const MouseEvent& rMEvt )
250 {
251 DrawButtonFlags oldCloseState = pData->mnCloseState;
252 DrawButtonFlags oldMenuState = pData->mnMenuState;
253 pData->mnCloseState &= ~DrawButtonFlags::Highlight;
254 pData->mnMenuState &= ~DrawButtonFlags::Highlight;
255
256 Point aMousePos = rMEvt.GetPosPixel();
257 BorderWindowHitTest nHitTest = ImplHitTest( pData, aMousePos );
258 PointerStyle ePtrStyle = PointerStyle::Arrow;
259 if ( nHitTest & BorderWindowHitTest::Left )
260 ePtrStyle = PointerStyle::WindowWSize;
261 else if ( nHitTest & BorderWindowHitTest::Right )
262 ePtrStyle = PointerStyle::WindowESize;
263 else if ( nHitTest & BorderWindowHitTest::Top )
264 ePtrStyle = PointerStyle::WindowNSize;
265 else if ( nHitTest & BorderWindowHitTest::Bottom )
266 ePtrStyle = PointerStyle::WindowSSize;
267 else if ( nHitTest & BorderWindowHitTest::TopLeft )
268 ePtrStyle = PointerStyle::WindowNWSize;
269 else if ( nHitTest & BorderWindowHitTest::BottomRight )
270 ePtrStyle = PointerStyle::WindowSESize;
271 else if ( nHitTest & BorderWindowHitTest::TopRight )
272 ePtrStyle = PointerStyle::WindowNESize;
273 else if ( nHitTest & BorderWindowHitTest::BottomLeft )
274 ePtrStyle = PointerStyle::WindowSWSize;
275 else if ( nHitTest & BorderWindowHitTest::Close )
276 pData->mnCloseState |= DrawButtonFlags::Highlight;
277 else if ( nHitTest & BorderWindowHitTest::Menu )
278 pData->mnMenuState |= DrawButtonFlags::Highlight;
279 else if ( nHitTest & BorderWindowHitTest::Title &&
280 pData->mnTitleType == BorderWindowTitleType::Tearoff && !rMEvt.IsLeaveWindow() )
281 ePtrStyle = PointerStyle::Move;
282 pData->mpBorderWindow->SetPointer( ePtrStyle );
283
284 if( pData->mnCloseState != oldCloseState )
285 pData->mpBorderWindow->Invalidate( pData->maCloseRect );
286 if( pData->mnMenuState != oldMenuState )
287 pData->mpBorderWindow->Invalidate( pData->maMenuRect );
288 }
289
ImplRequestHelp(ImplBorderFrameData const * pData,const Point & rPos,tools::Rectangle & rHelpRect)290 OUString ImplBorderWindowView::ImplRequestHelp( ImplBorderFrameData const * pData,
291 const Point& rPos,
292 tools::Rectangle& rHelpRect )
293 {
294 const char* pHelpId = nullptr;
295 OUString aHelpStr;
296 BorderWindowHitTest nHitTest = ImplHitTest( pData, rPos );
297 if ( nHitTest != BorderWindowHitTest::NONE )
298 {
299 if ( nHitTest & BorderWindowHitTest::Close )
300 {
301 pHelpId = SV_HELPTEXT_CLOSE;
302 rHelpRect = pData->maCloseRect;
303 }
304 else if ( nHitTest & BorderWindowHitTest::Roll )
305 {
306 if ( pData->mpBorderWindow->mbRollUp )
307 pHelpId = SV_HELPTEXT_ROLLDOWN;
308 else
309 pHelpId = SV_HELPTEXT_ROLLUP;
310 rHelpRect = pData->maRollRect;
311 }
312 else if ( nHitTest & BorderWindowHitTest::Dock )
313 {
314 pHelpId = SV_HELPTEXT_MAXIMIZE;
315 rHelpRect = pData->maDockRect;
316 }
317 else if ( nHitTest & BorderWindowHitTest::Hide )
318 {
319 pHelpId = SV_HELPTEXT_MINIMIZE;
320 rHelpRect = pData->maHideRect;
321 }
322 else if ( nHitTest & BorderWindowHitTest::Help )
323 {
324 pHelpId = SV_HELPTEXT_HELP;
325 rHelpRect = pData->maHelpRect;
326 }
327 else if ( nHitTest & BorderWindowHitTest::Title )
328 {
329 if( !pData->maTitleRect.IsEmpty() )
330 {
331 // tooltip only if title truncated
332 if( pData->mbTitleClipped )
333 {
334 rHelpRect = pData->maTitleRect;
335 // no help id, use window title as help string
336 aHelpStr = pData->mpBorderWindow->GetText();
337 }
338 }
339 }
340 }
341
342 if (pHelpId)
343 aHelpStr = VclResId(pHelpId);
344
345 return aHelpStr;
346 }
347
ImplCalcTitleWidth(const ImplBorderFrameData * pData)348 long ImplBorderWindowView::ImplCalcTitleWidth( const ImplBorderFrameData* pData )
349 {
350 // title is not visible therefore no width
351 if ( !pData->mnTitleHeight )
352 return 0;
353
354 ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
355 long nTitleWidth = pBorderWindow->GetTextWidth( pBorderWindow->GetText() )+6;
356 nTitleWidth += pData->maCloseRect.GetWidth();
357 nTitleWidth += pData->maRollRect.GetWidth();
358 nTitleWidth += pData->maDockRect.GetWidth();
359 nTitleWidth += pData->maMenuRect.GetWidth();
360 nTitleWidth += pData->maHideRect.GetWidth();
361 nTitleWidth += pData->maHelpRect.GetWidth();
362 nTitleWidth += pData->mnLeftBorder+pData->mnRightBorder;
363 return nTitleWidth;
364 }
365
366
ImplNoBorderWindowView()367 ImplNoBorderWindowView::ImplNoBorderWindowView()
368 {
369 }
370
Init(OutputDevice *,long,long)371 void ImplNoBorderWindowView::Init( OutputDevice*, long, long )
372 {
373 }
374
GetBorder(sal_Int32 & rLeftBorder,sal_Int32 & rTopBorder,sal_Int32 & rRightBorder,sal_Int32 & rBottomBorder) const375 void ImplNoBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
376 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
377 {
378 rLeftBorder = 0;
379 rTopBorder = 0;
380 rRightBorder = 0;
381 rBottomBorder = 0;
382 }
383
CalcTitleWidth() const384 long ImplNoBorderWindowView::CalcTitleWidth() const
385 {
386 return 0;
387 }
388
DrawWindow(vcl::RenderContext &,const Point *)389 void ImplNoBorderWindowView::DrawWindow(vcl::RenderContext&, const Point*)
390 {
391 }
392
ImplSmallBorderWindowView(ImplBorderWindow * pBorderWindow)393 ImplSmallBorderWindowView::ImplSmallBorderWindowView( ImplBorderWindow* pBorderWindow )
394 : mpBorderWindow(pBorderWindow)
395 , mpOutDev(nullptr)
396 , mnWidth(0)
397 , mnHeight(0)
398 , mnLeftBorder(0)
399 , mnTopBorder(0)
400 , mnRightBorder(0)
401 , mnBottomBorder(0)
402 , mbNWFBorder(false)
403 {
404 }
405
Init(OutputDevice * pDev,long nWidth,long nHeight)406 void ImplSmallBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
407 {
408 mpOutDev = pDev;
409 mnWidth = nWidth;
410 mnHeight = nHeight;
411 mbNWFBorder = false;
412
413 vcl::Window *pWin = nullptr, *pCtrl = nullptr;
414 if (mpOutDev->GetOutDevType() == OUTDEV_WINDOW)
415 pWin = static_cast<vcl::Window*>(mpOutDev.get());
416
417 if (pWin)
418 pCtrl = mpBorderWindow->GetWindow(GetWindowType::Client);
419
420 long nOrigLeftBorder = mnLeftBorder;
421 long nOrigTopBorder = mnTopBorder;
422 long nOrigRightBorder = mnRightBorder;
423 long nOrigBottomBorder = mnBottomBorder;
424
425 WindowBorderStyle nBorderStyle = mpBorderWindow->GetBorderStyle();
426 if ( nBorderStyle & WindowBorderStyle::NOBORDER )
427 {
428 mnLeftBorder = 0;
429 mnTopBorder = 0;
430 mnRightBorder = 0;
431 mnBottomBorder = 0;
432 }
433 else
434 {
435 // FIXME: this is currently only on macOS, check with other
436 // platforms
437 if( ImplGetSVData()->maNWFData.mbNoFocusRects && !( nBorderStyle & WindowBorderStyle::NWF ) )
438 {
439 // for native widget drawing we must find out what
440 // control this border belongs to
441 ControlType aCtrlType = ControlType::Generic;
442 if (pCtrl)
443 {
444 switch( pCtrl->GetType() )
445 {
446 case WindowType::LISTBOX:
447 if( pCtrl->GetStyle() & WB_DROPDOWN )
448 {
449 aCtrlType = ControlType::Listbox;
450 mbNWFBorder = true;
451 }
452 break;
453 case WindowType::COMBOBOX:
454 if( pCtrl->GetStyle() & WB_DROPDOWN )
455 {
456 aCtrlType = ControlType::Combobox;
457 mbNWFBorder = true;
458 }
459 break;
460 case WindowType::MULTILINEEDIT:
461 aCtrlType = ControlType::MultilineEditbox;
462 mbNWFBorder = true;
463 break;
464 case WindowType::EDIT:
465 case WindowType::PATTERNFIELD:
466 case WindowType::METRICFIELD:
467 case WindowType::CURRENCYFIELD:
468 case WindowType::DATEFIELD:
469 case WindowType::TIMEFIELD:
470 case WindowType::LONGCURRENCYFIELD:
471 case WindowType::NUMERICFIELD:
472 case WindowType::SPINFIELD:
473 case WindowType::CALCINPUTLINE:
474 mbNWFBorder = true;
475 if (pCtrl->GetStyle() & WB_SPIN)
476 aCtrlType = ControlType::Spinbox;
477 else
478 aCtrlType = ControlType::Editbox;
479 break;
480 default:
481 break;
482 }
483 }
484 if( mbNWFBorder )
485 {
486 ImplControlValue aControlValue;
487 Size aMinSize( mnWidth - mnLeftBorder - mnRightBorder, mnHeight - mnTopBorder - mnBottomBorder );
488 if( aMinSize.Width() < 10 ) aMinSize.setWidth( 10 );
489 if( aMinSize.Height() < 10 ) aMinSize.setHeight( 10 );
490 tools::Rectangle aCtrlRegion( Point(mnLeftBorder, mnTopBorder), aMinSize );
491 tools::Rectangle aBounds, aContent;
492 if( pWin->GetNativeControlRegion( aCtrlType, ControlPart::Entire, aCtrlRegion,
493 ControlState::ENABLED, aControlValue,
494 aBounds, aContent ) )
495 {
496 mnLeftBorder = aContent.Left() - aBounds.Left();
497 mnRightBorder = aBounds.Right() - aContent.Right();
498 mnTopBorder = aContent.Top() - aBounds.Top();
499 mnBottomBorder = aBounds.Bottom() - aContent.Bottom();
500 if( mnWidth && mnHeight )
501 {
502
503 mpBorderWindow->SetPaintTransparent( true );
504 mpBorderWindow->SetBackground();
505 pCtrl->SetPaintTransparent( true );
506
507 vcl::Window* pCompoundParent = nullptr;
508 if( pWin->GetParent() && pWin->GetParent()->IsCompoundControl() )
509 pCompoundParent = pWin->GetParent();
510
511 if( pCompoundParent )
512 pCompoundParent->SetPaintTransparent( true );
513
514 if( mnWidth < aBounds.GetWidth() || mnHeight < aBounds.GetHeight() )
515 {
516 if( ! pCompoundParent ) // compound controls have to fix themselves
517 {
518 Point aPos( mpBorderWindow->GetPosPixel() );
519 if( mnWidth < aBounds.GetWidth() )
520 aPos.AdjustX( -((aBounds.GetWidth() - mnWidth) / 2) );
521 if( mnHeight < aBounds.GetHeight() )
522 aPos.AdjustY( -((aBounds.GetHeight() - mnHeight) / 2) );
523 mpBorderWindow->SetPosSizePixel( aPos, aBounds.GetSize() );
524 }
525 }
526 }
527 }
528 else
529 mbNWFBorder = false;
530 }
531 }
532
533 if( ! mbNWFBorder )
534 {
535 DrawFrameStyle nStyle = DrawFrameStyle::NONE;
536 DrawFrameFlags nFlags = DrawFrameFlags::NoDraw;
537 // move border outside if border was converted or if the BorderWindow is a frame window,
538 if ( mpBorderWindow->mbSmallOutBorder )
539 nStyle = DrawFrameStyle::DoubleOut;
540 else if ( nBorderStyle & WindowBorderStyle::NWF )
541 nStyle = DrawFrameStyle::NWF;
542 else
543 nStyle = DrawFrameStyle::DoubleIn;
544 if ( nBorderStyle & WindowBorderStyle::MONO )
545 nFlags |= DrawFrameFlags::Mono;
546
547 DecorationView aDecoView( mpOutDev );
548 tools::Rectangle aRect( 0, 0, 10, 10 );
549 tools::Rectangle aCalcRect = aDecoView.DrawFrame( aRect, nStyle, nFlags );
550 mnLeftBorder = aCalcRect.Left();
551 mnTopBorder = aCalcRect.Top();
552 mnRightBorder = aRect.Right()-aCalcRect.Right();
553 mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
554 }
555 }
556
557 if (pCtrl)
558 {
559 //fdo#57090 If the borders have changed, then trigger a queue_resize on
560 //the bordered window, which will resync its borders at that point
561 if (nOrigLeftBorder != mnLeftBorder ||
562 nOrigTopBorder != mnTopBorder ||
563 nOrigRightBorder != mnRightBorder ||
564 nOrigBottomBorder != mnBottomBorder)
565 {
566 pCtrl->queue_resize();
567 }
568 }
569 }
570
GetBorder(sal_Int32 & rLeftBorder,sal_Int32 & rTopBorder,sal_Int32 & rRightBorder,sal_Int32 & rBottomBorder) const571 void ImplSmallBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
572 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
573 {
574 rLeftBorder = mnLeftBorder;
575 rTopBorder = mnTopBorder;
576 rRightBorder = mnRightBorder;
577 rBottomBorder = mnBottomBorder;
578 }
579
CalcTitleWidth() const580 long ImplSmallBorderWindowView::CalcTitleWidth() const
581 {
582 return 0;
583 }
584
DrawWindow(vcl::RenderContext & rRenderContext,const Point *)585 void ImplSmallBorderWindowView::DrawWindow(vcl::RenderContext& rRenderContext, const Point*)
586 {
587 WindowBorderStyle nBorderStyle = mpBorderWindow->GetBorderStyle();
588 if (nBorderStyle & WindowBorderStyle::NOBORDER)
589 return;
590
591 bool bNativeOK = false;
592 // for native widget drawing we must find out what
593 // control this border belongs to
594 vcl::Window* pCtrl = mpBorderWindow->GetWindow(GetWindowType::Client);
595
596 ControlType aCtrlType = ControlType::Generic;
597 ControlPart aCtrlPart = ControlPart::Entire;
598 if (pCtrl)
599 {
600 switch (pCtrl->GetType())
601 {
602 case WindowType::MULTILINEEDIT:
603 aCtrlType = ControlType::MultilineEditbox;
604 break;
605 case WindowType::EDIT:
606 case WindowType::PATTERNFIELD:
607 case WindowType::METRICFIELD:
608 case WindowType::CURRENCYFIELD:
609 case WindowType::DATEFIELD:
610 case WindowType::TIMEFIELD:
611 case WindowType::LONGCURRENCYFIELD:
612 case WindowType::NUMERICFIELD:
613 case WindowType::SPINFIELD:
614 case WindowType::CALCINPUTLINE:
615 if (pCtrl->GetStyle() & WB_SPIN)
616 aCtrlType = ControlType::Spinbox;
617 else
618 aCtrlType = ControlType::Editbox;
619 break;
620
621 case WindowType::LISTBOX:
622 case WindowType::MULTILISTBOX:
623 case WindowType::TREELISTBOX:
624 aCtrlType = ControlType::Listbox;
625 if (pCtrl->GetStyle() & WB_DROPDOWN)
626 aCtrlPart = ControlPart::Entire;
627 else
628 aCtrlPart = ControlPart::ListboxWindow;
629 break;
630
631 case WindowType::LISTBOXWINDOW:
632 aCtrlType = ControlType::Listbox;
633 aCtrlPart = ControlPart::ListboxWindow;
634 break;
635
636 case WindowType::COMBOBOX:
637 case WindowType::PATTERNBOX:
638 case WindowType::NUMERICBOX:
639 case WindowType::METRICBOX:
640 case WindowType::CURRENCYBOX:
641 case WindowType::DATEBOX:
642 case WindowType::TIMEBOX:
643 case WindowType::LONGCURRENCYBOX:
644 if (pCtrl->GetStyle() & WB_DROPDOWN)
645 {
646 aCtrlType = ControlType::Combobox;
647 aCtrlPart = ControlPart::Entire;
648 }
649 else
650 {
651 aCtrlType = ControlType::Listbox;
652 aCtrlPart = ControlPart::ListboxWindow;
653 }
654 break;
655
656 default:
657 break;
658 }
659 }
660
661 if (aCtrlType != ControlType::Generic && pCtrl->IsNativeControlSupported(aCtrlType, aCtrlPart))
662 {
663 ImplControlValue aControlValue;
664 ControlState nState = ControlState::ENABLED;
665
666 if (!mpBorderWindow->IsEnabled())
667 nState &= ~ControlState::ENABLED;
668 if (mpBorderWindow->HasFocus())
669 nState |= ControlState::FOCUSED;
670 else if(mbNWFBorder)
671 {
672 // FIXME: this is currently only on macOS, see if other platforms can profit
673
674 // FIXME: for macOS focus rings all controls need to support GetNativeControlRegion
675 // for the dropdown style
676 if (pCtrl->HasFocus() || pCtrl->HasChildPathFocus())
677 nState |= ControlState::FOCUSED;
678 }
679
680 bool bMouseOver = false;
681 vcl::Window *pCtrlChild = pCtrl->GetWindow(GetWindowType::FirstChild);
682 while(pCtrlChild && !(bMouseOver = pCtrlChild->IsMouseOver()))
683 {
684 pCtrlChild = pCtrlChild->GetWindow(GetWindowType::Next);
685 }
686
687 if (bMouseOver)
688 nState |= ControlState::ROLLOVER;
689
690 Point aPoint;
691 tools::Rectangle aCtrlRegion(aPoint, Size(mnWidth, mnHeight));
692
693 tools::Rectangle aBoundingRgn(aPoint, Size(mnWidth, mnHeight));
694 tools::Rectangle aContentRgn(aCtrlRegion);
695 if (!ImplGetSVData()->maNWFData.mbCanDrawWidgetAnySize &&
696 rRenderContext.GetNativeControlRegion(aCtrlType, aCtrlPart, aCtrlRegion,
697 nState, aControlValue,
698 aBoundingRgn, aContentRgn))
699 {
700 aCtrlRegion=aContentRgn;
701 }
702
703 bNativeOK = rRenderContext.DrawNativeControl(aCtrlType, aCtrlPart, aCtrlRegion, nState, aControlValue, OUString());
704
705 // if the native theme draws the spinbuttons in one call, make sure the proper settings
706 // are passed, this might force a redraw though... (TODO: improve)
707 if ((aCtrlType == ControlType::Spinbox) && !pCtrl->IsNativeControlSupported(ControlType::Spinbox, ControlPart::ButtonUp))
708 {
709 Edit* pEdit = static_cast<Edit*>(pCtrl)->GetSubEdit();
710 if (pEdit && !pEdit->SupportsDoubleBuffering())
711 pCtrl->Paint(*pCtrl, tools::Rectangle()); // make sure the buttons are also drawn as they might overwrite the border
712 }
713 }
714
715 if (bNativeOK)
716 return;
717
718 DrawFrameStyle nStyle = DrawFrameStyle::NONE;
719 DrawFrameFlags nFlags = DrawFrameFlags::NONE;
720 // move border outside if border was converted or if the border window is a frame window,
721 if (mpBorderWindow->mbSmallOutBorder)
722 nStyle = DrawFrameStyle::DoubleOut;
723 else if (nBorderStyle & WindowBorderStyle::NWF)
724 nStyle = DrawFrameStyle::NWF;
725 else
726 nStyle = DrawFrameStyle::DoubleIn;
727 if (nBorderStyle & WindowBorderStyle::MONO)
728 nFlags |= DrawFrameFlags::Mono;
729 if (nBorderStyle & WindowBorderStyle::MENU)
730 nFlags |= DrawFrameFlags::Menu;
731 // tell DrawFrame that we're drawing a window border of a frame window to avoid round corners
732 if (mpBorderWindow == mpBorderWindow->ImplGetFrameWindow())
733 nFlags |= DrawFrameFlags::WindowBorder;
734
735 DecorationView aDecoView(&rRenderContext);
736 tools::Rectangle aInRect(Point(), Size(mnWidth, mnHeight));
737 aDecoView.DrawFrame(aInRect, nStyle, nFlags);
738 }
739
740
ImplStdBorderWindowView(ImplBorderWindow * pBorderWindow)741 ImplStdBorderWindowView::ImplStdBorderWindowView( ImplBorderWindow* pBorderWindow )
742 {
743 maFrameData.mpBorderWindow = pBorderWindow;
744 maFrameData.mbDragFull = false;
745 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
746 maFrameData.mnCloseState = DrawButtonFlags::NONE;
747 maFrameData.mnRollState = DrawButtonFlags::NONE;
748 maFrameData.mnDockState = DrawButtonFlags::NONE;
749 maFrameData.mnMenuState = DrawButtonFlags::NONE;
750 maFrameData.mnHideState = DrawButtonFlags::NONE;
751 maFrameData.mnHelpState = DrawButtonFlags::NONE;
752 maFrameData.mbTitleClipped = false;
753 }
754
~ImplStdBorderWindowView()755 ImplStdBorderWindowView::~ImplStdBorderWindowView()
756 {
757 }
758
MouseMove(const MouseEvent & rMEvt)759 bool ImplStdBorderWindowView::MouseMove( const MouseEvent& rMEvt )
760 {
761 ImplMouseMove( &maFrameData, rMEvt );
762 return true;
763 }
764
MouseButtonDown(const MouseEvent & rMEvt)765 bool ImplStdBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
766 {
767 ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
768
769 if ( rMEvt.IsLeft() || rMEvt.IsRight() )
770 {
771 maFrameData.maMouseOff = rMEvt.GetPosPixel();
772 maFrameData.mnHitTest = ImplHitTest( &maFrameData, maFrameData.maMouseOff );
773 if ( maFrameData.mnHitTest != BorderWindowHitTest::NONE )
774 {
775 DragFullOptions nDragFullTest = DragFullOptions::NONE;
776 bool bTracking = true;
777 bool bHitTest = true;
778
779 if ( maFrameData.mnHitTest & BorderWindowHitTest::Close )
780 {
781 maFrameData.mnCloseState |= DrawButtonFlags::Pressed;
782 pBorderWindow->InvalidateBorder();
783 }
784 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Roll )
785 {
786 maFrameData.mnRollState |= DrawButtonFlags::Pressed;
787 pBorderWindow->InvalidateBorder();
788 }
789 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Dock )
790 {
791 maFrameData.mnDockState |= DrawButtonFlags::Pressed;
792 pBorderWindow->InvalidateBorder();
793 }
794 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Menu )
795 {
796 maFrameData.mnMenuState |= DrawButtonFlags::Pressed;
797 pBorderWindow->InvalidateBorder();
798
799 // call handler already on mouse down
800 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
801 {
802 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
803 pClientWindow->TitleButtonClick( TitleButton::Menu );
804 }
805 }
806 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Hide )
807 {
808 maFrameData.mnHideState |= DrawButtonFlags::Pressed;
809 pBorderWindow->InvalidateBorder();
810 }
811 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Help )
812 {
813 maFrameData.mnHelpState |= DrawButtonFlags::Pressed;
814 pBorderWindow->InvalidateBorder();
815 }
816 else
817 {
818 if ( rMEvt.GetClicks() == 1 )
819 {
820 Point aPos = pBorderWindow->GetPosPixel();
821 Size aSize = pBorderWindow->GetOutputSizePixel();
822 maFrameData.mnTrackX = aPos.X();
823 maFrameData.mnTrackY = aPos.Y();
824 maFrameData.mnTrackWidth = aSize.Width();
825 maFrameData.mnTrackHeight = aSize.Height();
826
827 if (maFrameData.mnHitTest & BorderWindowHitTest::Title)
828 nDragFullTest = DragFullOptions::WindowMove;
829 else
830 nDragFullTest = DragFullOptions::WindowSize;
831 }
832 else
833 {
834 bTracking = false;
835
836 if ( (maFrameData.mnHitTest & BorderWindowHitTest::Title) &&
837 ((rMEvt.GetClicks() % 2) == 0) )
838 {
839 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
840 bHitTest = false;
841
842 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
843 {
844 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
845 // always perform docking on double click, no button required
846 pClientWindow->TitleButtonClick( TitleButton::Docking );
847 }
848 }
849 }
850 }
851
852 if ( bTracking )
853 {
854 maFrameData.mbDragFull = false;
855 if ( nDragFullTest != DragFullOptions::NONE )
856 maFrameData.mbDragFull = true; // always fulldrag for proper docking, ignore system settings
857 pBorderWindow->StartTracking();
858 }
859 else if ( bHitTest )
860 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
861 }
862 }
863
864 return true;
865 }
866
Tracking(const TrackingEvent & rTEvt)867 bool ImplStdBorderWindowView::Tracking( const TrackingEvent& rTEvt )
868 {
869 ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
870
871 if ( rTEvt.IsTrackingEnded() )
872 {
873 BorderWindowHitTest nHitTest = maFrameData.mnHitTest;
874 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
875
876 if ( nHitTest & BorderWindowHitTest::Close )
877 {
878 if ( maFrameData.mnCloseState & DrawButtonFlags::Pressed )
879 {
880 maFrameData.mnCloseState &= ~DrawButtonFlags::Pressed;
881 pBorderWindow->InvalidateBorder();
882
883 // do not call a Click-Handler when aborting
884 if ( !rTEvt.IsTrackingCanceled() )
885 {
886 // dispatch to correct window type (why is Close() not virtual ??? )
887 // TODO: make Close() virtual
888 VclPtr<vcl::Window> pWin = pBorderWindow->ImplGetClientWindow()->ImplGetWindow();
889 SystemWindow *pSysWin = dynamic_cast<SystemWindow* >(pWin.get());
890 DockingWindow *pDockWin = dynamic_cast<DockingWindow*>(pWin.get());
891 if ( pSysWin )
892 pSysWin->Close();
893 else if ( pDockWin )
894 pDockWin->Close();
895 }
896 }
897 }
898 else if ( nHitTest & BorderWindowHitTest::Roll )
899 {
900 if ( maFrameData.mnRollState & DrawButtonFlags::Pressed )
901 {
902 maFrameData.mnRollState &= ~DrawButtonFlags::Pressed;
903 pBorderWindow->InvalidateBorder();
904
905 // do not call a Click-Handler when aborting
906 if ( !rTEvt.IsTrackingCanceled() )
907 {
908 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
909 {
910 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
911 if ( pClientWindow->IsRollUp() )
912 pClientWindow->RollDown();
913 else
914 pClientWindow->RollUp();
915 }
916 }
917 }
918 }
919 else if ( nHitTest & BorderWindowHitTest::Dock )
920 {
921 if ( maFrameData.mnDockState & DrawButtonFlags::Pressed )
922 {
923 maFrameData.mnDockState &= ~DrawButtonFlags::Pressed;
924 pBorderWindow->InvalidateBorder();
925
926 // do not call a Click-Handler when aborting
927 if ( !rTEvt.IsTrackingCanceled() )
928 {
929 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
930 {
931 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
932 pClientWindow->TitleButtonClick( TitleButton::Docking );
933 }
934 }
935 }
936 }
937 else if ( nHitTest & BorderWindowHitTest::Menu )
938 {
939 if ( maFrameData.mnMenuState & DrawButtonFlags::Pressed )
940 {
941 maFrameData.mnMenuState &= ~DrawButtonFlags::Pressed;
942 pBorderWindow->InvalidateBorder();
943
944 // handler already called on mouse down
945 }
946 }
947 else if ( nHitTest & BorderWindowHitTest::Hide )
948 {
949 if ( maFrameData.mnHideState & DrawButtonFlags::Pressed )
950 {
951 maFrameData.mnHideState &= ~DrawButtonFlags::Pressed;
952 pBorderWindow->InvalidateBorder();
953
954 // do not call a Click-Handler when aborting
955 if ( !rTEvt.IsTrackingCanceled() )
956 {
957 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
958 {
959 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
960 pClientWindow->TitleButtonClick( TitleButton::Hide );
961 }
962 }
963 }
964 }
965 else if ( nHitTest & BorderWindowHitTest::Help )
966 {
967 if ( maFrameData.mnHelpState & DrawButtonFlags::Pressed )
968 {
969 maFrameData.mnHelpState &= ~DrawButtonFlags::Pressed;
970 pBorderWindow->InvalidateBorder();
971 }
972 }
973 else
974 {
975 if ( maFrameData.mbDragFull )
976 {
977 // restore old state when aborting
978 if ( rTEvt.IsTrackingCanceled() )
979 pBorderWindow->SetPosSizePixel( Point( maFrameData.mnTrackX, maFrameData.mnTrackY ), Size( maFrameData.mnTrackWidth, maFrameData.mnTrackHeight ) );
980 }
981 else
982 {
983 pBorderWindow->HideTracking();
984 if ( !rTEvt.IsTrackingCanceled() )
985 pBorderWindow->SetPosSizePixel( Point( maFrameData.mnTrackX, maFrameData.mnTrackY ), Size( maFrameData.mnTrackWidth, maFrameData.mnTrackHeight ) );
986 }
987
988 if ( !rTEvt.IsTrackingCanceled() )
989 {
990 if ( pBorderWindow->ImplGetClientWindow()->ImplIsFloatingWindow() )
991 {
992 if ( static_cast<FloatingWindow*>(pBorderWindow->ImplGetClientWindow())->IsInPopupMode() )
993 static_cast<FloatingWindow*>(pBorderWindow->ImplGetClientWindow())->EndPopupMode( FloatWinPopupEndFlags::TearOff );
994 }
995 }
996 }
997 }
998 else if ( !rTEvt.GetMouseEvent().IsSynthetic() )
999 {
1000 Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1001
1002 if ( maFrameData.mnHitTest & BorderWindowHitTest::Close )
1003 {
1004 if ( maFrameData.maCloseRect.IsInside( aMousePos ) )
1005 {
1006 if ( !(maFrameData.mnCloseState & DrawButtonFlags::Pressed) )
1007 {
1008 maFrameData.mnCloseState |= DrawButtonFlags::Pressed;
1009 pBorderWindow->InvalidateBorder();
1010 }
1011 }
1012 else
1013 {
1014 if ( maFrameData.mnCloseState & DrawButtonFlags::Pressed )
1015 {
1016 maFrameData.mnCloseState &= ~DrawButtonFlags::Pressed;
1017 pBorderWindow->InvalidateBorder();
1018 }
1019 }
1020 }
1021 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Roll )
1022 {
1023 if ( maFrameData.maRollRect.IsInside( aMousePos ) )
1024 {
1025 if ( !(maFrameData.mnRollState & DrawButtonFlags::Pressed) )
1026 {
1027 maFrameData.mnRollState |= DrawButtonFlags::Pressed;
1028 pBorderWindow->InvalidateBorder();
1029 }
1030 }
1031 else
1032 {
1033 if ( maFrameData.mnRollState & DrawButtonFlags::Pressed )
1034 {
1035 maFrameData.mnRollState &= ~DrawButtonFlags::Pressed;
1036 pBorderWindow->InvalidateBorder();
1037 }
1038 }
1039 }
1040 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Dock )
1041 {
1042 if ( maFrameData.maDockRect.IsInside( aMousePos ) )
1043 {
1044 if ( !(maFrameData.mnDockState & DrawButtonFlags::Pressed) )
1045 {
1046 maFrameData.mnDockState |= DrawButtonFlags::Pressed;
1047 pBorderWindow->InvalidateBorder();
1048 }
1049 }
1050 else
1051 {
1052 if ( maFrameData.mnDockState & DrawButtonFlags::Pressed )
1053 {
1054 maFrameData.mnDockState &= ~DrawButtonFlags::Pressed;
1055 pBorderWindow->InvalidateBorder();
1056 }
1057 }
1058 }
1059 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Menu )
1060 {
1061 if ( maFrameData.maMenuRect.IsInside( aMousePos ) )
1062 {
1063 if ( !(maFrameData.mnMenuState & DrawButtonFlags::Pressed) )
1064 {
1065 maFrameData.mnMenuState |= DrawButtonFlags::Pressed;
1066 pBorderWindow->InvalidateBorder();
1067 }
1068 }
1069 else
1070 {
1071 if ( maFrameData.mnMenuState & DrawButtonFlags::Pressed )
1072 {
1073 maFrameData.mnMenuState &= ~DrawButtonFlags::Pressed;
1074 pBorderWindow->InvalidateBorder();
1075 }
1076 }
1077 }
1078 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Hide )
1079 {
1080 if ( maFrameData.maHideRect.IsInside( aMousePos ) )
1081 {
1082 if ( !(maFrameData.mnHideState & DrawButtonFlags::Pressed) )
1083 {
1084 maFrameData.mnHideState |= DrawButtonFlags::Pressed;
1085 pBorderWindow->InvalidateBorder();
1086 }
1087 }
1088 else
1089 {
1090 if ( maFrameData.mnHideState & DrawButtonFlags::Pressed )
1091 {
1092 maFrameData.mnHideState &= ~DrawButtonFlags::Pressed;
1093 pBorderWindow->InvalidateBorder();
1094 }
1095 }
1096 }
1097 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Help )
1098 {
1099 if ( maFrameData.maHelpRect.IsInside( aMousePos ) )
1100 {
1101 if ( !(maFrameData.mnHelpState & DrawButtonFlags::Pressed) )
1102 {
1103 maFrameData.mnHelpState |= DrawButtonFlags::Pressed;
1104 pBorderWindow->InvalidateBorder();
1105 }
1106 }
1107 else
1108 {
1109 if ( maFrameData.mnHelpState & DrawButtonFlags::Pressed )
1110 {
1111 maFrameData.mnHelpState &= ~DrawButtonFlags::Pressed;
1112 pBorderWindow->InvalidateBorder();
1113 }
1114 }
1115 }
1116 else
1117 {
1118 aMousePos.AdjustX( -(maFrameData.maMouseOff.X()) );
1119 aMousePos.AdjustY( -(maFrameData.maMouseOff.Y()) );
1120
1121 if ( maFrameData.mnHitTest & BorderWindowHitTest::Title )
1122 {
1123 maFrameData.mpBorderWindow->SetPointer( PointerStyle::Move );
1124
1125 Point aPos = pBorderWindow->GetPosPixel();
1126 aPos.AdjustX(aMousePos.X() );
1127 aPos.AdjustY(aMousePos.Y() );
1128 if ( maFrameData.mbDragFull )
1129 {
1130 pBorderWindow->SetPosPixel( aPos );
1131 pBorderWindow->ImplUpdateAll();
1132 pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
1133 }
1134 else
1135 {
1136 maFrameData.mnTrackX = aPos.X();
1137 maFrameData.mnTrackY = aPos.Y();
1138 pBorderWindow->ShowTracking( tools::Rectangle( pBorderWindow->ScreenToOutputPixel( aPos ), pBorderWindow->GetOutputSizePixel() ), ShowTrackFlags::Big );
1139 }
1140 }
1141 else
1142 {
1143 Point aOldPos = pBorderWindow->GetPosPixel();
1144 Size aSize = pBorderWindow->GetSizePixel();
1145 tools::Rectangle aNewRect( aOldPos, aSize );
1146 long nOldWidth = aSize.Width();
1147 long nOldHeight = aSize.Height();
1148 long nBorderWidth = maFrameData.mnLeftBorder+maFrameData.mnRightBorder;
1149 long nBorderHeight = maFrameData.mnTopBorder+maFrameData.mnBottomBorder;
1150 long nMinWidth = pBorderWindow->mnMinWidth+nBorderWidth;
1151 long nMinHeight = pBorderWindow->mnMinHeight+nBorderHeight;
1152 long nMinWidth2 = nBorderWidth;
1153 long nMaxWidth = pBorderWindow->mnMaxWidth+nBorderWidth;
1154 long nMaxHeight = pBorderWindow->mnMaxHeight+nBorderHeight;
1155
1156 if ( maFrameData.mnTitleHeight )
1157 {
1158 nMinWidth2 += 4;
1159
1160 if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
1161 nMinWidth2 += maFrameData.maCloseRect.GetWidth();
1162 }
1163 if ( nMinWidth2 > nMinWidth )
1164 nMinWidth = nMinWidth2;
1165 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Left | BorderWindowHitTest::TopLeft | BorderWindowHitTest::BottomLeft) )
1166 {
1167 aNewRect.AdjustLeft(aMousePos.X() );
1168 if ( aNewRect.GetWidth() < nMinWidth )
1169 aNewRect.SetLeft( aNewRect.Right()-nMinWidth+1 );
1170 else if ( aNewRect.GetWidth() > nMaxWidth )
1171 aNewRect.SetLeft( aNewRect.Right()-nMaxWidth+1 );
1172 }
1173 else if ( maFrameData.mnHitTest & (BorderWindowHitTest::Right | BorderWindowHitTest::TopRight | BorderWindowHitTest::BottomRight) )
1174 {
1175 aNewRect.AdjustRight(aMousePos.X() );
1176 if ( aNewRect.GetWidth() < nMinWidth )
1177 aNewRect.SetRight( aNewRect.Left()+nMinWidth+1 );
1178 else if ( aNewRect.GetWidth() > nMaxWidth )
1179 aNewRect.SetRight( aNewRect.Left()+nMaxWidth+1 );
1180 }
1181 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Top | BorderWindowHitTest::TopLeft | BorderWindowHitTest::TopRight) )
1182 {
1183 aNewRect.AdjustTop(aMousePos.Y() );
1184 if ( aNewRect.GetHeight() < nMinHeight )
1185 aNewRect.SetTop( aNewRect.Bottom()-nMinHeight+1 );
1186 else if ( aNewRect.GetHeight() > nMaxHeight )
1187 aNewRect.SetTop( aNewRect.Bottom()-nMaxHeight+1 );
1188 }
1189 else if ( maFrameData.mnHitTest & (BorderWindowHitTest::Bottom | BorderWindowHitTest::BottomLeft | BorderWindowHitTest::BottomRight) )
1190 {
1191 aNewRect.AdjustBottom(aMousePos.Y() );
1192 if ( aNewRect.GetHeight() < nMinHeight )
1193 aNewRect.SetBottom( aNewRect.Top()+nMinHeight+1 );
1194 else if ( aNewRect.GetHeight() > nMaxHeight )
1195 aNewRect.SetBottom( aNewRect.Top()+nMaxHeight+1 );
1196 }
1197
1198 // call Resizing-Handler for SystemWindows
1199 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
1200 {
1201 // adjust size for Resizing-call
1202 aSize = aNewRect.GetSize();
1203 aSize.AdjustWidth( -nBorderWidth );
1204 aSize.AdjustHeight( -nBorderHeight );
1205 static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow())->Resizing( aSize );
1206 aSize.AdjustWidth(nBorderWidth );
1207 aSize.AdjustHeight(nBorderHeight );
1208 if ( aSize.Width() < nMinWidth )
1209 aSize.setWidth( nMinWidth );
1210 if ( aSize.Height() < nMinHeight )
1211 aSize.setHeight( nMinHeight );
1212 if ( aSize.Width() > nMaxWidth )
1213 aSize.setWidth( nMaxWidth );
1214 if ( aSize.Height() > nMaxHeight )
1215 aSize.setHeight( nMaxHeight );
1216 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Left | BorderWindowHitTest::TopLeft | BorderWindowHitTest::BottomLeft) )
1217 aNewRect.SetLeft( aNewRect.Right()-aSize.Width()+1 );
1218 else
1219 aNewRect.SetRight( aNewRect.Left()+aSize.Width()-1 );
1220 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Top | BorderWindowHitTest::TopLeft | BorderWindowHitTest::TopRight) )
1221 aNewRect.SetTop( aNewRect.Bottom()-aSize.Height()+1 );
1222 else
1223 aNewRect.SetBottom( aNewRect.Top()+aSize.Height()-1 );
1224 }
1225
1226 if ( maFrameData.mbDragFull )
1227 {
1228 // no move (only resize) if position did not change
1229 if( aOldPos != aNewRect.TopLeft() )
1230 pBorderWindow->setPosSizePixel( aNewRect.Left(), aNewRect.Top(),
1231 aNewRect.GetWidth(), aNewRect.GetHeight() );
1232 else
1233 pBorderWindow->setPosSizePixel( aNewRect.Left(), aNewRect.Top(),
1234 aNewRect.GetWidth(), aNewRect.GetHeight(), PosSizeFlags::Size );
1235
1236 pBorderWindow->ImplUpdateAll();
1237 pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
1238 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Right | BorderWindowHitTest::TopRight | BorderWindowHitTest::BottomRight) )
1239 maFrameData.maMouseOff.AdjustX(aNewRect.GetWidth()-nOldWidth );
1240 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Bottom | BorderWindowHitTest::BottomLeft | BorderWindowHitTest::BottomRight) )
1241 maFrameData.maMouseOff.AdjustY(aNewRect.GetHeight()-nOldHeight );
1242 }
1243 else
1244 {
1245 maFrameData.mnTrackX = aNewRect.Left();
1246 maFrameData.mnTrackY = aNewRect.Top();
1247 maFrameData.mnTrackWidth = aNewRect.GetWidth();
1248 maFrameData.mnTrackHeight = aNewRect.GetHeight();
1249 pBorderWindow->ShowTracking( tools::Rectangle( pBorderWindow->ScreenToOutputPixel( aNewRect.TopLeft() ), aNewRect.GetSize() ), ShowTrackFlags::Big );
1250 }
1251 }
1252 }
1253 }
1254
1255 return true;
1256 }
1257
RequestHelp(const Point & rPos,tools::Rectangle & rHelpRect)1258 OUString ImplStdBorderWindowView::RequestHelp( const Point& rPos, tools::Rectangle& rHelpRect )
1259 {
1260 return ImplRequestHelp( &maFrameData, rPos, rHelpRect );
1261 }
1262
GetMenuRect() const1263 tools::Rectangle ImplStdBorderWindowView::GetMenuRect() const
1264 {
1265 return maFrameData.maMenuRect;
1266 }
1267
Init(OutputDevice * pDev,long nWidth,long nHeight)1268 void ImplStdBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
1269 {
1270 ImplBorderFrameData* pData = &maFrameData;
1271 ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
1272 const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
1273 DecorationView aDecoView( pDev );
1274 tools::Rectangle aRect( 0, 0, 10, 10 );
1275 tools::Rectangle aCalcRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleOut, DrawFrameFlags::NoDraw );
1276
1277 pData->mpOutDev = pDev;
1278 pData->mnWidth = nWidth;
1279 pData->mnHeight = nHeight;
1280
1281 pData->mnTitleType = pBorderWindow->mnTitleType;
1282
1283 if ( !(pBorderWindow->GetStyle() & (WB_MOVEABLE | WB_POPUP)) || (pData->mnTitleType == BorderWindowTitleType::NONE) )
1284 pData->mnBorderSize = 0;
1285 else if ( pData->mnTitleType == BorderWindowTitleType::Tearoff )
1286 pData->mnBorderSize = 0;
1287 else
1288 pData->mnBorderSize = StyleSettings::GetBorderSize();
1289 pData->mnLeftBorder = aCalcRect.Left();
1290 pData->mnTopBorder = aCalcRect.Top();
1291 pData->mnRightBorder = aRect.Right()-aCalcRect.Right();
1292 pData->mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
1293 pData->mnLeftBorder += pData->mnBorderSize;
1294 pData->mnTopBorder += pData->mnBorderSize;
1295 pData->mnRightBorder += pData->mnBorderSize;
1296 pData->mnBottomBorder += pData->mnBorderSize;
1297 pData->mnNoTitleTop = pData->mnTopBorder;
1298
1299 ImplInitTitle(&maFrameData);
1300 if (pData->mnTitleHeight)
1301 {
1302 // to improve symbol display force a minimum title height
1303 if (pData->mnTitleType != BorderWindowTitleType::Tearoff &&
1304 pData->mnTitleHeight < MIN_CAPTION_HEIGHT)
1305 pData->mnTitleHeight = MIN_CAPTION_HEIGHT;
1306
1307 // set a proper background for drawing
1308 // highlighted buttons in the title
1309 pBorderWindow->SetBackground( rStyleSettings.GetFaceColor() );
1310
1311 pData->maTitleRect.SetLeft( pData->mnLeftBorder );
1312 pData->maTitleRect.SetRight( nWidth-pData->mnRightBorder-1 );
1313 pData->maTitleRect.SetTop( pData->mnTopBorder );
1314 pData->maTitleRect.SetBottom( pData->maTitleRect.Top()+pData->mnTitleHeight-1 );
1315
1316 if ( pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small) )
1317 {
1318 long nRight = pData->maTitleRect.Right() - 3;
1319 long const nItemTop = pData->maTitleRect.Top() + 2;
1320 long const nItemBottom = pData->maTitleRect.Bottom() - 2;
1321
1322 auto addSquareOnRight = [&nRight, nItemTop, nItemBottom](
1323 tools::Rectangle & rect, long gap)
1324 {
1325 rect.SetTop( nItemTop );
1326 rect.SetBottom( nItemBottom );
1327 rect.SetRight( nRight );
1328 rect.SetLeft( rect.Right() - rect.GetHeight() + 1 );
1329 nRight -= rect.GetWidth() + gap;
1330 };
1331
1332 if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
1333 {
1334 addSquareOnRight(pData->maCloseRect, 3);
1335 }
1336
1337 if ( pBorderWindow->mbMenuBtn )
1338 {
1339 addSquareOnRight(pData->maMenuRect, 0);
1340 }
1341
1342 if ( pBorderWindow->mbDockBtn )
1343 {
1344 addSquareOnRight(pData->maDockRect, 0);
1345 }
1346
1347 if ( pBorderWindow->mbHideBtn )
1348 {
1349 addSquareOnRight(pData->maHideRect, 0);
1350 }
1351
1352 if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
1353 {
1354 addSquareOnRight(pData->maRollRect, 0);
1355 }
1356 }
1357 else
1358 {
1359 pData->maCloseRect.SetEmpty();
1360 pData->maDockRect.SetEmpty();
1361 pData->maMenuRect.SetEmpty();
1362 pData->maHideRect.SetEmpty();
1363 pData->maRollRect.SetEmpty();
1364 pData->maHelpRect.SetEmpty();
1365 }
1366
1367 pData->mnTopBorder += pData->mnTitleHeight;
1368 }
1369 else
1370 {
1371 pData->maTitleRect.SetEmpty();
1372 pData->maCloseRect.SetEmpty();
1373 pData->maDockRect.SetEmpty();
1374 pData->maMenuRect.SetEmpty();
1375 pData->maHideRect.SetEmpty();
1376 pData->maRollRect.SetEmpty();
1377 pData->maHelpRect.SetEmpty();
1378 }
1379 }
1380
GetBorder(sal_Int32 & rLeftBorder,sal_Int32 & rTopBorder,sal_Int32 & rRightBorder,sal_Int32 & rBottomBorder) const1381 void ImplStdBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
1382 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
1383 {
1384 rLeftBorder = maFrameData.mnLeftBorder;
1385 rTopBorder = maFrameData.mnTopBorder;
1386 rRightBorder = maFrameData.mnRightBorder;
1387 rBottomBorder = maFrameData.mnBottomBorder;
1388 }
1389
CalcTitleWidth() const1390 long ImplStdBorderWindowView::CalcTitleWidth() const
1391 {
1392 return ImplCalcTitleWidth( &maFrameData );
1393 }
1394
DrawWindow(vcl::RenderContext & rRenderContext,const Point * pOffset)1395 void ImplStdBorderWindowView::DrawWindow(vcl::RenderContext& rRenderContext, const Point* pOffset)
1396 {
1397 ImplBorderFrameData* pData = &maFrameData;
1398 ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
1399 Point aTmpPoint = pOffset ? *pOffset : Point();
1400 tools::Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) );
1401 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1402 DecorationView aDecoView(&rRenderContext);
1403 Color aFaceColor(rStyleSettings.GetFaceColor());
1404 Color aFrameColor(aFaceColor);
1405
1406 aFrameColor.DecreaseContrast(sal_uInt8(0.5 * 255));
1407
1408 // Draw Frame
1409 vcl::Region oldClipRgn(rRenderContext.GetClipRegion());
1410
1411 // for popups, don't draw part of the frame
1412 if (!(pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small)))
1413 {
1414 FloatingWindow* pWin = dynamic_cast<FloatingWindow*>(pData->mpBorderWindow->GetWindow(GetWindowType::Client));
1415 if (pWin)
1416 {
1417 vcl::Region aClipRgn(aInRect);
1418 tools::Rectangle aItemClipRect(pWin->ImplGetItemEdgeClipRect());
1419 if (!aItemClipRect.IsEmpty())
1420 {
1421 aItemClipRect.SetPos(pData->mpBorderWindow->AbsoluteScreenToOutputPixel(aItemClipRect.TopLeft()));
1422 aClipRgn.Exclude(aItemClipRect);
1423 rRenderContext.SetClipRegion(aClipRgn);
1424 }
1425 }
1426 }
1427
1428 // single line frame
1429 rRenderContext.SetLineColor(aFrameColor);
1430 rRenderContext.SetFillColor();
1431 rRenderContext.DrawRect(aInRect);
1432 aInRect.AdjustLeft( 1 );
1433 aInRect.AdjustRight( -1 );
1434 aInRect.AdjustTop( 1 );
1435 aInRect.AdjustBottom( -1 );
1436
1437 // restore
1438 if (!(pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small)))
1439 rRenderContext.SetClipRegion(oldClipRgn);
1440
1441 // Draw Border
1442 rRenderContext.SetLineColor();
1443 long nBorderSize = pData->mnBorderSize;
1444 if (nBorderSize)
1445 {
1446 rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
1447 rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Top()),
1448 Size(aInRect.GetWidth(), nBorderSize)));
1449 rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Top() + nBorderSize),
1450 Size(nBorderSize, aInRect.GetHeight() - nBorderSize)));
1451 rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Bottom() - nBorderSize + 1),
1452 Size(aInRect.GetWidth(), nBorderSize)));
1453 rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Right()-nBorderSize + 1, aInRect.Top() + nBorderSize),
1454 Size(nBorderSize, aInRect.GetHeight() - nBorderSize)));
1455 }
1456
1457 // Draw Title
1458 if (!pData->maTitleRect.IsEmpty())
1459 {
1460 aInRect = pData->maTitleRect;
1461
1462 // use no gradient anymore, just a static titlecolor
1463 if (pData->mnTitleType == BorderWindowTitleType::Tearoff)
1464 rRenderContext.SetFillColor(rStyleSettings.GetFaceGradientColor());
1465 else if (pData->mnTitleType == BorderWindowTitleType::Popup)
1466 rRenderContext.SetFillColor(aFaceColor);
1467 else
1468 rRenderContext.SetFillColor(aFrameColor);
1469
1470 rRenderContext.SetTextColor(rStyleSettings.GetButtonTextColor());
1471 tools::Rectangle aTitleRect(pData->maTitleRect);
1472 if(pOffset)
1473 aTitleRect.Move(pOffset->X(), pOffset->Y());
1474 rRenderContext.DrawRect(aTitleRect);
1475
1476 if (pData->mnTitleType != BorderWindowTitleType::Tearoff)
1477 {
1478 aInRect.AdjustLeft(2 );
1479 aInRect.AdjustRight( -2 );
1480
1481 if (!pData->maHelpRect.IsEmpty())
1482 aInRect.SetRight( pData->maHelpRect.Left() - 2 );
1483 else if (!pData->maRollRect.IsEmpty())
1484 aInRect.SetRight( pData->maRollRect.Left() - 2 );
1485 else if (!pData->maHideRect.IsEmpty())
1486 aInRect.SetRight( pData->maHideRect.Left() - 2 );
1487 else if (!pData->maDockRect.IsEmpty())
1488 aInRect.SetRight( pData->maDockRect.Left() - 2 );
1489 else if (!pData->maMenuRect.IsEmpty())
1490 aInRect.SetRight( pData->maMenuRect.Left() - 2 );
1491 else if (!pData->maCloseRect.IsEmpty())
1492 aInRect.SetRight( pData->maCloseRect.Left() - 2 );
1493
1494 if (pOffset)
1495 aInRect.Move(pOffset->X(), pOffset->Y());
1496
1497 DrawTextFlags nTextStyle = DrawTextFlags::Left | DrawTextFlags::VCenter | DrawTextFlags::EndEllipsis | DrawTextFlags::Clip;
1498
1499 // must show tooltip ?
1500 TextRectInfo aInfo;
1501 rRenderContext.GetTextRect(aInRect, pBorderWindow->GetText(), nTextStyle, &aInfo);
1502 pData->mbTitleClipped = aInfo.IsEllipses();
1503
1504 rRenderContext.DrawText(aInRect, pBorderWindow->GetText(), nTextStyle);
1505 }
1506 else
1507 {
1508 ToolBox::ImplDrawGrip(rRenderContext, aTitleRect, ToolBox::ImplGetDragWidth(rRenderContext, false),
1509 WindowAlign::Left, false);
1510 }
1511 }
1512
1513 if (!pData->maCloseRect.IsEmpty())
1514 {
1515 tools::Rectangle aSymbolRect(pData->maCloseRect);
1516 if (pOffset)
1517 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1518 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::CLOSE, pData->mnCloseState);
1519 }
1520 if (!pData->maDockRect.IsEmpty())
1521 {
1522 tools::Rectangle aSymbolRect(pData->maDockRect);
1523 if (pOffset)
1524 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1525 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::DOCK, pData->mnDockState);
1526 }
1527 if (!pData->maMenuRect.IsEmpty())
1528 {
1529 tools::Rectangle aSymbolRect(pData->maMenuRect);
1530 if (pOffset)
1531 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1532 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::MENU, pData->mnMenuState);
1533 }
1534 if (!pData->maHideRect.IsEmpty())
1535 {
1536 tools::Rectangle aSymbolRect(pData->maHideRect);
1537 if (pOffset)
1538 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1539 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::HIDE, pData->mnHideState);
1540 }
1541 if (!pData->maRollRect.IsEmpty())
1542 {
1543 SymbolType eType;
1544 if (pBorderWindow->mbRollUp)
1545 eType = SymbolType::ROLLDOWN;
1546 else
1547 eType = SymbolType::ROLLUP;
1548 tools::Rectangle aSymbolRect(pData->maRollRect);
1549 if (pOffset)
1550 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1551 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, eType, pData->mnRollState);
1552 }
1553
1554 if (!pData->maHelpRect.IsEmpty())
1555 {
1556 tools::Rectangle aSymbolRect(pData->maHelpRect);
1557 if (pOffset)
1558 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1559 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::HELP, pData->mnHelpState);
1560 }
1561 }
1562
ImplInit(vcl::Window * pParent,WinBits nStyle,BorderWindowStyle nTypeStyle,SystemParentData * pSystemParentData)1563 void ImplBorderWindow::ImplInit( vcl::Window* pParent,
1564 WinBits nStyle, BorderWindowStyle nTypeStyle,
1565 SystemParentData* pSystemParentData
1566 )
1567 {
1568 // remove all unwanted WindowBits
1569 WinBits nOrgStyle = nStyle;
1570 WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW | WB_POPUP);
1571 if ( nTypeStyle & BorderWindowStyle::App )
1572 nTestStyle |= WB_APP;
1573 nStyle &= nTestStyle;
1574
1575 mpWindowImpl->mbBorderWin = true;
1576 mbSmallOutBorder = false;
1577 if ( nTypeStyle & BorderWindowStyle::Frame )
1578 {
1579 if( nStyle & WB_SYSTEMCHILDWINDOW )
1580 {
1581 mpWindowImpl->mbOverlapWin = true;
1582 mpWindowImpl->mbFrame = true;
1583 mbFrameBorder = false;
1584 }
1585 else if( nStyle & (WB_OWNERDRAWDECORATION | WB_POPUP) )
1586 {
1587 mpWindowImpl->mbOverlapWin = true;
1588 mpWindowImpl->mbFrame = true;
1589 mbFrameBorder = (nOrgStyle & WB_NOBORDER) == 0;
1590 }
1591 else
1592 {
1593 mpWindowImpl->mbOverlapWin = true;
1594 mpWindowImpl->mbFrame = true;
1595 mbFrameBorder = false;
1596 // closeable windows may have a border as well, eg. system floating windows without caption
1597 if ( (nOrgStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE/* | WB_CLOSEABLE*/)) == WB_BORDER )
1598 mbSmallOutBorder = true;
1599 }
1600 }
1601 else if ( nTypeStyle & BorderWindowStyle::Overlap )
1602 {
1603 mpWindowImpl->mbOverlapWin = true;
1604 mbFrameBorder = true;
1605 }
1606 else
1607 mbFrameBorder = false;
1608
1609 if ( nTypeStyle & BorderWindowStyle::Float )
1610 mbFloatWindow = true;
1611 else
1612 mbFloatWindow = false;
1613
1614 Window::ImplInit( pParent, nStyle, pSystemParentData );
1615 SetBackground();
1616 SetTextFillColor();
1617
1618 mpMenuBarWindow = nullptr;
1619 mnMinWidth = 0;
1620 mnMinHeight = 0;
1621 mnMaxWidth = SHRT_MAX;
1622 mnMaxHeight = SHRT_MAX;
1623 mnOrgMenuHeight = 0;
1624 mbRollUp = false;
1625 mbMenuHide = false;
1626 mbDockBtn = false;
1627 mbMenuBtn = false;
1628 mbHideBtn = false;
1629 mbDisplayActive = IsActive();
1630
1631 if ( nTypeStyle & BorderWindowStyle::Float )
1632 mnTitleType = BorderWindowTitleType::Small;
1633 else
1634 mnTitleType = BorderWindowTitleType::Normal;
1635 mnBorderStyle = WindowBorderStyle::NORMAL;
1636 InitView();
1637 }
1638
ImplBorderWindow(vcl::Window * pParent,SystemParentData * pSystemParentData,WinBits nStyle,BorderWindowStyle nTypeStyle)1639 ImplBorderWindow::ImplBorderWindow( vcl::Window* pParent,
1640 SystemParentData* pSystemParentData,
1641 WinBits nStyle, BorderWindowStyle nTypeStyle
1642 ) : Window( WindowType::BORDERWINDOW )
1643 {
1644 ImplInit( pParent, nStyle, nTypeStyle, pSystemParentData );
1645 }
1646
ImplBorderWindow(vcl::Window * pParent,WinBits nStyle,BorderWindowStyle nTypeStyle)1647 ImplBorderWindow::ImplBorderWindow( vcl::Window* pParent, WinBits nStyle ,
1648 BorderWindowStyle nTypeStyle ) :
1649 Window( WindowType::BORDERWINDOW )
1650 {
1651 ImplInit( pParent, nStyle, nTypeStyle, nullptr );
1652 }
1653
~ImplBorderWindow()1654 ImplBorderWindow::~ImplBorderWindow()
1655 {
1656 disposeOnce();
1657 }
1658
dispose()1659 void ImplBorderWindow::dispose()
1660 {
1661 mpBorderView.reset();
1662 mpMenuBarWindow.clear();
1663 mpNotebookBar.disposeAndClear();
1664 vcl::Window::dispose();
1665 }
1666
MouseMove(const MouseEvent & rMEvt)1667 void ImplBorderWindow::MouseMove( const MouseEvent& rMEvt )
1668 {
1669 if (mpBorderView)
1670 mpBorderView->MouseMove( rMEvt );
1671 }
1672
MouseButtonDown(const MouseEvent & rMEvt)1673 void ImplBorderWindow::MouseButtonDown( const MouseEvent& rMEvt )
1674 {
1675 if (mpBorderView)
1676 mpBorderView->MouseButtonDown( rMEvt );
1677 }
1678
Tracking(const TrackingEvent & rTEvt)1679 void ImplBorderWindow::Tracking( const TrackingEvent& rTEvt )
1680 {
1681 if (mpBorderView)
1682 mpBorderView->Tracking( rTEvt );
1683 }
1684
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)1685 void ImplBorderWindow::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& )
1686 {
1687 if (mpBorderView)
1688 mpBorderView->DrawWindow(rRenderContext);
1689 }
1690
Draw(OutputDevice * pOutDev,const Point & rPos)1691 void ImplBorderWindow::Draw( OutputDevice* pOutDev, const Point& rPos )
1692 {
1693 if (mpBorderView)
1694 mpBorderView->DrawWindow(*pOutDev, &rPos);
1695 }
1696
Activate()1697 void ImplBorderWindow::Activate()
1698 {
1699 SetDisplayActive( true );
1700 Window::Activate();
1701 }
1702
Deactivate()1703 void ImplBorderWindow::Deactivate()
1704 {
1705 // remove active windows from the ruler, also ignore the Deactivate
1706 // if a menu becomes active
1707 if ( GetActivateMode() != ActivateModeFlags::NONE && !ImplGetSVData()->maWinData.mbNoDeactivate )
1708 SetDisplayActive( false );
1709 Window::Deactivate();
1710 }
1711
RequestHelp(const HelpEvent & rHEvt)1712 void ImplBorderWindow::RequestHelp( const HelpEvent& rHEvt )
1713 {
1714 // no keyboard help for border window
1715 if ( rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK) && !rHEvt.KeyboardActivated() )
1716 {
1717 Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
1718 tools::Rectangle aHelpRect;
1719 OUString aHelpStr( mpBorderView->RequestHelp( aMousePosPixel, aHelpRect ) );
1720
1721 // retrieve rectangle
1722 if ( !aHelpStr.isEmpty() )
1723 {
1724 aHelpRect.SetPos( OutputToScreenPixel( aHelpRect.TopLeft() ) );
1725 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
1726 Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aHelpStr );
1727 else
1728 Help::ShowQuickHelp( this, aHelpRect, aHelpStr );
1729 return;
1730 }
1731 }
1732
1733 Window::RequestHelp( rHEvt );
1734 }
1735
Resize()1736 void ImplBorderWindow::Resize()
1737 {
1738 Size aSize = GetOutputSizePixel();
1739
1740 if ( !mbRollUp )
1741 {
1742 vcl::Window* pClientWindow = ImplGetClientWindow();
1743
1744 sal_Int32 nLeftBorder;
1745 sal_Int32 nTopBorder;
1746 sal_Int32 nRightBorder;
1747 sal_Int32 nBottomBorder;
1748 mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1749
1750 if (mpMenuBarWindow)
1751 {
1752 long nMenuHeight = mpMenuBarWindow->GetSizePixel().Height();
1753 if ( mbMenuHide )
1754 {
1755 if ( nMenuHeight )
1756 mnOrgMenuHeight = nMenuHeight;
1757 nMenuHeight = 0;
1758 }
1759 else
1760 {
1761 if ( !nMenuHeight )
1762 nMenuHeight = mnOrgMenuHeight;
1763 }
1764 mpMenuBarWindow->setPosSizePixel(
1765 nLeftBorder, nTopBorder,
1766 aSize.Width()-nLeftBorder-nRightBorder,
1767 nMenuHeight);
1768
1769 // shift the notebookbar down accordingly
1770 nTopBorder += nMenuHeight;
1771 }
1772
1773 if (mpNotebookBar)
1774 {
1775 long nNotebookBarHeight = mpNotebookBar->GetSizePixel().Height();
1776
1777 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1778 const BitmapEx& aPersona = rStyleSettings.GetPersonaHeader();
1779 // since size of notebookbar changes, to make common persona for menubar
1780 // and notebookbar persona should be set again with changed coordinates
1781 if (!aPersona.IsEmpty())
1782 {
1783 Wallpaper aWallpaper(aPersona);
1784 aWallpaper.SetStyle(WallpaperStyle::TopRight);
1785 aWallpaper.SetRect(tools::Rectangle(Point(0, -nTopBorder),
1786 Size(aSize.Width() - nLeftBorder - nRightBorder,
1787 nNotebookBarHeight + nTopBorder)));
1788 mpNotebookBar->SetBackground(aWallpaper);
1789 }
1790
1791 mpNotebookBar->setPosSizePixel(
1792 nLeftBorder, nTopBorder,
1793 aSize.Width() - nLeftBorder - nRightBorder,
1794 nNotebookBarHeight);
1795 }
1796
1797 GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder,
1798 pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder );
1799 pClientWindow->ImplPosSizeWindow( pClientWindow->mpWindowImpl->mnLeftBorder,
1800 pClientWindow->mpWindowImpl->mnTopBorder,
1801 aSize.Width()-pClientWindow->mpWindowImpl->mnLeftBorder-pClientWindow->mpWindowImpl->mnRightBorder,
1802 aSize.Height()-pClientWindow->mpWindowImpl->mnTopBorder-pClientWindow->mpWindowImpl->mnBottomBorder,
1803 PosSizeFlags::X | PosSizeFlags::Y |
1804 PosSizeFlags::Width | PosSizeFlags::Height );
1805 }
1806
1807 // UpdateView
1808 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1809 InvalidateBorder();
1810
1811 Window::Resize();
1812 }
1813
StateChanged(StateChangedType nType)1814 void ImplBorderWindow::StateChanged( StateChangedType nType )
1815 {
1816 if ( (nType == StateChangedType::Text) ||
1817 (nType == StateChangedType::Data) )
1818 {
1819 if (IsReallyVisible() && mbFrameBorder)
1820 InvalidateBorder();
1821 }
1822
1823 Window::StateChanged( nType );
1824 }
1825
DataChanged(const DataChangedEvent & rDCEvt)1826 void ImplBorderWindow::DataChanged( const DataChangedEvent& rDCEvt )
1827 {
1828 if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1829 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1830 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1831 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1832 {
1833 if ( !mpWindowImpl->mbFrame || (GetStyle() & (WB_OWNERDRAWDECORATION | WB_POPUP)) )
1834 UpdateView( true, ImplGetWindow()->GetOutputSizePixel() );
1835 }
1836
1837 Window::DataChanged( rDCEvt );
1838 }
1839
InitView()1840 void ImplBorderWindow::InitView()
1841 {
1842 if ( mbSmallOutBorder )
1843 mpBorderView.reset(new ImplSmallBorderWindowView( this ));
1844 else if ( mpWindowImpl->mbFrame )
1845 {
1846 if( mbFrameBorder )
1847 mpBorderView.reset(new ImplStdBorderWindowView( this ));
1848 else
1849 mpBorderView.reset(new ImplNoBorderWindowView);
1850 }
1851 else if ( !mbFrameBorder )
1852 mpBorderView.reset(new ImplSmallBorderWindowView( this ));
1853 else
1854 mpBorderView.reset(new ImplStdBorderWindowView( this ));
1855 Size aSize = GetOutputSizePixel();
1856 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1857 }
1858
UpdateView(bool bNewView,const Size & rNewOutSize)1859 void ImplBorderWindow::UpdateView( bool bNewView, const Size& rNewOutSize )
1860 {
1861 sal_Int32 nLeftBorder;
1862 sal_Int32 nTopBorder;
1863 sal_Int32 nRightBorder;
1864 sal_Int32 nBottomBorder;
1865 Size aOldSize = GetSizePixel();
1866 Size aOutputSize = rNewOutSize;
1867
1868 if ( bNewView )
1869 {
1870 mpBorderView.reset();
1871 InitView();
1872 }
1873 else
1874 {
1875 Size aSize = aOutputSize;
1876 mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1877 aSize.AdjustWidth(nLeftBorder+nRightBorder );
1878 aSize.AdjustHeight(nTopBorder+nBottomBorder );
1879 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1880 }
1881
1882 vcl::Window* pClientWindow = ImplGetClientWindow();
1883 if ( pClientWindow )
1884 {
1885 GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder,
1886 pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder );
1887 }
1888 GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1889 if ( aOldSize.Width() || aOldSize.Height() )
1890 {
1891 aOutputSize.AdjustWidth(nLeftBorder+nRightBorder );
1892 aOutputSize.AdjustHeight(nTopBorder+nBottomBorder );
1893 if ( aOutputSize == GetSizePixel() )
1894 InvalidateBorder();
1895 else
1896 SetSizePixel( aOutputSize );
1897 }
1898 }
1899
InvalidateBorder()1900 void ImplBorderWindow::InvalidateBorder()
1901 {
1902 if ( IsReallyVisible() )
1903 {
1904 // invalidate only if we have a border
1905 sal_Int32 nLeftBorder;
1906 sal_Int32 nTopBorder;
1907 sal_Int32 nRightBorder;
1908 sal_Int32 nBottomBorder;
1909 mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1910 if ( nLeftBorder || nTopBorder || nRightBorder || nBottomBorder )
1911 {
1912 tools::Rectangle aWinRect( Point( 0, 0 ), GetOutputSizePixel() );
1913 vcl::Region aRegion( aWinRect );
1914 aWinRect.AdjustLeft(nLeftBorder );
1915 aWinRect.AdjustTop(nTopBorder );
1916 aWinRect.AdjustRight( -nRightBorder );
1917 aWinRect.AdjustBottom( -nBottomBorder );
1918 // no output area anymore, now invalidate all
1919 if ( (aWinRect.Right() < aWinRect.Left()) ||
1920 (aWinRect.Bottom() < aWinRect.Top()) )
1921 Invalidate( InvalidateFlags::NoChildren );
1922 else
1923 {
1924 aRegion.Exclude( aWinRect );
1925 Invalidate( aRegion, InvalidateFlags::NoChildren );
1926 }
1927 }
1928 }
1929 }
1930
SetDisplayActive(bool bActive)1931 void ImplBorderWindow::SetDisplayActive( bool bActive )
1932 {
1933 if ( mbDisplayActive != bActive )
1934 {
1935 mbDisplayActive = bActive;
1936 if ( mbFrameBorder )
1937 InvalidateBorder();
1938 }
1939 }
1940
SetTitleType(BorderWindowTitleType nTitleType,const Size & rSize)1941 void ImplBorderWindow::SetTitleType( BorderWindowTitleType nTitleType, const Size& rSize )
1942 {
1943 mnTitleType = nTitleType;
1944 UpdateView( false, rSize );
1945 }
1946
SetBorderStyle(WindowBorderStyle nStyle)1947 void ImplBorderWindow::SetBorderStyle( WindowBorderStyle nStyle )
1948 {
1949 if ( !mbFrameBorder && (mnBorderStyle != nStyle) )
1950 {
1951 mnBorderStyle = nStyle;
1952 UpdateView( false, ImplGetWindow()->GetOutputSizePixel() );
1953 }
1954 }
1955
SetRollUp(bool bRollUp,const Size & rSize)1956 void ImplBorderWindow::SetRollUp( bool bRollUp, const Size& rSize )
1957 {
1958 mbRollUp = bRollUp;
1959 UpdateView( false, rSize );
1960 }
1961
SetCloseButton()1962 void ImplBorderWindow::SetCloseButton()
1963 {
1964 SetStyle( GetStyle() | WB_CLOSEABLE );
1965 Size aSize = GetOutputSizePixel();
1966 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1967 InvalidateBorder();
1968 }
1969
SetDockButton(bool bDockButton)1970 void ImplBorderWindow::SetDockButton( bool bDockButton )
1971 {
1972 mbDockBtn = bDockButton;
1973 Size aSize = GetOutputSizePixel();
1974 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1975 InvalidateBorder();
1976 }
1977
SetHideButton(bool bHideButton)1978 void ImplBorderWindow::SetHideButton( bool bHideButton )
1979 {
1980 mbHideBtn = bHideButton;
1981 Size aSize = GetOutputSizePixel();
1982 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1983 InvalidateBorder();
1984 }
1985
SetMenuButton(bool bMenuButton)1986 void ImplBorderWindow::SetMenuButton( bool bMenuButton )
1987 {
1988 mbMenuBtn = bMenuButton;
1989 Size aSize = GetOutputSizePixel();
1990 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1991 InvalidateBorder();
1992 }
1993
UpdateMenuHeight()1994 void ImplBorderWindow::UpdateMenuHeight()
1995 {
1996 Resize();
1997 }
1998
SetMenuBarWindow(vcl::Window * pWindow)1999 void ImplBorderWindow::SetMenuBarWindow( vcl::Window* pWindow )
2000 {
2001 mpMenuBarWindow = pWindow;
2002 UpdateMenuHeight();
2003 if ( pWindow )
2004 pWindow->Show();
2005 }
2006
SetMenuBarMode(bool bHide)2007 void ImplBorderWindow::SetMenuBarMode( bool bHide )
2008 {
2009 mbMenuHide = bHide;
2010 UpdateMenuHeight();
2011 }
2012
SetNotebookBar(const OUString & rUIXMLDescription,const css::uno::Reference<css::frame::XFrame> & rFrame,const NotebookBarAddonsItem & aNotebookBarAddonsItem)2013 void ImplBorderWindow::SetNotebookBar(const OUString& rUIXMLDescription,
2014 const css::uno::Reference<css::frame::XFrame>& rFrame,
2015 const NotebookBarAddonsItem& aNotebookBarAddonsItem)
2016 {
2017 if (mpNotebookBar)
2018 mpNotebookBar.disposeAndClear();
2019 mpNotebookBar = VclPtr<NotebookBar>::Create(this, "NotebookBar", rUIXMLDescription, rFrame,
2020 aNotebookBarAddonsItem);
2021 Resize();
2022 }
2023
CloseNotebookBar()2024 void ImplBorderWindow::CloseNotebookBar()
2025 {
2026 if (mpNotebookBar)
2027 mpNotebookBar.disposeAndClear();
2028 mpNotebookBar = nullptr;
2029 Resize();
2030 }
2031
GetBorder(sal_Int32 & rLeftBorder,sal_Int32 & rTopBorder,sal_Int32 & rRightBorder,sal_Int32 & rBottomBorder) const2032 void ImplBorderWindow::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
2033 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
2034 {
2035 mpBorderView->GetBorder(rLeftBorder, rTopBorder, rRightBorder, rBottomBorder);
2036
2037 if (mpMenuBarWindow && !mbMenuHide)
2038 rTopBorder += mpMenuBarWindow->GetSizePixel().Height();
2039
2040 if (mpNotebookBar && mpNotebookBar->IsVisible())
2041 rTopBorder += mpNotebookBar->GetSizePixel().Height();
2042 }
2043
CalcTitleWidth() const2044 long ImplBorderWindow::CalcTitleWidth() const
2045 {
2046 return mpBorderView->CalcTitleWidth();
2047 }
2048
GetMenuRect() const2049 tools::Rectangle ImplBorderWindow::GetMenuRect() const
2050 {
2051 return mpBorderView->GetMenuRect();
2052 }
2053
GetOptimalSize() const2054 Size ImplBorderWindow::GetOptimalSize() const
2055 {
2056 const vcl::Window* pClientWindow = ImplGetClientWindow();
2057 if (pClientWindow)
2058 return pClientWindow->GetOptimalSize();
2059 return Size(mnMinWidth, mnMinHeight);
2060 }
2061
queue_resize(StateChangedType eReason)2062 void ImplBorderWindow::queue_resize(StateChangedType eReason)
2063 {
2064 //if we are floating, then we don't want to inform our parent that it needs
2065 //to calculate a new layout allocation. Because while we are a child
2066 //of our parent we are not embedded into the parent so it doesn't care
2067 //about us.
2068 if (mbFloatWindow)
2069 return;
2070 vcl::Window::queue_resize(eReason);
2071 }
2072
2073 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2074