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 <brwview.hxx>
21 #include <sbagrid.hxx>
22 #include <toolkit/helper/vclunohelper.hxx>
23 #include <comphelper/types.hxx>
24 #include <vcl/split.hxx>
25 #include <strings.hxx>
26 #include <com/sun/star/form/XLoadable.hpp>
27 #include <com/sun/star/awt/XControlContainer.hpp>
28 #include <com/sun/star/awt/PosSize.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/container/XChild.hpp>
31 #include <osl/diagnose.h>
32
33 using namespace dbaui;
34 using namespace ::com::sun::star::uno;
35 using namespace ::com::sun::star::sdb;
36 using namespace ::com::sun::star::form;
37 using namespace ::com::sun::star::beans;
38 using namespace ::com::sun::star::container;
39 using namespace ::com::sun::star::lang;
40
41 namespace
42 {
isGrabVclControlFocusAllowed(const UnoDataBrowserView * _pView)43 bool isGrabVclControlFocusAllowed(const UnoDataBrowserView* _pView)
44 {
45 bool bGrabFocus = false;
46 SbaGridControl* pVclControl = _pView->getVclControl();
47 const Reference< css::awt::XControl >& xGrid = _pView->getGridControl();
48 if (pVclControl && xGrid.is())
49 {
50 bGrabFocus = true;
51 if(!pVclControl->HasChildPathFocus())
52 {
53 Reference<XChild> xChild(xGrid->getModel(),UNO_QUERY);
54 Reference<XLoadable> xLoad;
55 if(xChild.is())
56 xLoad.set(xChild->getParent(),UNO_QUERY);
57 bGrabFocus = xLoad.is() && xLoad->isLoaded();
58 }
59 }
60 return bGrabFocus;
61 }
62 }
63
64 // UnoDataBrowserView
65
UnoDataBrowserView(vcl::Window * pParent,IController & _rController,const Reference<css::uno::XComponentContext> & _rxContext)66 UnoDataBrowserView::UnoDataBrowserView( vcl::Window* pParent,
67 IController& _rController,
68 const Reference< css::uno::XComponentContext >& _rxContext)
69 :ODataView(pParent,_rController,_rxContext)
70 ,m_pTreeView(nullptr)
71 ,m_pSplitter(nullptr)
72 ,m_pVclControl(nullptr)
73 {
74
75 }
76
Construct(const Reference<css::awt::XControlModel> & xModel)77 void UnoDataBrowserView::Construct(const Reference< css::awt::XControlModel >& xModel)
78 {
79 try
80 {
81 ODataView::Construct();
82
83 // our UNO representation
84 m_xMe = VCLUnoHelper::CreateControlContainer(this);
85
86 // create the (UNO-) control
87 m_xGrid = new SbaXGridControl( getORB() );
88 OSL_ENSURE(m_xGrid.is(), "UnoDataBrowserView::Construct : could not create a grid control !");
89 // in design mode (for the moment)
90 m_xGrid->setDesignMode(true);
91
92 Reference< css::awt::XWindow > xGridWindow(m_xGrid, UNO_QUERY);
93 xGridWindow->setVisible(true);
94 xGridWindow->setEnable(true);
95
96 // introduce the model to the grid
97 m_xGrid->setModel(xModel);
98 // introduce the container (me) to the grid
99 Reference< css::beans::XPropertySet > xModelSet(xModel, UNO_QUERY);
100 getContainer()->addControl(::comphelper::getString(xModelSet->getPropertyValue(PROPERTY_NAME)), m_xGrid);
101
102 // get the VCL-control
103 m_pVclControl = nullptr;
104 getVclControl();
105
106 OSL_ENSURE(m_pVclControl != nullptr, "UnoDataBrowserView::Construct : no real grid control !");
107 }
108 catch(const Exception&)
109 {
110 ::comphelper::disposeComponent(m_xGrid);
111 throw;
112 }
113 }
114
~UnoDataBrowserView()115 UnoDataBrowserView::~UnoDataBrowserView()
116 {
117 disposeOnce();
118 }
119
dispose()120 void UnoDataBrowserView::dispose()
121 {
122 m_pSplitter.disposeAndClear();
123 setTreeView(nullptr);
124
125 try
126 {
127 ::comphelper::disposeComponent(m_xGrid);
128 ::comphelper::disposeComponent(m_xMe);
129 }
130 catch(const Exception&)
131 {}
132 m_pTreeView.clear();
133 m_pVclControl.clear();
134 ODataView::dispose();
135 }
136
IMPL_LINK_NOARG(UnoDataBrowserView,SplitHdl,Splitter *,void)137 IMPL_LINK_NOARG( UnoDataBrowserView, SplitHdl, Splitter*, void )
138 {
139 tools::Long nYPos = m_pSplitter->GetPosPixel().Y();
140 m_pSplitter->SetPosPixel( Point( m_pSplitter->GetSplitPosPixel(), nYPos ) );
141 Resize();
142 }
143
setSplitter(Splitter * _pSplitter)144 void UnoDataBrowserView::setSplitter(Splitter* _pSplitter)
145 {
146 m_pSplitter = _pSplitter;
147 m_pSplitter->SetSplitHdl( LINK( this, UnoDataBrowserView, SplitHdl ) );
148 LINK( this, UnoDataBrowserView, SplitHdl ).Call(m_pSplitter);
149 }
150
setTreeView(InterimDBTreeListBox * pTreeView)151 void UnoDataBrowserView::setTreeView(InterimDBTreeListBox* pTreeView)
152 {
153 if (m_pTreeView.get() != pTreeView)
154 {
155 m_pTreeView.disposeAndClear();
156 m_pTreeView = pTreeView;
157 }
158 }
159
showStatus(const OUString & _rStatus)160 void UnoDataBrowserView::showStatus( const OUString& _rStatus )
161 {
162 if (_rStatus.isEmpty())
163 hideStatus();
164 else
165 {
166 if (!m_pTreeView)
167 return;
168 weld::Label& rLabel = m_pTreeView->GetStatusBar();
169 rLabel.set_label(_rStatus);
170 rLabel.show();
171 Resize();
172 PaintImmediately();
173 }
174 }
175
hideStatus()176 void UnoDataBrowserView::hideStatus()
177 {
178 if (!m_pTreeView)
179 return;
180 weld::Label& rLabel = m_pTreeView->GetStatusBar();
181 if (!rLabel.get_visible())
182 {
183 // nothing to do
184 return;
185 }
186 rLabel.hide();
187 Resize();
188 PaintImmediately();
189 }
190
resizeDocumentView(tools::Rectangle & _rPlayground)191 void UnoDataBrowserView::resizeDocumentView(tools::Rectangle& _rPlayground)
192 {
193 Point aSplitPos;
194 Size aSplitSize;
195 Point aPlaygroundPos( _rPlayground.TopLeft() );
196 Size aPlaygroundSize( _rPlayground.GetSize() );
197
198 if (m_pTreeView && m_pTreeView->IsVisible() && m_pSplitter)
199 {
200 // calculate the splitter pos and size
201 aSplitPos = m_pSplitter->GetPosPixel();
202 aSplitPos.setY( aPlaygroundPos.Y() );
203 aSplitSize = m_pSplitter->GetOutputSizePixel();
204 aSplitSize.setHeight( aPlaygroundSize.Height() );
205
206 if( ( aSplitPos.X() + aSplitSize.Width() ) > ( aPlaygroundSize.Width() ))
207 aSplitPos.setX( aPlaygroundSize.Width() - aSplitSize.Width() );
208
209 if( aSplitPos.X() <= aPlaygroundPos.X() )
210 aSplitPos.setX( aPlaygroundPos.X() + sal_Int32(aPlaygroundSize.Width() * 0.2) );
211
212 // the tree pos and size
213 Point aTreeViewPos( aPlaygroundPos );
214 Size aTreeViewSize( aSplitPos.X(), aPlaygroundSize.Height() );
215
216 // set the size of treelistbox
217 m_pTreeView->SetPosSizePixel( aTreeViewPos, aTreeViewSize );
218 // Call this to trigger InterimItemWindow::Layout immediately, and
219 // not later on idle so the statusbar will be shown to explain
220 // a long delay on opening databases
221 m_pTreeView->Resize();
222
223 //set the size of the splitter
224 m_pSplitter->SetPosSizePixel( aSplitPos, Size( aSplitSize.Width(), aPlaygroundSize.Height() ) );
225 m_pSplitter->SetDragRectPixel( _rPlayground );
226 }
227
228 // set the size of grid control
229 Reference< css::awt::XWindow > xGridAsWindow(m_xGrid, UNO_QUERY);
230 if (xGridAsWindow.is())
231 xGridAsWindow->setPosSize( aSplitPos.X() + aSplitSize.Width(), aPlaygroundPos.Y(),
232 aPlaygroundSize.Width() - aSplitSize.Width() - aSplitPos.X(), aPlaygroundSize.Height(), css::awt::PosSize::POSSIZE);
233
234 // just for completeness: there is no space left, we occupied it all ...
235 _rPlayground.SetPos( _rPlayground.BottomRight() );
236 _rPlayground.SetSize( Size( 0, 0 ) );
237 }
238
View2ModelPos(sal_uInt16 nPos) const239 sal_uInt16 UnoDataBrowserView::View2ModelPos(sal_uInt16 nPos) const
240 {
241 return m_pVclControl ? m_pVclControl->GetModelColumnPos(m_pVclControl->GetColumnIdFromViewPos(nPos)) : -1;
242 }
243
getVclControl() const244 SbaGridControl* UnoDataBrowserView::getVclControl() const
245 {
246 if ( !m_pVclControl )
247 {
248 OSL_ENSURE(m_xGrid.is(),"Grid not set!");
249 if ( m_xGrid.is() )
250 {
251 Reference< css::awt::XWindowPeer > xPeer = m_xGrid->getPeer();
252 if ( xPeer.is() )
253 {
254 SbaXGridPeer* pPeer = comphelper::getUnoTunnelImplementation<SbaXGridPeer>(xPeer);
255 UnoDataBrowserView* pTHIS = const_cast<UnoDataBrowserView*>(this);
256 if ( pPeer )
257 {
258 m_pVclControl = static_cast<SbaGridControl*>(pPeer->GetWindow());
259 pTHIS->startComponentListening(VCLUnoHelper::GetInterface(m_pVclControl));
260 }
261 }
262 }
263 }
264 return m_pVclControl;
265 }
266
GetFocus()267 void UnoDataBrowserView::GetFocus()
268 {
269 ODataView::GetFocus();
270 if( m_pTreeView && m_pTreeView->IsVisible() && !m_pTreeView->HasChildPathFocus())
271 m_pTreeView->GrabFocus();
272 else if (m_pVclControl && m_xGrid.is())
273 {
274 bool bGrabFocus = false;
275 if(!m_pVclControl->HasChildPathFocus())
276 {
277 bGrabFocus = isGrabVclControlFocusAllowed(this);
278 if( bGrabFocus )
279 m_pVclControl->GrabFocus();
280 }
281 if(!bGrabFocus && m_pTreeView && m_pTreeView->IsVisible() )
282 m_pTreeView->GrabFocus();
283 }
284 }
285
_disposing(const css::lang::EventObject &)286 void UnoDataBrowserView::_disposing( const css::lang::EventObject& /*_rSource*/ )
287 {
288 stopComponentListening(VCLUnoHelper::GetInterface(m_pVclControl));
289 m_pVclControl = nullptr;
290 }
291
PreNotify(NotifyEvent & rNEvt)292 bool UnoDataBrowserView::PreNotify( NotifyEvent& rNEvt )
293 {
294 bool bDone = false;
295 if(rNEvt.GetType() == MouseNotifyEvent::KEYINPUT)
296 {
297 bool bGrabAllowed = isGrabVclControlFocusAllowed(this);
298 if ( bGrabAllowed )
299 {
300 const KeyEvent* pKeyEvt = rNEvt.GetKeyEvent();
301 const vcl::KeyCode& rKeyCode = pKeyEvt->GetKeyCode();
302 if ( ( rKeyCode == vcl::KeyCode( KEY_E, true, true, false, false ) )
303 || ( rKeyCode == vcl::KeyCode( KEY_TAB, true, false, false, false ) )
304 )
305 {
306 if ( m_pTreeView && m_pVclControl && m_pTreeView->HasChildPathFocus() )
307 m_pVclControl->GrabFocus();
308 else if ( m_pTreeView && m_pVclControl && m_pVclControl->HasChildPathFocus() )
309 m_pTreeView->GrabFocus();
310
311 bDone = true;
312 }
313 }
314 }
315 return bDone || ODataView::PreNotify(rNEvt);
316 }
317
BrowserViewStatusDisplay(UnoDataBrowserView * _pView,const OUString & _rStatus)318 BrowserViewStatusDisplay::BrowserViewStatusDisplay( UnoDataBrowserView* _pView, const OUString& _rStatus )
319 :m_pView(_pView)
320 {
321
322 if (m_pView)
323 m_pView->showStatus(_rStatus);
324 }
325
~BrowserViewStatusDisplay()326 BrowserViewStatusDisplay::~BrowserViewStatusDisplay( )
327 {
328 if (m_pView)
329 m_pView->showStatus(OUString());
330
331 }
332
333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
334