1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_framework.hxx"
24 
25 #include <uielement/statusbarmerger.hxx>
26 
27 using rtl::OUString;
28 using com::sun::star::frame::XFrame;
29 using com::sun::star::uno::Reference;
30 using com::sun::star::beans::PropertyValue;
31 using com::sun::star::uno::Sequence;
32 
33 namespace framework
34 {
35 namespace {
36 
37 static const char MERGE_STATUSBAR_URL[]         = "URL";
38 static const char MERGE_STATUSBAR_TITLE[]       = "Title";
39 static const char MERGE_STATUSBAR_CONTEXT[]     = "Context";
40 static const char MERGE_STATUSBAR_ALIGN[]       = "Alignment";
41 static const char MERGE_STATUSBAR_AUTOSIZE[]    = "AutoSize";
42 static const char MERGE_STATUSBAR_OWNERDRAW[]   = "OwnerDraw";
43 static const char MERGE_STATUSBAR_WIDTH[]       = "Width";
44 
45 static const char STATUSBAR_ALIGN_LEFT[]        = "left";
46 static const char STATUSBAR_ALIGN_CENTER[]      = "center";
47 static const char STATUSBAR_ALIGN_RIGHT[]       = "right";
48 
49 static const char MERGECOMMAND_ADDAFTER[]       = "AddAfter";
50 static const char MERGECOMMAND_ADDBEFORE[]      = "AddBefore";
51 static const char MERGECOMMAND_REPLACE[]        = "Replace";
52 static const char MERGECOMMAND_REMOVE[]         = "Remove";
53 
54 static const char MERGEFALLBACK_ADDLAST[]       = "AddLast";
55 static const char MERGEFALLBACK_ADDFIRST[]      = "AddFirst";
56 static const char MERGEFALLBACK_IGNORE[]        = "Ignore";
57 
58 
59 static void lcl_ConvertSequenceToValues(
60     const Sequence< PropertyValue > &rSequence,
61     AddonStatusbarItem &rItem )
62 {
63     OUString sAlignment;
64     sal_Bool bAutoSize = sal_False;
65     sal_Bool bOwnerDraw = sal_False;
66 
67     PropertyValue aPropVal;
68     for ( sal_Int32 i = 0; i < rSequence.getLength(); i++ )
69     {
70         aPropVal = rSequence[i];
71         if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_URL ) ) )
72             aPropVal.Value >>= rItem.aCommandURL;
73         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_TITLE ) ) )
74             aPropVal.Value >>= rItem.aLabel;
75         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_CONTEXT ) ) )
76             aPropVal.Value >>= rItem.aContext;
77         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_ALIGN ) ) )
78             aPropVal.Value >>= sAlignment;
79         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_AUTOSIZE ) ) )
80             aPropVal.Value >>= bAutoSize;
81         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_OWNERDRAW ) ) )
82             aPropVal.Value >>= bOwnerDraw;
83         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_WIDTH ) ) )
84         {
85             sal_Int32 aWidth = 0;
86             aPropVal.Value >>= aWidth;
87             rItem.nWidth = sal_uInt16( aWidth );
88         }
89     }
90 
91     sal_uInt16 nItemBits(0);
92     if ( bAutoSize )
93         nItemBits |= SIB_AUTOSIZE;
94     if ( bOwnerDraw )
95         nItemBits |= SIB_USERDRAW;
96     if ( sAlignment.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STATUSBAR_ALIGN_CENTER )))
97         nItemBits |= SIB_CENTER;
98     else if ( sAlignment.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STATUSBAR_ALIGN_RIGHT )))
99         nItemBits |= SIB_RIGHT;
100     else
101         // if unset, defaults to left alignment
102         nItemBits |= SIB_LEFT;
103     rItem.nItemBits = nItemBits;
104 }
105 
106 static void lcl_CreateStatusbarItem( StatusBar* pStatusbar,
107                                      sal_uInt16 nPos,
108                                      sal_uInt16 nItemId,
109                                      const AddonStatusbarItem& rAddonItem )
110 {
111     pStatusbar->InsertItem( nItemId,
112                             rAddonItem.nWidth,
113                             rAddonItem.nItemBits,
114                             STATUSBAR_OFFSET,
115                             nPos );
116     pStatusbar->SetItemCommand( nItemId, rAddonItem.aCommandURL );
117     pStatusbar->SetQuickHelpText( nItemId, rAddonItem.aLabel );
118     pStatusbar->SetAccessibleName( nItemId, rAddonItem.aLabel );
119 
120     // add-on specific data
121     AddonStatusbarItemData *pUserData = new AddonStatusbarItemData;
122     pUserData->aLabel = rAddonItem.aLabel;
123     pUserData->nItemBits = rAddonItem.nItemBits;
124     pStatusbar->SetItemData( nItemId, pUserData );
125 }
126 
127 static bool lcl_MergeItems( StatusBar* pStatusbar,
128                             sal_uInt16 nPos,
129                             sal_uInt16 nModIndex,
130                             sal_uInt16& rItemId,
131                             const ::rtl::OUString& rModuleIdentifier,
132                             const AddonStatusbarItemContainer& rAddonItems )
133 {
134     OSL_ENSURE(rAddonItems.size() <= 0xffff, "Caution: Not all items get handled (!)");
135     const sal_uInt16 nSize( static_cast< sal_uInt16 >(rAddonItems.size()) );
136     for ( sal_Int32 i = 0; i < nSize; i++ )
137     {
138         const AddonStatusbarItem& rItem = rAddonItems[i];
139         if ( !StatusbarMerger::IsCorrectContext( rItem.aContext, rModuleIdentifier ) )
140             continue;
141 
142         sal_uInt16 nInsPos = nPos + nModIndex + i;
143         if ( nInsPos > pStatusbar->GetItemCount() )
144             nInsPos = STATUSBAR_APPEND;
145 
146         lcl_CreateStatusbarItem( pStatusbar, nInsPos, rItemId, rItem );
147         ++rItemId;
148     }
149 
150     return true;
151 }
152 
153 static bool lcl_ReplaceItem( StatusBar* pStatusbar,
154                              sal_uInt16 nPos,
155                              sal_uInt16& rItemId,
156                             const ::rtl::OUString& rModuleIdentifier,
157                              const AddonStatusbarItemContainer& rAddonToolbarItems )
158 {
159     pStatusbar->RemoveItem( pStatusbar->GetItemId( nPos ) );
160     return lcl_MergeItems( pStatusbar, nPos, 0, rItemId, rModuleIdentifier, rAddonToolbarItems );
161 }
162 
163 static bool lcl_RemoveItems( StatusBar* pStatusbar,
164                              sal_uInt16 nPos,
165                              const ::rtl::OUString& rMergeCommandParameter )
166 {
167     sal_Int32 nCount = rMergeCommandParameter.toInt32();
168     if ( nCount > 0 )
169     {
170         for ( sal_Int32 i = 0; i < nCount; i++ )
171         {
172             if ( nPos < pStatusbar->GetItemCount() )
173                 pStatusbar->RemoveItem( nPos );
174         }
175     }
176     return true;
177 }
178 
179 /*
180 static ::cppu::OWeakObject* CreateController(
181     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMGR,
182     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame,
183     StatusBar* pStatusbar,
184     const ::rtl::OUString& rCommandURL,
185     sal_uInt16 nId,
186     sal_uInt16 nWidth,
187     const ::rtl::OUString& rControlType );
188 
189 */
190 }
191 
192 bool StatusbarMerger::IsCorrectContext(
193     const OUString& rContext,
194     const OUString& rModuleIdentifier )
195 {
196     return (( rContext.getLength() == 0 ) || ( rContext.indexOf( rModuleIdentifier ) >= 0 ));
197 }
198 
199 bool StatusbarMerger::ConvertSeqSeqToVector(
200     const Sequence< Sequence< PropertyValue > > &rSequence,
201     AddonStatusbarItemContainer& rContainer )
202 {
203     for ( sal_Int32 i = 0; i < rSequence.getLength(); i++ )
204     {
205         AddonStatusbarItem aStatusBarItem;
206         lcl_ConvertSequenceToValues( rSequence[i], aStatusBarItem );
207         rContainer.push_back( aStatusBarItem );
208     }
209 
210     return true;
211 }
212 
213 sal_uInt16 StatusbarMerger::FindReferencePos(
214     StatusBar* pStatusbar,
215     const OUString& rReferencePoint )
216 {
217     for ( sal_uInt16 nPos = 0; nPos < pStatusbar->GetItemCount(); nPos++ )
218     {
219         const ::rtl::OUString rCmd = pStatusbar->GetItemCommand( pStatusbar->GetItemId( nPos ) );
220         if ( rReferencePoint == rCmd )
221             return nPos;
222     }
223 
224     return STATUSBAR_ITEM_NOTFOUND;
225 }
226 
227 bool StatusbarMerger::ProcessMergeOperation(
228     StatusBar* pStatusbar,
229     sal_uInt16 nPos,
230     sal_uInt16& rItemId,
231     const ::rtl::OUString& rModuleIdentifier,
232     const ::rtl::OUString& rMergeCommand,
233     const ::rtl::OUString& rMergeCommandParameter,
234     const AddonStatusbarItemContainer& rItems )
235 {
236     if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDAFTER ) ) )
237         return lcl_MergeItems( pStatusbar, nPos, 1, rItemId, rModuleIdentifier, rItems );
238     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDBEFORE ) ) )
239         return lcl_MergeItems( pStatusbar, nPos, 0, rItemId, rModuleIdentifier, rItems );
240     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_REPLACE ) ) )
241         return lcl_ReplaceItem( pStatusbar, nPos, rItemId, rModuleIdentifier, rItems );
242     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_REMOVE ) ) )
243         return lcl_RemoveItems( pStatusbar, nPos, rMergeCommandParameter );
244 
245     return false;
246 }
247 
248 bool StatusbarMerger::ProcessMergeFallback(
249     StatusBar* pStatusbar,
250     sal_uInt16 /*nPos*/,
251     sal_uInt16& rItemId,
252     const ::rtl::OUString& rModuleIdentifier,
253     const ::rtl::OUString& rMergeCommand,
254     const ::rtl::OUString& rMergeFallback,
255     const AddonStatusbarItemContainer& rItems )
256 {
257     // fallback IGNORE or REPLACE/REMOVE item not found
258     if (( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_IGNORE ))) ||
259             ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(  MERGECOMMAND_REPLACE ))) ||
260             ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(  MERGECOMMAND_REMOVE  ))) )
261     {
262         return true;
263     }
264     else if (( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDBEFORE ))) ||
265              ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDAFTER ))) )
266     {
267         if ( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_ADDFIRST )))
268             return lcl_MergeItems( pStatusbar, 0, 0, rItemId, rModuleIdentifier, rItems );
269         else if ( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_ADDLAST )))
270             return lcl_MergeItems( pStatusbar, STATUSBAR_APPEND, 0, rItemId, rModuleIdentifier, rItems );
271     }
272 
273     return false;
274 }
275 
276 
277 }
278