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 <uielement/dropdownboxtoolbarcontroller.hxx>
21 
22 #include <com/sun/star/util/XURLTransformer.hpp>
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 
25 #include <svtools/toolboxcontroller.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/mnemonic.hxx>
28 #include <vcl/lstbox.hxx>
29 #include <vcl/toolbox.hxx>
30 
31 using namespace ::com::sun::star;
32 using namespace css::awt;
33 using namespace css::uno;
34 using namespace css::beans;
35 using namespace css::lang;
36 using namespace css::frame;
37 using namespace css::util;
38 
39 namespace framework
40 {
41 
42 // Wrapper class to notify controller about events from ListBox.
43 // Unfortunaltly the events are notified through virtual methods instead
44 // of Listeners.
45 
46 class ListBoxControl : public ListBox
47 {
48     public:
49         ListBoxControl( vcl::Window* pParent, WinBits nStyle, DropdownToolbarController* pListBoxListener );
50         virtual ~ListBoxControl() override;
51         virtual void dispose() override;
52 
53         virtual void Select() override;
54         virtual void GetFocus() override;
55         virtual void LoseFocus() override;
56         virtual bool PreNotify( NotifyEvent& rNEvt ) override;
57 
58     private:
59         DropdownToolbarController* m_pListBoxListener;
60 };
61 
ListBoxControl(vcl::Window * pParent,WinBits nStyle,DropdownToolbarController * pListBoxListener)62 ListBoxControl::ListBoxControl( vcl::Window* pParent, WinBits nStyle, DropdownToolbarController* pListBoxListener ) :
63     ListBox( pParent, nStyle )
64     , m_pListBoxListener( pListBoxListener )
65 {
66 }
67 
~ListBoxControl()68 ListBoxControl::~ListBoxControl()
69 {
70     disposeOnce();
71 }
72 
dispose()73 void ListBoxControl::dispose()
74 {
75     m_pListBoxListener = nullptr;
76     ListBox::dispose();
77 }
78 
Select()79 void ListBoxControl::Select()
80 {
81     ListBox::Select();
82     if ( m_pListBoxListener )
83         m_pListBoxListener->Select();
84 }
85 
GetFocus()86 void ListBoxControl::GetFocus()
87 {
88     ListBox::GetFocus();
89     if ( m_pListBoxListener )
90         m_pListBoxListener->GetFocus();
91 }
92 
LoseFocus()93 void ListBoxControl::LoseFocus()
94 {
95     ListBox::LoseFocus();
96     if ( m_pListBoxListener )
97         m_pListBoxListener->LoseFocus();
98 }
99 
PreNotify(NotifyEvent & rNEvt)100 bool ListBoxControl::PreNotify( NotifyEvent& rNEvt )
101 {
102     bool bRet = false;
103     if ( m_pListBoxListener )
104         bRet = false;
105     if ( !bRet )
106         bRet = ListBox::PreNotify( rNEvt );
107 
108     return bRet;
109 }
110 
DropdownToolbarController(const Reference<XComponentContext> & rxContext,const Reference<XFrame> & rFrame,ToolBox * pToolbar,sal_uInt16 nID,sal_Int32 nWidth,const OUString & aCommand)111 DropdownToolbarController::DropdownToolbarController(
112     const Reference< XComponentContext >&    rxContext,
113     const Reference< XFrame >&               rFrame,
114     ToolBox*                                 pToolbar,
115     sal_uInt16                                   nID,
116     sal_Int32                                nWidth,
117     const OUString&                          aCommand ) :
118     ComplexToolbarController( rxContext, rFrame, pToolbar, nID, aCommand )
119     ,   m_pListBoxControl( nullptr )
120 {
121     m_pListBoxControl = VclPtr<ListBoxControl>::Create( m_pToolbar, WB_DROPDOWN|WB_AUTOHSCROLL|WB_BORDER, this );
122     if ( nWidth == 0 )
123         nWidth = 100;
124 
125     // default dropdown size
126     ::Size aLogicalSize( 0, 160 );
127     ::Size aPixelSize = m_pListBoxControl->LogicToPixel(aLogicalSize, MapMode(MapUnit::MapAppFont));
128 
129     m_pListBoxControl->SetSizePixel( ::Size( nWidth, aPixelSize.Height() ));
130     m_pToolbar->SetItemWindow( m_nID, m_pListBoxControl );
131     m_pListBoxControl->SetDropDownLineCount( 5 );
132 }
133 
~DropdownToolbarController()134 DropdownToolbarController::~DropdownToolbarController()
135 {
136 }
137 
dispose()138 void SAL_CALL DropdownToolbarController::dispose()
139 {
140     SolarMutexGuard aSolarMutexGuard;
141 
142     m_pToolbar->SetItemWindow( m_nID, nullptr );
143     m_pListBoxControl.disposeAndClear();
144 
145     ComplexToolbarController::dispose();
146 }
147 
getExecuteArgs(sal_Int16 KeyModifier) const148 Sequence<PropertyValue> DropdownToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const
149 {
150     Sequence<PropertyValue> aArgs( 2 );
151     OUString aSelectedText = m_pListBoxControl->GetSelectedEntry();
152 
153     // Add key modifier to argument list
154     aArgs[0].Name = "KeyModifier";
155     aArgs[0].Value <<= KeyModifier;
156     aArgs[1].Name = "Text";
157     aArgs[1].Value <<= aSelectedText;
158     return aArgs;
159 }
160 
Select()161 void DropdownToolbarController::Select()
162 {
163     if ( m_pListBoxControl->GetEntryCount() > 0 )
164     {
165         vcl::Window::PointerState aState = m_pListBoxControl->GetPointerState();
166 
167         sal_uInt16 nKeyModifier = sal_uInt16( aState.mnState & KEY_MODIFIERS_MASK );
168         execute( nKeyModifier );
169     }
170 }
171 
GetFocus()172 void DropdownToolbarController::GetFocus()
173 {
174     notifyFocusGet();
175 }
176 
LoseFocus()177 void DropdownToolbarController::LoseFocus()
178 {
179     notifyFocusLost();
180 }
181 
executeControlCommand(const css::frame::ControlCommand & rControlCommand)182 void DropdownToolbarController::executeControlCommand( const css::frame::ControlCommand& rControlCommand )
183 {
184     if ( rControlCommand.Command == "SetList" )
185     {
186         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
187         {
188             if ( rControlCommand.Arguments[i].Name == "List" )
189             {
190                 Sequence< OUString > aList;
191                 m_pListBoxControl->Clear();
192 
193                 rControlCommand.Arguments[i].Value >>= aList;
194                 for ( sal_Int32 j = 0; j < aList.getLength(); j++ )
195                     m_pListBoxControl->InsertEntry( aList[j] );
196 
197                 m_pListBoxControl->SelectEntryPos( 0 );
198 
199                 // send notification
200                 uno::Sequence< beans::NamedValue > aInfo { { "List", css::uno::makeAny(aList) } };
201                 addNotifyInfo( "ListChanged",
202                                getDispatchFromCommand( m_aCommandURL ),
203                                aInfo );
204 
205                 break;
206             }
207         }
208     }
209     else if ( rControlCommand.Command == "AddEntry" )
210     {
211         OUString   aText;
212         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
213         {
214             if ( rControlCommand.Arguments[i].Name == "Text" )
215             {
216                 if ( rControlCommand.Arguments[i].Value >>= aText )
217                     m_pListBoxControl->InsertEntry( aText, LISTBOX_APPEND );
218                 break;
219             }
220         }
221     }
222     else if ( rControlCommand.Command == "InsertEntry" )
223     {
224         sal_Int32      nPos( LISTBOX_APPEND );
225         OUString   aText;
226         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
227         {
228             if ( rControlCommand.Arguments[i].Name == "Pos" )
229             {
230                 sal_Int32 nTmpPos = 0;
231                 if ( rControlCommand.Arguments[i].Value >>= nTmpPos )
232                 {
233                     if (( nTmpPos >= 0 ) &&
234                         ( nTmpPos < m_pListBoxControl->GetEntryCount() ))
235                         nPos = nTmpPos;
236                 }
237             }
238             else if ( rControlCommand.Arguments[i].Name == "Text" )
239                 rControlCommand.Arguments[i].Value >>= aText;
240         }
241 
242         m_pListBoxControl->InsertEntry( aText, nPos );
243     }
244     else if ( rControlCommand.Command == "RemoveEntryPos" )
245     {
246         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
247         {
248             if ( rControlCommand.Arguments[i].Name == "Pos" )
249             {
250                 sal_Int32 nPos( -1 );
251                 if ( rControlCommand.Arguments[i].Value >>= nPos )
252                 {
253                     if ( 0 <= nPos && nPos < m_pListBoxControl->GetEntryCount() )
254                         m_pListBoxControl->RemoveEntry( nPos );
255                 }
256                 break;
257             }
258         }
259     }
260     else if ( rControlCommand.Command == "RemoveEntryText" )
261     {
262         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
263         {
264             if ( rControlCommand.Arguments[i].Name == "Text" )
265             {
266                 OUString aText;
267                 if ( rControlCommand.Arguments[i].Value >>= aText )
268                     m_pListBoxControl->RemoveEntry( aText );
269                 break;
270             }
271         }
272     }
273     else if ( rControlCommand.Command == "SetDropDownLines" )
274     {
275         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
276         {
277             if ( rControlCommand.Arguments[i].Name == "Lines" )
278             {
279                 sal_Int32 nValue( 5 );
280                 rControlCommand.Arguments[i].Value >>= nValue;
281                 m_pListBoxControl->SetDropDownLineCount( sal_uInt16( nValue ));
282                 break;
283             }
284         }
285     }
286 }
287 
288 } // namespace
289 
290 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
291