Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sfx2/source/statbar/stbitem.cxx
Line
Count
Source
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 <svl/stritem.hxx>
21
#include <svl/voiditem.hxx>
22
#include <com/sun/star/util/URL.hpp>
23
#include <com/sun/star/util/URLTransformer.hpp>
24
#include <com/sun/star/util/XURLTransformer.hpp>
25
#include <com/sun/star/frame/XController.hpp>
26
#include <com/sun/star/frame/XDispatchProvider.hpp>
27
#include <com/sun/star/lang/XUnoTunnel.hpp>
28
#include <com/sun/star/frame/status/ItemStatus.hpp>
29
#include <com/sun/star/awt/MouseButton.hpp>
30
31
#include <vcl/commandevent.hxx>
32
#include <vcl/event.hxx>
33
#include <vcl/status.hxx>
34
#include <vcl/svapp.hxx>
35
#include <vcl/unohelp.hxx>
36
37
#include <sfx2/app.hxx>
38
#include <sfx2/stbitem.hxx>
39
#include <sfx2/msg.hxx>
40
#include <sfx2/msgpool.hxx>
41
#include <sfx2/module.hxx>
42
#include <sfx2/dispatch.hxx>
43
#include <unoctitm.hxx>
44
#include <sfx2/objsh.hxx>
45
46
#include <comphelper/processfactory.hxx>
47
#include <comphelper/servicehelper.hxx>
48
#include <svl/eitem.hxx>
49
#include <svl/intitem.hxx>
50
#include <toolkit/helper/vclunohelper.hxx>
51
52
using namespace ::com::sun::star;
53
54
55
sal_uInt16 SfxStatusBarControl::convertAwtToVCLMouseButtons( sal_Int16 nAwtMouseButtons )
56
0
{
57
0
    sal_uInt16 nVCLMouseButtons( 0 );
58
59
0
    if ( nAwtMouseButtons & awt::MouseButton::LEFT )
60
0
        nVCLMouseButtons |= MOUSE_LEFT;
61
0
    if ( nAwtMouseButtons & awt::MouseButton::RIGHT )
62
0
        nVCLMouseButtons |= MOUSE_RIGHT;
63
0
    if ( nAwtMouseButtons & awt::MouseButton::MIDDLE )
64
0
        nVCLMouseButtons |= MOUSE_MIDDLE;
65
66
0
    return nVCLMouseButtons;
67
0
}
68
69
70
rtl::Reference<svt::StatusbarController> SfxStatusBarControllerFactory(
71
    const uno::Reference< frame::XFrame >& rFrame,
72
    StatusBar* pStatusBar,
73
    unsigned short nID,
74
    const OUString& aCommandURL )
75
0
{
76
0
    SolarMutexGuard aGuard;
77
78
0
    util::URL aTargetURL;
79
0
    aTargetURL.Complete = aCommandURL;
80
0
    uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
81
0
    xTrans->parseStrict( aTargetURL );
82
83
0
    uno::Reference < frame::XController > xController;
84
0
    uno::Reference < frame::XModel > xModel;
85
0
    if ( rFrame.is() )
86
0
    {
87
0
        xController = rFrame->getController();
88
0
        if ( xController.is() )
89
0
            xModel = xController->getModel();
90
0
    }
91
92
0
    SfxObjectShell* pObjShell = SfxObjectShell::GetShellFromComponent(xModel);
93
94
0
    SfxModule*     pModule   = pObjShell ? pObjShell->GetModule() : nullptr;
95
0
    SfxSlotPool*   pSlotPool = nullptr;
96
97
0
    if ( pModule )
98
0
        pSlotPool = pModule->GetSlotPool();
99
0
    else
100
0
        pSlotPool = &(SfxSlotPool::GetSlotPool());
101
102
0
    const SfxSlot* pSlot = pSlotPool->GetUnoSlot( aTargetURL.Path );
103
0
    if ( pSlot )
104
0
    {
105
0
        sal_uInt16 nSlotId = pSlot->GetSlotId();
106
0
        if ( nSlotId > 0 )
107
0
        {
108
0
            OUString aCmd = pSlot->GetCommand();
109
0
            pStatusBar->SetHelpId( nSlotId, aCmd );
110
0
            return SfxStatusBarControl::CreateControl( nSlotId, nID, pStatusBar, pModule );
111
0
        }
112
0
    }
113
114
0
    return nullptr;
115
0
}
116
117
118
SfxStatusBarControl::SfxStatusBarControl
119
(
120
    sal_uInt16      nSlotID,            /* Slot-Id which is connected to this
121
                                       instance. If a Slot-Id is set to != 0 at
122
                                       registration it will always be set there.
123
                                    */
124
125
126
    sal_uInt16      nCtrlID,            /* ID of this controller in the status bar */
127
128
    StatusBar&  rBar                /* Reference to the StatusBar,for which
129
                                       this Control was created. */
130
)
131
132
133
/*  [Description]
134
135
    Constructor of the SfxStatusBarControl Class. The Subclasses are
136
    created at the Factory if necessary.
137
138
    Instances of this base class are created for all StatusBar-fields
139
    for which no specific ones have been registered.
140
*/
141
142
0
:   nSlotId( nSlotID ),
143
0
    nId( nCtrlID ),
