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 #include <uielement/statusbarmerger.hxx>
23 
24 using rtl::OUString;
25 using com::sun::star::frame::XFrame;
26 using com::sun::star::uno::Reference;
27 using com::sun::star::beans::PropertyValue;
28 using com::sun::star::uno::Sequence;
29 
30 namespace framework
31 {
32 namespace {
33 
34 static const char MERGE_STATUSBAR_URL[]         = "URL";
35 static const char MERGE_STATUSBAR_TITLE[]       = "Title";
36 static const char MERGE_STATUSBAR_CONTEXT[]     = "Context";
37 static const char MERGE_STATUSBAR_ALIGN[]       = "Alignment";
38 static const char MERGE_STATUSBAR_AUTOSIZE[]    = "AutoSize";
39 static const char MERGE_STATUSBAR_OWNERDRAW[]   = "OwnerDraw";
40 static const char MERGE_STATUSBAR_WIDTH[]       = "Width";
41 
42 static const char STATUSBAR_ALIGN_LEFT[]        = "left";
43 static const char STATUSBAR_ALIGN_CENTER[]      = "center";
44 static const char STATUSBAR_ALIGN_RIGHT[]       = "right";
45 
46 static const char MERGECOMMAND_ADDAFTER[]       = "AddAfter";
47 static const char MERGECOMMAND_ADDBEFORE[]      = "AddBefore";
48 static const char MERGECOMMAND_REPLACE[]        = "Replace";
49 static const char MERGECOMMAND_REMOVE[]         = "Remove";
50 
51 static const char MERGEFALLBACK_ADDLAST[]       = "AddLast";
52 static const char MERGEFALLBACK_ADDFIRST[]      = "AddFirst";
53 static const char MERGEFALLBACK_IGNORE[]        = "Ignore";
54 
55 
56 static void lcl_ConvertSequenceToValues(
57     const Sequence< PropertyValue > &rSequence,
58     AddonStatusbarItem &rItem )
59 {
60     OUString sAlignment;
61     sal_Bool bAutoSize = sal_False;
62     sal_Bool bOwnerDraw = sal_False;
63 
64     PropertyValue aPropVal;
65     for ( sal_Int32 i = 0; i < rSequence.getLength(); i++ )
66     {
67         aPropVal = rSequence[i];
68         if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_URL ) ) )
69             aPropVal.Value >>= rItem.aCommandURL;
70         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_TITLE ) ) )
71             aPropVal.Value >>= rItem.aLabel;
72         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_CONTEXT ) ) )
73             aPropVal.Value >>= rItem.aContext;
74         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_ALIGN ) ) )
75             aPropVal.Value >>= sAlignment;
76         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_AUTOSIZE ) ) )
77             aPropVal.Value >>= bAutoSize;
78         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_OWNERDRAW ) ) )
79             aPropVal.Value >>= bOwnerDraw;
80         else if ( aPropVal.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGE_STATUSBAR_WIDTH ) ) )
81         {
82             sal_Int32 aWidth = 0;
83             aPropVal.Value >>= aWidth;
84             rItem.nWidth = sal_uInt16( aWidth );
85         }
86     }
87 
88     sal_uInt16 nItemBits(0);
89     if ( bAutoSize )
90         nItemBits |= SIB_AUTOSIZE;
91     if ( bOwnerDraw )
92         nItemBits |= SIB_USERDRAW;
93     if ( sAlignment.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STATUSBAR_ALIGN_CENTER )))
94         nItemBits |= SIB_CENTER;
95     else if ( sAlignment.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STATUSBAR_ALIGN_RIGHT )))
96         nItemBits |= SIB_RIGHT;
97     else
98         // if unset, defaults to left alignment
99         nItemBits |= SIB_LEFT;
100     rItem.nItemBits = nItemBits;
101 }
102 
103 static void lcl_CreateStatusbarItem( StatusBar* pStatusbar,
104                                      sal_uInt16 nPos,
105                                      sal_uInt16 nItemId,
106                                      const AddonStatusbarItem& rAddonItem )
107 {
108     pStatusbar->InsertItem( nItemId,
109                             rAddonItem.nWidth,
110                             rAddonItem.nItemBits,
111                             STATUSBAR_OFFSET,
112                             nPos );
113     pStatusbar->SetItemCommand( nItemId, rAddonItem.aCommandURL );
114     pStatusbar->SetQuickHelpText( nItemId, rAddonItem.aLabel );
115     pStatusbar->SetAccessibleName( nItemId, rAddonItem.aLabel );
116 
117     // add-on specific data
118     AddonStatusbarItemData *pUserData = new AddonStatusbarItemData;
119     pUserData->aLabel = rAddonItem.aLabel;
120     pUserData->nItemBits = rAddonItem.nItemBits;
121     pStatusbar->SetItemData( nItemId, pUserData );
122 }
123 
124 static bool lcl_MergeItems( StatusBar* pStatusbar,
125                             sal_uInt16 nPos,
126                             sal_uInt16 nModIndex,
127                             sal_uInt16& rItemId,
128                             const ::rtl::OUString& rModuleIdentifier,
129                             const AddonStatusbarItemContainer& rAddonItems )
130 {
131     const sal_uInt16 nSize( rAddonItems.size() );
132     for ( sal_Int32 i = 0; i < nSize; i++ )
133     {
134         const AddonStatusbarItem& rItem = rAddonItems[i];
135         if ( !StatusbarMerger::IsCorrectContext( rItem.aContext, rModuleIdentifier ) )
136             continue;
137 
138         sal_uInt16 nInsPos = nPos + nModIndex + i;
139         if ( nInsPos > pStatusbar->GetItemCount() )
140             nInsPos = STATUSBAR_APPEND;
141 
142         lcl_CreateStatusbarItem( pStatusbar, nInsPos, rItemId, rItem );
143         ++rItemId;
144     }
145 
146     return true;
147 }
148 
149 static bool lcl_ReplaceItem( StatusBar* pStatusbar,
150                              sal_uInt16 nPos,
151                              sal_uInt16& rItemId,
152                             const ::rtl::OUString& rModuleIdentifier,
153                              const AddonStatusbarItemContainer& rAddonToolbarItems )
154 {
155     pStatusbar->RemoveItem( pStatusbar->GetItemId( nPos ) );
156     return lcl_MergeItems( pStatusbar, nPos, 0, rItemId, rModuleIdentifier, rAddonToolbarItems );
157 }
158 
159 static bool lcl_RemoveItems( StatusBar* pStatusbar,
160                              sal_uInt16 nPos,
161                              const ::rtl::OUString& rMergeCommandParameter )
162 {
163     sal_Int32 nCount = rMergeCommandParameter.toInt32();
164     if ( nCount > 0 )
165     {
166         for ( sal_Int32 i = 0; i < nCount; i++ )
167         {
168             if ( nPos < pStatusbar->GetItemCount() )
169                 pStatusbar->RemoveItem( nPos );
170         }
171     }
172     return true;
173 }
174 
175 /*
176 static ::cppu::OWeakObject* CreateController(
177     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMGR,
178     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame,
179     StatusBar* pStatusbar,
180     const ::rtl::OUString& rCommandURL,
181     sal_uInt16 nId,
182     sal_uInt16 nWidth,
183     const ::rtl::OUString& rControlType );
184 
185 */
186 }
187 
188 bool StatusbarMerger::IsCorrectContext(
189     const OUString& rContext,
190     const OUString& rModuleIdentifier )
191 {
192     return (( rContext.getLength() == 0 ) || ( rContext.indexOf( rModuleIdentifier ) >= 0 ));
193 }
194 
195 bool StatusbarMerger::ConvertSeqSeqToVector(
196     const Sequence< Sequence< PropertyValue > > &rSequence,
197     AddonStatusbarItemContainer& rContainer )
198 {
199     for ( sal_Int32 i = 0; i < rSequence.getLength(); i++ )
200     {
201         AddonStatusbarItem aStatusBarItem;
202         lcl_ConvertSequenceToValues( rSequence[i], aStatusBarItem );
203         rContainer.push_back( aStatusBarItem );
204     }
205 
206     return true;
207 }
208 
209 sal_uInt16 StatusbarMerger::FindReferencePos(
210     StatusBar* pStatusbar,
211     const OUString& rReferencePoint )
212 {
213     for ( sal_uInt16 nPos = 0; nPos < pStatusbar->GetItemCount(); nPos++ )
214     {
215         const ::rtl::OUString rCmd = pStatusbar->GetItemCommand( pStatusbar->GetItemId( nPos ) );
216         if ( rReferencePoint == rCmd )
217             return nPos;
218     }
219 
220     return STATUSBAR_ITEM_NOTFOUND;
221 }
222 
223 bool StatusbarMerger::ProcessMergeOperation(
224     StatusBar* pStatusbar,
225     sal_uInt16 nPos,
226     sal_uInt16& rItemId,
227     const ::rtl::OUString& rModuleIdentifier,
228     const ::rtl::OUString& rMergeCommand,
229     const ::rtl::OUString& rMergeCommandParameter,
230     const AddonStatusbarItemContainer& rItems )
231 {
232     if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDAFTER ) ) )
233         return lcl_MergeItems( pStatusbar, nPos, 1, rItemId, rModuleIdentifier, rItems );
234     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDBEFORE ) ) )
235         return lcl_MergeItems( pStatusbar, nPos, 0, rItemId, rModuleIdentifier, rItems );
236     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_REPLACE ) ) )
237         return lcl_ReplaceItem( pStatusbar, nPos, rItemId, rModuleIdentifier, rItems );
238     else if ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_REMOVE ) ) )
239         return lcl_RemoveItems( pStatusbar, nPos, rMergeCommandParameter );
240 
241     return false;
242 }
243 
244 bool StatusbarMerger::ProcessMergeFallback(
245     StatusBar* pStatusbar,
246     sal_uInt16 /*nPos*/,
247     sal_uInt16& rItemId,
248     const ::rtl::OUString& rModuleIdentifier,
249     const ::rtl::OUString& rMergeCommand,
250     const ::rtl::OUString& rMergeFallback,
251     const AddonStatusbarItemContainer& rItems )
252 {
253     // fallback IGNORE or REPLACE/REMOVE item not found
254     if (( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_IGNORE ))) ||
255             ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(  MERGECOMMAND_REPLACE ))) ||
256             ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(  MERGECOMMAND_REMOVE  ))) )
257     {
258         return true;
259     }
260     else if (( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDBEFORE ))) ||
261              ( rMergeCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGECOMMAND_ADDAFTER ))) )
262     {
263         if ( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_ADDFIRST )))
264             return lcl_MergeItems( pStatusbar, 0, 0, rItemId, rModuleIdentifier, rItems );
265         else if ( rMergeFallback.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MERGEFALLBACK_ADDLAST )))
266             return lcl_MergeItems( pStatusbar, STATUSBAR_APPEND, 0, rItemId, rModuleIdentifier, rItems );
267     }
268 
269     return false;
270 }
271 
272 
273 }
274