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 
lcl_ConvertSequenceToValues(const Sequence<PropertyValue> & rSequence,AddonStatusbarItem & rItem)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 
lcl_CreateStatusbarItem(StatusBar * pStatusbar,sal_uInt16 nPos,sal_uInt16 nItemId,const AddonStatusbarItem & rAddonItem)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 
lcl_MergeItems(StatusBar * pStatusbar,sal_uInt16 nPos,sal_uInt16 nModIndex,sal_uInt16 & rItemId,const::rtl::OUString & rModuleIdentifier,const AddonStatusbarItemContainer & rAddonItems)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 
lcl_ReplaceItem(StatusBar * pStatusbar,sal_uInt16 nPos,sal_uInt16 & rItemId,const::rtl::OUString & rModuleIdentifier,const AddonStatusbarItemContainer & rAddonToolbarItems)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 
lcl_RemoveItems(StatusBar * pStatusbar,sal_uInt16 nPos,const::rtl::OUString & rMergeCommandParameter)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 
IsCorrectContext(const OUString & rContext,const OUString & rModuleIdentifier)181 bool StatusbarMerger::IsCorrectContext(
182     const OUString& rContext,
183     const OUString& rModuleIdentifier )
184 {
185     return (( rContext.getLength() == 0 ) || ( rContext.indexOf( rModuleIdentifier ) >= 0 ));
186 }
187 
ConvertSeqSeqToVector(const Sequence<Sequence<PropertyValue>> & rSequence,AddonStatusbarItemContainer & rContainer)188 bool StatusbarMerger::ConvertSeqSeqToVector(
189     const Sequence< Sequence< PropertyValue > > &rSequence,
190     AddonStatusbarItemContainer& rContainer )
191 {
192     for ( sal_Int32 i = 0; i < rSequence.getLength(); i++ )
193     {
194         AddonStatusbarItem aStatusBarItem;
195         lcl_ConvertSequenceToValues( rSequence[i], aStatusBarItem );
196         rContainer.push_back( aStatusBarItem );
197     }
198 
199     return true;
200 }
201 
FindReferencePos(StatusBar * pStatusbar,const OUString & rReferencePoint)202 sal_uInt16 StatusbarMerger::FindReferencePos(
203     StatusBar* pStatusbar,
204     const OUString& rReferencePoint )
205 {
206     for ( sal_uInt16 nPos = 0; nPos < pStatusbar->GetItemCount(); nPos++ )
207     {
208         const ::rtl::OUString rCmd = pStatusbar->GetItemCommand( pStatusbar->GetItemId( nPos ) );
209         if ( rReferencePoint == rCmd )
210             return nPos;
211     }
212 
213     return STATUSBAR_ITEM_NOTFOUND;
214 }
215 
ProcessMergeOperation(StatusBar * pStatusbar,sal_uInt16 nPos,sal_uInt16 & rItemId,const::rtl::OUString & rModuleIdentifier,const::rtl::OUString & rMergeCommand,const::rtl::OUString & rMergeCommandParameter,const AddonStatusbarItemContainer & rItems)216 bool StatusbarMerger::ProcessMergeOperation(
217     StatusBar* pStatusbar,
218     sal_uInt16 nPos,
219     sal_uInt16& rItemId,
220     const ::rtl::OUString& rModuleIdentifier,
221     const ::rtl::OUString& rMergeCommand,
222     const ::rtl::OUString& rMergeCommandParameter,
223     const AddonStatusbarItemContainer& rItems )
224 {
225     if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDAFTER ) ) )
226         return lcl_MergeItems( pStatusbar, nPos, 1, rItemId, rModuleIdentifier, rItems );
227     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDBEFORE ) ) )
228         return lcl_MergeItems( pStatusbar, nPos, 0, rItemId, rModuleIdentifier, rItems );
229     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_REPLACE ) ) )
230         return lcl_ReplaceItem( pStatusbar, nPos, rItemId, rModuleIdentifier, rItems );
231     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_REMOVE ) ) )
232         return lcl_RemoveItems( pStatusbar, nPos, rMergeCommandParameter );
233 
234     return false;
235 }
236 
ProcessMergeFallback(StatusBar * pStatusbar,sal_uInt16,sal_uInt16 & rItemId,const::rtl::OUString & rModuleIdentifier,const::rtl::OUString & rMergeCommand,const::rtl::OUString & rMergeFallback,const AddonStatusbarItemContainer & rItems)237 bool StatusbarMerger::ProcessMergeFallback(
238     StatusBar* pStatusbar,
239     sal_uInt16 /*nPos*/,
240     sal_uInt16& rItemId,
241     const ::rtl::OUString& rModuleIdentifier,
242     const ::rtl::OUString& rMergeCommand,
243     const ::rtl::OUString& rMergeFallback,
244     const AddonStatusbarItemContainer& rItems )
245 {
246     // fallback IGNORE or REPLACE/REMOVE item not found
247     if (( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_IGNORE ))) ||
248             ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(  MERGECOMMAND_REPLACE ))) ||
249             ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(  MERGECOMMAND_REMOVE  ))) )
250     {
251         return true;
252     }
253     else if (( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDBEFORE ))) ||
254              ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDAFTER ))) )
255     {
256         if ( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_ADDFIRST )))
257             return lcl_MergeItems( pStatusbar, 0, 0, rItemId, rModuleIdentifier, rItems );
258         else if ( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_ADDLAST )))
259             return lcl_MergeItems( pStatusbar, STATUSBAR_APPEND, 0, rItemId, rModuleIdentifier, rItems );
260     }
261 
262     return false;
263 }
264 
265 
266 }
267