144
0
    pBar( &rBar )
145
0
{
146
0
}
147
148
149
SfxStatusBarControl::~SfxStatusBarControl()
150
151
/*  [Description]
152
153
    Destructor of the SfxStatusBarControl Class. The Class and its Subclasses
154
    are destroyed by SFx.
155
*/
156
157
0
{}
158
159
160
// XInterface
161
void SAL_CALL SfxStatusBarControl::acquire() noexcept
162
0
{
163
0
    OWeakObject::acquire();
164
0
}
165
166
void SAL_CALL SfxStatusBarControl::release() noexcept
167
0
{
168
0
    OWeakObject::release();
169
0
}
170
171
172
// XStatusListener
173
void SAL_CALL SfxStatusBarControl::statusChanged( const frame::FeatureStateEvent& rEvent )
174
0
{
175
0
    SfxViewFrame* pViewFrame = nullptr;
176
0
    uno::Reference < frame::XController > xController;
177
178
0
    SolarMutexGuard aGuard;
179
0
    if ( m_xFrame.is() )
180
0
        xController = m_xFrame->getController();
181
182
0
    uno::Reference < frame::XDispatchProvider > xProvider( xController, uno::UNO_QUERY );
183
0
    if ( xProvider.is() )
184
0
    {
185
0
        uno::Reference < frame::XDispatch > xDisp = xProvider->queryDispatch( rEvent.FeatureURL, OUString(), 0 );
186
0
        if ( xDisp.is() )
187
0
        {
188
0
            if (auto pDisp = dynamic_cast<SfxOfficeDispatch*>(xDisp.get()))
189
0
                pViewFrame = pDisp->GetDispatcher_Impl()->GetFrame();
190
0
        }
191
0
    }
192
193
0
    sal_uInt16 nSlotID = 0;
194
0
    SfxSlotPool& rPool = SfxSlotPool::GetSlotPool( pViewFrame );
195
0
    const SfxSlot* pSlot = rPool.GetUnoSlot( rEvent.FeatureURL.Path );
196
0
    if ( pSlot )
197
0
        nSlotID = pSlot->GetSlotId();
198
199
0
    if ( nSlotID <= 0 )
200
0
        return;
201
202
0
    if ( rEvent.Requery )
203
0
        svt::StatusbarController::statusChanged( rEvent );
204
0
    else
205
0
    {
206
0
        SfxItemState eState = SfxItemState::DISABLED;
207
0
        std::unique_ptr<SfxPoolItem> pItem;
208
0
        if ( rEvent.IsEnabled )
209
0
        {
210
0
            eState = SfxItemState::DEFAULT;
211
0
            uno::Type aType = rEvent.State.getValueType();
212
213
0
            if ( aType == cppu::UnoType<void>::get() )
214
0
            {
215
0
                pItem.reset( new SfxVoidItem( nSlotID ) );
216
0
                eState = SfxItemState::UNKNOWN;
217
0
            }
218
0
            else if ( aType == cppu::UnoType<bool>::get() )
219
0
            {
220
0
                bool bTemp = false;
221
0
                rEvent.State >>= bTemp ;
222
0
                pItem.reset( new SfxBoolItem( nSlotID, bTemp ) );
223
0
            }
224
0
            else if ( aType == ::cppu::UnoType< ::cppu::UnoUnsignedShortType >::get() )
225
0
            {
226
0
                sal_uInt16 nTemp = 0;
227
0
                rEvent.State >>= nTemp ;
228
0
                pItem.reset( new SfxUInt16Item( nSlotID, nTemp ) );
229
0
            }
230
0
            else if ( aType == cppu::UnoType<sal_uInt32>::get() )
231
0
            {
232
0
                sal_uInt32 nTemp = 0;
233
0
                rEvent.State >>= nTemp ;
234
0
                pItem.reset( new SfxUInt32Item( nSlotID, nTemp ) );
235
0
            }
236
0
            else if ( aType == cppu::UnoType<OUString>::get() )
237
0
            {
238
0
                OUString sTemp ;
239
0
                rEvent.State >>= sTemp ;
240
0
                pItem.reset( new SfxStringItem( nSlotID, sTemp ) );
241
0
            }
242
0
            else if ( aType == cppu::UnoType< css::frame::status::ItemStatus>::get() )
243
0
            {
244
0
                frame::status::ItemStatus aItemStatus;
245
0
                rEvent.State >>= aItemStatus;
246
0
                eState = static_cast<SfxItemState>(aItemStatus.State);
247
0
                pItem.reset( new SfxVoidItem( nSlotID ) );
248
0
            }
249
0
            else
250
0
            {
251
0
                if ( pSlot )
252
0
                    pItem = pSlot->GetType()->CreateItem();
253
0
                if ( pItem )
254
0
                {
255
0
                    pItem->SetWhich( nSlotID );
256
0
                    pItem->PutValue( rEvent.State, 0 );
257
0
                }
258
0
                else
259
0
                    pItem.reset( new SfxVoidItem( nSlotID ) );
260
0
            }
261
0
        }
262
263
0
        StateChangedAtStatusBarControl( nSlotID, eState, pItem.get() );
264
0
    }
265
0
}
266
267
// XStatusbarController
268
sal_Bool SAL_CALL SfxStatusBarControl::mouseButtonDown(
269
    const awt::MouseEvent& rMouseEvent )
