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