270
0
{
271
0
    SolarMutexGuard aGuard;
272
0
    ::Point aPos( rMouseEvent.X, rMouseEvent.Y );
273
274
0
    ::MouseEvent aMouseEvent( aPos,
275
0
                              static_cast<sal_uInt16>(rMouseEvent.ClickCount),
276
0
                              MouseEventModifiers::NONE,
277
0
                              convertAwtToVCLMouseButtons( rMouseEvent.Buttons ),
278
0
                              0 );
279
280
0
    return MouseButtonDown( aMouseEvent );
281
0
}
282
283
sal_Bool SAL_CALL SfxStatusBarControl::mouseMove(
284
    const awt::MouseEvent& rMouseEvent )
285
0
{
286
0
    SolarMutexGuard aGuard;
287
0
    ::Point aPos( rMouseEvent.X, rMouseEvent.Y );
288
289
0
    ::MouseEvent aMouseEvent( aPos,
290
0
                              static_cast<sal_uInt16>(rMouseEvent.ClickCount),
291
0
                              MouseEventModifiers::NONE,
292
0
                              convertAwtToVCLMouseButtons( rMouseEvent.Buttons ),
293
0
                              0 );
294
0
    return MouseMove( aMouseEvent );
295
0
}
296
297
sal_Bool SAL_CALL SfxStatusBarControl::mouseButtonUp(
298
    const ::awt::MouseEvent& rMouseEvent )
299
0
{
300
0
    SolarMutexGuard aGuard;
301
0
    ::Point aPos( rMouseEvent.X, rMouseEvent.Y );
302
303
0
    ::MouseEvent aMouseEvent( aPos,
304
0
                              static_cast<sal_uInt16>(rMouseEvent.ClickCount),
305
0
                              MouseEventModifiers::NONE,
306
0
                              convertAwtToVCLMouseButtons( rMouseEvent.Buttons ),
307
0
                              0 );
308
0
    return MouseButtonUp( aMouseEvent );
309
0
}
310
311
void SAL_CALL SfxStatusBarControl::command(
312
    const awt::Point& rPos,
313
    ::sal_Int32 nCommand,
314
    sal_Bool /*bMouseEvent*/,
315
    const css::uno::Any& /*aData*/ )
316
0
{
317
0
    SolarMutexGuard aGuard;
318
0
    ::Point aPos( rPos.X, rPos.Y );
319
0
    CommandEvent aCmdEvent( aPos, static_cast<CommandEventId>(nCommand), true, nullptr );
320
321
0
    Command( aCmdEvent );
322
0
}
323
324
void SAL_CALL SfxStatusBarControl::paint(
325
    const uno::Reference< awt::XGraphics >& xGraphics,
326
    const awt::Rectangle& rOutputRectangle,
327
    ::sal_Int32 /*nStyle*/ )
328
0
{
329
0
    SolarMutexGuard aGuard;
330
331
0
    OutputDevice* pOutDev = VCLUnoHelper::GetOutputDevice( xGraphics );
332
0
    if ( pOutDev )
333
0
    {
334
0
        ::tools::Rectangle aRect = vcl::unohelper::ConvertToVCLRect(rOutputRectangle);
335
0
        UserDrawEvent aUserDrawEvent(pOutDev, aRect, pBar->GetCurItemId());
336
0
        Paint( aUserDrawEvent );
337
0
    }
338
0
}
339
340
void SAL_CALL SfxStatusBarControl::click( const awt::Point& )
341
0
{
342
0
    SolarMutexGuard aGuard;
343
0
    Click();
344
0
}
345
346
void SAL_CALL SfxStatusBarControl::doubleClick( const awt::Point& )
347
0
{
348
0
}
349
350
// old sfx2 interface
351
void SfxStatusBarControl::StateChangedAtStatusBarControl
352
(
353
    sal_uInt16              nSID,
354
    SfxItemState        eState,
355
    const SfxPoolItem*  pState  /* Pointer to SfxPoolItem, is only valid
356
                                   within this Method call. This can be a
357
                                   Null-Pointer, a Pointer to SfxVoidItem
358
                                   or of this Type found registered by the
359
                                   Subclass of SfxStatusBarControl.
360
                                */
361
)
362
363
/*  [Description]
364
365
    The base implementation includes items of type SfxStringItem
366
    where the text is entered in the status row field and
367
    SfxVoidItem, where the field is emptied. The base implementation
368
    should not be called in overriding methods.
369
*/
370
371
0
{
372
0
    DBG_ASSERT( pBar != nullptr, "setting state to dangling StatusBar" );
373
374
0
    const SfxStringItem* pStr = dynamic_cast<const SfxStringItem*>( pState  );
375
0
    if ( eState == SfxItemState::DEFAULT && pStr )
376
0
        pBar->SetItemText( nSID, pStr->GetValue() );
377
0
    else
378
0
    {
379
0
        DBG_ASSERT( eState != SfxItemState::DEFAULT || IsDisabledItem(pState),
380
0
                    "wrong SfxPoolItem subclass in SfxStatusBarControl" );
381
0
        pBar->SetItemText( nSID, OUString() );
382
0
    }
383
0
}
384
385
386
bool SfxStatusBarControl::MouseButtonDown( const MouseEvent & )
387
388
/*  [Description]
389
390
    This virtual method forwards the Event MouseButtonDown() of the
391
    StatusBar if the mouse position is within the range of the items,
392
    or if the mouse was captured by <SfxStatusBarControl::CaptureMouse()>
393
394
    The default implementation is empty and returns FALSE.
395
396
    [Return value]
397
398
    sal_Bool                TRUE
399
           The event has been processed and is not intended to
400
           be forwarded to StatusBar
401
402
                        FALSE
403
           The event was not processed and is to be
404
           be forwarded to StatusBar
405
*/
406
407
0
{
408
0
    return false;
409
0
}
410
411
412
bool SfxStatusBarControl::MouseMove( const MouseEvent & )
413
414
/*  [Description]
415
416
    This virtual method forwards the Event MouseMove() of the
417
    StatusBar if the mouse position is within the range of the items,
418
    or if the mouse was captured by <SfxStatusBarControl::CaptureMouse()>
419
420
    The default implementation is empty and returns FALSE.
421
422
    [Return value]
423
424
    sal_Bool                TRUE
425
           The event has been processed and is not intended to
426
           be forwarded to StatusBar
427
428
                        FALSE
429
           The event was not processed and is to be
430
           be forwarded to StatusBar
431
*/
432
433
0
{
434
0
    return false;
435
0
}
436
437
438
bool SfxStatusBarControl::MouseButtonUp( const MouseEvent & )
439
440
/*  [Description]
441
442
    This virtual method forwards the Event MouseButtonUp() of the
443
    StatusBar if the mouse position is within the range of the items,
444
    or if the mouse was captured by <SfxStatusBarControl::CaptureMouse()>
445
446
    The default implementation is empty and returns FALSE.
447
448
    [Return value]
449
450
    sal_Bool                TRUE
451
           The event has been processed and is not intended to
452
           be forwarded to StatusBar
453
454
                        FALSE
455
           The event was not processed and is to be
456
           be forwarded to StatusBar
457
*/
458
459
0
{
460
0
    return false;
461
0
}
462
463
464
void SfxStatusBarControl::Command( const CommandEvent& )
465
466
/*  [Description]
467
468
    This virtual method is called when a CommandEvent is received by
469
    SfxStatusBarControl.
470
471
    The default implementation is empty.
472
*/
473
474
0
{
475
0
}
476
477
478
void SfxStatusBarControl::Click()
479
480
/*  [Description]
481
482
    This virtual method is called when the user clicks on the
483
    field in the status row that belongs to this control.
484
*/
485
486
0
{
487
0
    css::uno::Sequence< css::beans::PropertyValue > aArgs;
488
0
    execute( aArgs );
489
0
}
490
491
492
void SfxStatusBarControl::Paint
493
(
494
    const UserDrawEvent& /* Reference to an UserDrawEvent */
495
)
496
497
/*  [Description]
498
499
    This virtual method is called to paint the contents if the field
500
    at hand is marked with StatusBarItemBits::UserDraw. The output must be obtained
501
    within the Rectangle of rUDEvt.GetRect() by the OutputDevice
502
    given by rUDEvt.GetDevice().
503
504
    The default implementation is empty.
505
*/
506
507
0
{
508
0
}
509
510
511
rtl::Reference<SfxStatusBarControl> SfxStatusBarControl::CreateControl
512
(
513
    sal_uInt16     nSlotID,
514
    sal_uInt16     nStbId,
515
    StatusBar* pBar,
516
    SfxModule const * pMod
517
)
518
0
{
519
0
    SolarMutexGuard aGuard;
520
0
    SfxApplication *pApp = SfxGetpApp();
521
522
0
    SfxSlotPool *pSlotPool;
523
0
    if ( pMod )
524
0
        pSlotPool = pMod->GetSlotPool();
525
0
    else
526
0
        pSlotPool = &SfxSlotPool::GetSlotPool();
527
528
0
    const std::type_info* aSlotType = pSlotPool->GetSlotType(nSlotID);
529
0
    if ( aSlotType )
530
0
    {
531
0
        if ( pMod )
532
0
        {
533
0
            SfxStbCtrlFactory *pFact = pMod->GetStbCtrlFactory(*aSlotType, nSlotID);
534
0
            if ( pFact )
535
0
                return pFact->pCtor( nSlotID, nStbId, *pBar );
536
0
        }
537
538
0
        SfxStbCtrlFactory* pFact = pApp->GetStbCtrlFactory(*aSlotType, nSlotID);
539
0
        if (pFact)
540
0
            return pFact->pCtor( nSlotID, nStbId, *pBar );
541
0
    }
542
543
0
    return nullptr;
544
0
}
545
546
547
void SfxStatusBarControl::RegisterStatusBarControl(SfxModule* pMod, const SfxStbCtrlFactory& rFact)
548
249
{
549
249
    SfxGetpApp()->RegisterStatusBarControl_Impl( pMod, rFact );
550
249
}
551
552
553
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */