Files
loongoffice/UnoControls/source/controls/progressmonitor.cxx
Stephan Bergmann 99ac0876bd Base BaseControl on WeakComponentImplHelper
...rather than on the deprecated OComponentHelper.

Various classes like BaseContainerControl, FrameControl, and ProgressBar, all
deriving from BaseControl, had been found to implement their respective
queryInterface in a way that is incompatible with the XAggregation protocol
inherited via OComponentHelper.  It looks like no code actually made use of the
XAggregation offered by this class hierarchy, so the easiest fix for those
queryInterface implementations appears to switch from OComponentHelper to
WeakComponentImplHelper.

Ideally, BaseControl would derive from WeakComponentImplHelper<XServiceInfo,
XPaintListener, XWindowListener, ...> covering all the UNO interface classes
from which it currently derives manually.  But changing that manual
implementation across the BaseControl class Hierarchy looks tricky, so merely
introduce an "empty" WeakComponentImplHelper<> for now and keep all the manual
stuff, and leave proper clean up for later.

Change-Id: I1aa8b06f78700008f844415818f4a5801daa89b8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145902
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2023-01-20 17:18:27 +00:00

833 lines
30 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <progressmonitor.hxx>
#include <com/sun/star/awt/XFixedText.hpp>
#include <com/sun/star/awt/XGraphics.hpp>
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <cppuhelper/typeprovider.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <rtl/ustrbuf.hxx>
#include <tools/debug.hxx>
#include <algorithm>
#include <progressbar.hxx>
using namespace ::cppu;
using namespace ::osl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::awt;
using ::std::vector;
constexpr OUStringLiteral FIXEDTEXT_SERVICENAME = u"com.sun.star.awt.UnoControlFixedText";
constexpr OUStringLiteral FIXEDTEXT_MODELNAME = u"com.sun.star.awt.UnoControlFixedTextModel";
constexpr OUStringLiteral CONTROLNAME_TEXT = u"Text"; // identifier the control in container
constexpr OUStringLiteral CONTROLNAME_PROGRESSBAR = u"ProgressBar";
constexpr OUStringLiteral BUTTON_SERVICENAME = u"com.sun.star.awt.UnoControlButton";
constexpr OUStringLiteral CONTROLNAME_BUTTON = u"Button";
constexpr OUStringLiteral BUTTON_MODELNAME = u"com.sun.star.awt.UnoControlButtonModel";
constexpr OUStringLiteral DEFAULT_BUTTONLABEL = u"Abbrechen";
namespace unocontrols {
ProgressMonitor::ProgressMonitor( const css::uno::Reference< XComponentContext >& rxContext )
: BaseContainerControl ( rxContext )
{
// It's not allowed to work with member in this method (refcounter !!!)
// But with a HACK (++refcount) its "OK" :-(
osl_atomic_increment(&m_refCount);
// Create instances for fixedtext, button and progress ...
m_xTopic_Top.set ( rxContext->getServiceManager()->createInstanceWithContext( FIXEDTEXT_SERVICENAME, rxContext ), UNO_QUERY );
m_xText_Top.set ( rxContext->getServiceManager()->createInstanceWithContext( FIXEDTEXT_SERVICENAME, rxContext ), UNO_QUERY );
m_xTopic_Bottom.set( rxContext->getServiceManager()->createInstanceWithContext( FIXEDTEXT_SERVICENAME, rxContext ), UNO_QUERY );
m_xText_Bottom.set ( rxContext->getServiceManager()->createInstanceWithContext( FIXEDTEXT_SERVICENAME, rxContext ), UNO_QUERY );
m_xButton.set ( rxContext->getServiceManager()->createInstanceWithContext( BUTTON_SERVICENAME, rxContext ), UNO_QUERY );
m_xProgressBar = new ProgressBar(rxContext);
// ... cast controls to Reference< XControl > (for "setModel"!) ...
css::uno::Reference< XControl > xRef_Topic_Top ( m_xTopic_Top , UNO_QUERY );
css::uno::Reference< XControl > xRef_Text_Top ( m_xText_Top , UNO_QUERY );
css::uno::Reference< XControl > xRef_Topic_Bottom ( m_xTopic_Bottom , UNO_QUERY );
css::uno::Reference< XControl > xRef_Text_Bottom ( m_xText_Bottom , UNO_QUERY );
css::uno::Reference< XControl > xRef_Button ( m_xButton , UNO_QUERY );
// ... set models ...
xRef_Topic_Top->setModel ( css::uno::Reference< XControlModel > ( rxContext->getServiceManager()->createInstanceWithContext( FIXEDTEXT_MODELNAME, rxContext ), UNO_QUERY ) );
xRef_Text_Top->setModel ( css::uno::Reference< XControlModel > ( rxContext->getServiceManager()->createInstanceWithContext( FIXEDTEXT_MODELNAME, rxContext ), UNO_QUERY ) );
xRef_Topic_Bottom->setModel ( css::uno::Reference< XControlModel > ( rxContext->getServiceManager()->createInstanceWithContext( FIXEDTEXT_MODELNAME, rxContext ), UNO_QUERY ) );
xRef_Text_Bottom->setModel ( css::uno::Reference< XControlModel > ( rxContext->getServiceManager()->createInstanceWithContext( FIXEDTEXT_MODELNAME, rxContext ), UNO_QUERY ) );
xRef_Button->setModel ( css::uno::Reference< XControlModel > ( rxContext->getServiceManager()->createInstanceWithContext( BUTTON_MODELNAME, rxContext ), UNO_QUERY ) );
// ProgressBar has no model !!!
// ... and add controls to basecontainercontrol!
addControl ( CONTROLNAME_TEXT, xRef_Topic_Top );
addControl ( CONTROLNAME_TEXT, xRef_Text_Top );
addControl ( CONTROLNAME_TEXT, xRef_Topic_Bottom );
addControl ( CONTROLNAME_TEXT, xRef_Text_Bottom );
addControl ( CONTROLNAME_BUTTON, xRef_Button );
addControl ( CONTROLNAME_PROGRESSBAR, m_xProgressBar );
// FixedText make it automatically visible by himself ... but not the progressbar !!!
// it must be set explicitly
m_xProgressBar->setVisible( true );
// Reset to defaults !!!
// (progressbar take automatically its own defaults)
m_xButton->setLabel ( DEFAULT_BUTTONLABEL );
m_xTopic_Top->setText ( PROGRESSMONITOR_DEFAULT_TOPIC );
m_xText_Top->setText ( PROGRESSMONITOR_DEFAULT_TEXT );
m_xTopic_Bottom->setText ( PROGRESSMONITOR_DEFAULT_TOPIC );
m_xText_Bottom->setText ( PROGRESSMONITOR_DEFAULT_TEXT );
osl_atomic_decrement(&m_refCount);
}
ProgressMonitor::~ProgressMonitor()
{
impl_cleanMemory ();
}
// XInterface
Any SAL_CALL ProgressMonitor::queryInterface( const Type& rType )
{
// Ask for my own supported interfaces ...
// Attention: XTypeProvider and XInterface are supported by WeakComponentImplHelper!
Any aReturn ( ::cppu::queryInterface( rType ,
static_cast< XLayoutConstrains* > ( this ) ,
static_cast< XButton* > ( this ) ,
static_cast< XProgressMonitor* > ( this )
)
);
// If searched interface not supported by this class ...
if ( !aReturn.hasValue() )
{
// ... ask baseclasses.
aReturn = BaseControl::queryInterface( rType );
}
return aReturn;
}
// XInterface
void SAL_CALL ProgressMonitor::acquire() noexcept
{
// Attention:
// Don't use mutex or guard in this method!!! Is a method of XInterface.
// Forward to baseclass
BaseControl::acquire();
}
// XInterface
void SAL_CALL ProgressMonitor::release() noexcept
{
// Attention:
// Don't use mutex or guard in this method!!! Is a method of XInterface.
// Forward to baseclass
BaseControl::release();
}
// XTypeProvider
Sequence< Type > SAL_CALL ProgressMonitor::getTypes()
{
static OTypeCollection ourTypeCollection(
cppu::UnoType<XLayoutConstrains>::get(),
cppu::UnoType<XButton>::get(),
cppu::UnoType<XProgressMonitor>::get(),
BaseContainerControl::getTypes() );
return ourTypeCollection.getTypes();
}
// XProgressMonitor
void SAL_CALL ProgressMonitor::addText(
const OUString& rTopic,
const OUString& rText,
sal_Bool bbeforeProgress
)
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
// Safe impossible cases
// Check valid call of this method.
DBG_ASSERT ( impl_debug_checkParameter ( rTopic, rText ), "ProgressMonitor::addText()\nCall without valid parameters!\n");
DBG_ASSERT ( !(impl_searchTopic ( rTopic, bbeforeProgress ) != nullptr ), "ProgressMonitor::addText()\nThe text already exist.\n" );
// Do nothing (in Release), if topic already exist.
if ( impl_searchTopic ( rTopic, bbeforeProgress ) != nullptr )
{
return;
}
// Else ... take memory for new item ...
IMPL_TextlistItem aTextItem;
// Set values ...
aTextItem.sTopic = rTopic;
aTextItem.sText = rText;
// ... and insert it in right list.
if ( bbeforeProgress )
{
maTextlist_Top.push_back( aTextItem );
}
else
{
maTextlist_Bottom.push_back( aTextItem );
}
// ... update window
impl_rebuildFixedText ();
impl_recalcLayout ();
}
// XProgressMonitor
void SAL_CALL ProgressMonitor::removeText ( const OUString& rTopic, sal_Bool bbeforeProgress )
{
// Safe impossible cases
// Check valid call of this method.
DBG_ASSERT ( impl_debug_checkParameter ( rTopic ), "ProgressMonitor::removeText()\nCall without valid parameters!" );
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
// Search the topic ...
IMPL_TextlistItem* pSearchItem = impl_searchTopic ( rTopic, bbeforeProgress );
if ( pSearchItem == nullptr )
return;
// ... delete item from right list ...
if ( bbeforeProgress )
{
auto itr = std::find_if( maTextlist_Top.begin(), maTextlist_Top.end(),
[&] (IMPL_TextlistItem const &p)
{ return &p == pSearchItem; } );
if (itr != maTextlist_Top.end())
maTextlist_Top.erase(itr);
}
else
{
auto itr = std::find_if( maTextlist_Bottom.begin(), maTextlist_Bottom.end(),
[&] (IMPL_TextlistItem const &p)
{ return &p == pSearchItem; } );
if (itr != maTextlist_Bottom.end())
maTextlist_Bottom.erase(itr);
}
// ... and update window.
impl_rebuildFixedText ();
impl_recalcLayout ();
}
// XProgressMonitor
void SAL_CALL ProgressMonitor::updateText (
const OUString& rTopic,
const OUString& rText,
sal_Bool bbeforeProgress
)
{
// Safe impossible cases
// Check valid call of this method.
DBG_ASSERT ( impl_debug_checkParameter ( rTopic, rText ), "ProgressMonitor::updateText()\nCall without valid parameters!\n" );
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
// Search topic ...
IMPL_TextlistItem* pSearchItem = impl_searchTopic ( rTopic, bbeforeProgress );
if ( pSearchItem != nullptr )
{
// ... update text ...
pSearchItem->sText = rText;
// ... and update window.
impl_rebuildFixedText ();
impl_recalcLayout ();
}
}
// XProgressBar
void SAL_CALL ProgressMonitor::setForegroundColor ( sal_Int32 nColor )
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
m_xProgressBar->setForegroundColor ( nColor );
}
// XProgressBar
void SAL_CALL ProgressMonitor::setBackgroundColor ( sal_Int32 nColor )
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
m_xProgressBar->setBackgroundColor ( nColor );
}
// XProgressBar
void SAL_CALL ProgressMonitor::setValue ( sal_Int32 nValue )
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
m_xProgressBar->setValue ( nValue );
}
// XProgressBar
void SAL_CALL ProgressMonitor::setRange ( sal_Int32 nMin, sal_Int32 nMax )
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
m_xProgressBar->setRange ( nMin, nMax );
}
// XProgressBar
sal_Int32 SAL_CALL ProgressMonitor::getValue ()
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
return m_xProgressBar->getValue ();
}
// XButton
void SAL_CALL ProgressMonitor::addActionListener ( const css::uno::Reference< XActionListener > & rListener )
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
if ( m_xButton.is () )
{
m_xButton->addActionListener ( rListener );
}
}
// XButton
void SAL_CALL ProgressMonitor::removeActionListener ( const css::uno::Reference< XActionListener > & rListener )
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
if ( m_xButton.is () )
{
m_xButton->removeActionListener ( rListener );
}
}
// XButton
void SAL_CALL ProgressMonitor::setLabel ( const OUString& rLabel )
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
if ( m_xButton.is () )
{
m_xButton->setLabel ( rLabel );
}
}
// XButton
void SAL_CALL ProgressMonitor::setActionCommand ( const OUString& rCommand )
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
if ( m_xButton.is () )
{
m_xButton->setActionCommand ( rCommand );
}
}
// XLayoutConstrains
Size SAL_CALL ProgressMonitor::getMinimumSize ()
{
return Size (PROGRESSMONITOR_DEFAULT_WIDTH, PROGRESSMONITOR_DEFAULT_HEIGHT);
}
// XLayoutConstrains
Size SAL_CALL ProgressMonitor::getPreferredSize ()
{
// Ready for multithreading
ClearableMutexGuard aGuard ( m_aMutex );
// get information about required place of child controls
css::uno::Reference< XLayoutConstrains > xTopicLayout_Top ( m_xTopic_Top , UNO_QUERY );
css::uno::Reference< XLayoutConstrains > xTopicLayout_Bottom ( m_xTopic_Bottom , UNO_QUERY );
css::uno::Reference< XLayoutConstrains > xButtonLayout ( m_xButton , UNO_QUERY );
Size aTopicSize_Top = xTopicLayout_Top->getPreferredSize ();
Size aTopicSize_Bottom = xTopicLayout_Bottom->getPreferredSize ();
Size aButtonSize = xButtonLayout->getPreferredSize ();
Rectangle aTempRectangle = m_xProgressBar->getPosSize();
Size aProgressBarSize( aTempRectangle.Width, aTempRectangle.Height );
aGuard.clear ();
// calc preferred size of progressmonitor
sal_Int32 nWidth = 3 * PROGRESSMONITOR_FREEBORDER;
nWidth += aProgressBarSize.Width;
sal_Int32 nHeight = 6 * PROGRESSMONITOR_FREEBORDER;
nHeight += aTopicSize_Top.Height;
nHeight += aProgressBarSize.Height;
nHeight += aTopicSize_Bottom.Height;
nHeight += 2; // 1 for black line, 1 for white line = 3D-Line!
nHeight += aButtonSize.Height;
// norm to minimum
if ( nWidth < PROGRESSMONITOR_DEFAULT_WIDTH )
{
nWidth = PROGRESSMONITOR_DEFAULT_WIDTH;
}
if ( nHeight < PROGRESSMONITOR_DEFAULT_HEIGHT )
{
nHeight = PROGRESSMONITOR_DEFAULT_HEIGHT;
}
// return to caller
return Size ( nWidth, nHeight );
}
// XLayoutConstrains
Size SAL_CALL ProgressMonitor::calcAdjustedSize ( const Size& /*rNewSize*/ )
{
return getPreferredSize ();
}
// XControl
void SAL_CALL ProgressMonitor::createPeer ( const css::uno::Reference< XToolkit > & rToolkit, const css::uno::Reference< XWindowPeer > & rParent )
{
if (!getPeer().is())
{
BaseContainerControl::createPeer ( rToolkit, rParent );
// If user forget to call "setPosSize()", we have still a correct size.
// And a "MinimumSize" IS A "MinimumSize"!
// We change not the position of control at this point.
Size aDefaultSize = getMinimumSize ();
setPosSize ( 0, 0, aDefaultSize.Width, aDefaultSize.Height, PosSize::SIZE );
}
}
// XControl
sal_Bool SAL_CALL ProgressMonitor::setModel ( const css::uno::Reference< XControlModel > & /*rModel*/ )
{
// We have no model.
return false;
}
// XControl
css::uno::Reference< XControlModel > SAL_CALL ProgressMonitor::getModel ()
{
// We have no model.
// return (XControlModel*)this;
return css::uno::Reference< XControlModel > ();
}
// XComponent
void SAL_CALL ProgressMonitor::dispose ()
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
// "removeControl()" control the state of a reference
css::uno::Reference< XControl > xRef_Topic_Top ( m_xTopic_Top , UNO_QUERY );
css::uno::Reference< XControl > xRef_Text_Top ( m_xText_Top , UNO_QUERY );
css::uno::Reference< XControl > xRef_Topic_Bottom ( m_xTopic_Bottom , UNO_QUERY );
css::uno::Reference< XControl > xRef_Text_Bottom ( m_xText_Bottom , UNO_QUERY );
css::uno::Reference< XControl > xRef_Button ( m_xButton , UNO_QUERY );
removeControl ( xRef_Topic_Top );
removeControl ( xRef_Text_Top );
removeControl ( xRef_Topic_Bottom );
removeControl ( xRef_Text_Bottom );
removeControl ( xRef_Button );
removeControl ( m_xProgressBar );
// don't use "...->clear ()" or "... = XFixedText ()"
// when other hold a reference at this object !!!
xRef_Topic_Top->dispose ();
xRef_Text_Top->dispose ();
xRef_Topic_Bottom->dispose ();
xRef_Text_Bottom->dispose ();
xRef_Button->dispose ();
m_xProgressBar->dispose();
BaseContainerControl::dispose ();
}
// XWindow
void SAL_CALL ProgressMonitor::setPosSize ( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int16 nFlags )
{
Rectangle aBasePosSize = getPosSize ();
BaseContainerControl::setPosSize (nX, nY, nWidth, nHeight, nFlags);
// if position or size changed
if (
( nWidth != aBasePosSize.Width ) ||
( nHeight != aBasePosSize.Height)
)
{
// calc new layout for controls
impl_recalcLayout ();
// clear background (!)
// [Children were repainted in "recalcLayout" by setPosSize() automatically!]
getPeer()->invalidate(2);
// and repaint the control
impl_paint ( 0, 0, impl_getGraphicsPeer() );
}
}
// protected method
void ProgressMonitor::impl_paint ( sal_Int32 nX, sal_Int32 nY, const css::uno::Reference< XGraphics > & rGraphics )
{
if (!rGraphics.is())
return;
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
// paint shadowed border around the progressmonitor
rGraphics->setLineColor ( PROGRESSMONITOR_LINECOLOR_SHADOW );
rGraphics->drawLine ( impl_getWidth()-1, impl_getHeight()-1, impl_getWidth()-1, nY );
rGraphics->drawLine ( impl_getWidth()-1, impl_getHeight()-1, nX , impl_getHeight()-1 );
rGraphics->setLineColor ( PROGRESSMONITOR_LINECOLOR_BRIGHT );
rGraphics->drawLine ( nX, nY, impl_getWidth(), nY );
rGraphics->drawLine ( nX, nY, nX , impl_getHeight() );
// Paint 3D-line
rGraphics->setLineColor ( PROGRESSMONITOR_LINECOLOR_SHADOW );
rGraphics->drawLine ( m_a3DLine.X, m_a3DLine.Y, m_a3DLine.X+m_a3DLine.Width, m_a3DLine.Y );
rGraphics->setLineColor ( PROGRESSMONITOR_LINECOLOR_BRIGHT );
rGraphics->drawLine ( m_a3DLine.X, m_a3DLine.Y+1, m_a3DLine.X+m_a3DLine.Width, m_a3DLine.Y+1 );
}
// private method
void ProgressMonitor::impl_recalcLayout ()
{
sal_Int32 nX_Button;
sal_Int32 nY_Button;
sal_Int32 nWidth_Button;
sal_Int32 nHeight_Button;
sal_Int32 nX_ProgressBar;
sal_Int32 nY_ProgressBar;
sal_Int32 nWidth_ProgressBar;
sal_Int32 nHeight_ProgressBar;
sal_Int32 nX_Text_Top;
sal_Int32 nY_Text_Top;
sal_Int32 nWidth_Text_Top;
sal_Int32 nHeight_Text_Top;
sal_Int32 nX_Topic_Top;
sal_Int32 nY_Topic_Top;
sal_Int32 nWidth_Topic_Top;
sal_Int32 nHeight_Topic_Top;
sal_Int32 nX_Text_Bottom;
sal_Int32 nY_Text_Bottom;
sal_Int32 nWidth_Text_Bottom;
sal_Int32 nHeight_Text_Bottom;
sal_Int32 nX_Topic_Bottom;
sal_Int32 nY_Topic_Bottom;
sal_Int32 nWidth_Topic_Bottom;
sal_Int32 nHeight_Topic_Bottom;
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
// get information about required place of child controls
css::uno::Reference< XLayoutConstrains > xTopicLayout_Top ( m_xTopic_Top , UNO_QUERY );
css::uno::Reference< XLayoutConstrains > xTextLayout_Top ( m_xText_Top , UNO_QUERY );
css::uno::Reference< XLayoutConstrains > xTopicLayout_Bottom ( m_xTopic_Bottom , UNO_QUERY );
css::uno::Reference< XLayoutConstrains > xTextLayout_Bottom ( m_xText_Bottom , UNO_QUERY );
css::uno::Reference< XLayoutConstrains > xButtonLayout ( m_xButton , UNO_QUERY );
Size aTopicSize_Top = xTopicLayout_Top->getPreferredSize ();
Size aTextSize_Top = xTextLayout_Top->getPreferredSize ();
Size aTopicSize_Bottom = xTopicLayout_Bottom->getPreferredSize ();
Size aTextSize_Bottom = xTextLayout_Bottom->getPreferredSize ();
Size aButtonSize = xButtonLayout->getPreferredSize ();
// calc position and size of child controls
// Button has preferred size!
nWidth_Button = aButtonSize.Width;
nHeight_Button = aButtonSize.Height;
// Left column before progressbar has preferred size and fixed position.
// But "Width" is oriented on left column below progressbar to!!! "max(...)"
nX_Topic_Top = PROGRESSMONITOR_FREEBORDER;
nY_Topic_Top = PROGRESSMONITOR_FREEBORDER;
nWidth_Topic_Top = std::max( aTopicSize_Top.Width, aTopicSize_Bottom.Width );
nHeight_Topic_Top = aTopicSize_Top.Height;
// Right column before progressbar has relative position to left column ...
// ... and a size as rest of dialog size!
nX_Text_Top = nX_Topic_Top+nWidth_Topic_Top+PROGRESSMONITOR_FREEBORDER;
nY_Text_Top = nY_Topic_Top;
nWidth_Text_Top = std::max ( aTextSize_Top.Width, aTextSize_Bottom.Width );
// Fix size of this column to minimum!
sal_Int32 nSummaryWidth = nWidth_Text_Top+nWidth_Topic_Top+(3*PROGRESSMONITOR_FREEBORDER);
if ( nSummaryWidth < PROGRESSMONITOR_DEFAULT_WIDTH )
nWidth_Text_Top = PROGRESSMONITOR_DEFAULT_WIDTH-nWidth_Topic_Top-(3*PROGRESSMONITOR_FREEBORDER);
// Fix size of column to maximum!
if ( nSummaryWidth > impl_getWidth() )
nWidth_Text_Top = impl_getWidth()-nWidth_Topic_Top-(3*PROGRESSMONITOR_FREEBORDER);
nHeight_Text_Top = nHeight_Topic_Top;
// Position of progressbar is relative to columns before.
// Progressbar.Width = Dialog.Width !!!
// Progressbar.Height = Button.Height
nX_ProgressBar = nX_Topic_Top;
nY_ProgressBar = nY_Topic_Top+nHeight_Topic_Top+PROGRESSMONITOR_FREEBORDER;
nWidth_ProgressBar = PROGRESSMONITOR_FREEBORDER+nWidth_Topic_Top+nWidth_Text_Top;
nHeight_ProgressBar = nHeight_Button;
// Oriented by left column before progressbar.
nX_Topic_Bottom = nX_Topic_Top;
nY_Topic_Bottom = nY_ProgressBar+nHeight_ProgressBar+PROGRESSMONITOR_FREEBORDER;
nWidth_Topic_Bottom = nWidth_Topic_Top;
nHeight_Topic_Bottom = aTopicSize_Bottom.Height;
// Oriented by right column before progressbar.
nX_Text_Bottom = nX_Topic_Bottom+nWidth_Topic_Bottom+PROGRESSMONITOR_FREEBORDER;
nY_Text_Bottom = nY_Topic_Bottom;
nWidth_Text_Bottom = nWidth_Text_Top;
nHeight_Text_Bottom = nHeight_Topic_Bottom;
// Oriented by progressbar.
nX_Button = nX_ProgressBar+nWidth_ProgressBar-nWidth_Button;
nY_Button = nY_Topic_Bottom+nHeight_Topic_Bottom+PROGRESSMONITOR_FREEBORDER;
// Calc offsets to center controls
sal_Int32 nDx;
sal_Int32 nDy;
nDx = ( (2*PROGRESSMONITOR_FREEBORDER)+nWidth_ProgressBar );
nDy = ( (6*PROGRESSMONITOR_FREEBORDER)+nHeight_Topic_Top+nHeight_ProgressBar+nHeight_Topic_Bottom+2+nHeight_Button );
// At this point use original dialog size to center controls!
nDx = (impl_getWidth ()/2)-(nDx/2);
nDy = (impl_getHeight()/2)-(nDy/2);
if ( nDx<0 )
{
nDx=0;
}
if ( nDy<0 )
{
nDy=0;
}
// Set new position and size on all controls
css::uno::Reference< XWindow > xRef_Topic_Top ( m_xTopic_Top , UNO_QUERY );
css::uno::Reference< XWindow > xRef_Text_Top ( m_xText_Top , UNO_QUERY );
css::uno::Reference< XWindow > xRef_Topic_Bottom ( m_xTopic_Bottom , UNO_QUERY );
css::uno::Reference< XWindow > xRef_Text_Bottom ( m_xText_Bottom , UNO_QUERY );
css::uno::Reference< XWindow > xRef_Button ( m_xButton , UNO_QUERY );
xRef_Topic_Top->setPosSize ( nDx+nX_Topic_Top , nDy+nY_Topic_Top , nWidth_Topic_Top , nHeight_Topic_Top , 15 );
xRef_Text_Top->setPosSize ( nDx+nX_Text_Top , nDy+nY_Text_Top , nWidth_Text_Top , nHeight_Text_Top , 15 );
xRef_Topic_Bottom->setPosSize ( nDx+nX_Topic_Bottom , nDy+nY_Topic_Bottom , nWidth_Topic_Bottom , nHeight_Topic_Bottom , 15 );
xRef_Text_Bottom->setPosSize ( nDx+nX_Text_Bottom , nDy+nY_Text_Bottom , nWidth_Text_Bottom , nHeight_Text_Bottom , 15 );
xRef_Button->setPosSize ( nDx+nX_Button , nDy+nY_Button , nWidth_Button , nHeight_Button , 15 );
m_xProgressBar->setPosSize( nDx+nX_ProgressBar, nDy+nY_ProgressBar, nWidth_ProgressBar, nHeight_ProgressBar, 15 );
m_a3DLine.X = nDx+nX_Topic_Top;
m_a3DLine.Y = nDy+nY_Topic_Bottom+nHeight_Topic_Bottom+(PROGRESSMONITOR_FREEBORDER/2);
m_a3DLine.Width = nWidth_ProgressBar;
m_a3DLine.Height = nHeight_ProgressBar;
// All childcontrols make an implicit repaint in setPosSize()!
// Make it also for this 3D-line ...
css::uno::Reference< XGraphics > xGraphics = impl_getGraphicsPeer ();
xGraphics->setLineColor ( PROGRESSMONITOR_LINECOLOR_SHADOW );
xGraphics->drawLine ( m_a3DLine.X, m_a3DLine.Y, m_a3DLine.X+m_a3DLine.Width, m_a3DLine.Y );
xGraphics->setLineColor ( PROGRESSMONITOR_LINECOLOR_BRIGHT );
xGraphics->drawLine ( m_a3DLine.X, m_a3DLine.Y+1, m_a3DLine.X+m_a3DLine.Width, m_a3DLine.Y+1 );
}
// private method
void ProgressMonitor::impl_rebuildFixedText ()
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
// Rebuild fixedtext before progress
// Rebuild left site of text
if (m_xTopic_Top.is())
{
OUStringBuffer aCollectString;
// Collect all topics from list and format text.
// "\n" MUST BE at the end of line!!! => Else ... topic and his text are not in the same line!!!
for (auto const & rSearchItem : maTextlist_Top)
{
aCollectString.append(rSearchItem.sTopic + "\n");
}
m_xTopic_Top->setText ( aCollectString.makeStringAndClear() );
}
// Rebuild right site of text
if (m_xText_Top.is())
{
OUStringBuffer aCollectString;
// Collect all topics from list and format text.
// "\n" MUST BE at the end of line!!! => Else ... topic and his text are not in the same line!!!
for (auto const & rSearchItem : maTextlist_Top)
{
aCollectString.append(rSearchItem.sText + "\n");
}
m_xText_Top->setText ( aCollectString.makeStringAndClear() );
}
// Rebuild fixedtext below progress
// Rebuild left site of text
if (m_xTopic_Bottom.is())
{
OUStringBuffer aCollectString;
// Collect all topics from list and format text.
// "\n" MUST BE at the end of line!!! => Else ... topic and his text are not in the same line!!!
for (auto const & rSearchItem : maTextlist_Bottom)
{
aCollectString.append(rSearchItem.sTopic + "\n");
}
m_xTopic_Bottom->setText ( aCollectString.makeStringAndClear() );
}
// Rebuild right site of text
if (!m_xText_Bottom.is())
return;
OUStringBuffer aCollectString;
// Collect all topics from list and format text.
// "\n" MUST BE at the end of line!!! => Else ... topic and his text are not in the same line!!!
for (auto const & rSearchItem : maTextlist_Bottom)
{
aCollectString.append(rSearchItem.sText + "\n");
}
m_xText_Bottom->setText ( aCollectString.makeStringAndClear() );
}
// private method
void ProgressMonitor::impl_cleanMemory ()
{
// Ready for multithreading
MutexGuard aGuard ( m_aMutex );
// Delete all of lists.
maTextlist_Top.clear();
maTextlist_Bottom.clear();
}
// private method
IMPL_TextlistItem* ProgressMonitor::impl_searchTopic ( std::u16string_view rTopic, bool bbeforeProgress )
{
// Get right textlist for following operations.
::std::vector< IMPL_TextlistItem >* pTextList;
if (bbeforeProgress)
{
pTextList = &maTextlist_Top;
}
else
{
pTextList = &maTextlist_Bottom;
}
// Search the topic in textlist.
size_t nPosition = 0;
size_t nCount = pTextList->size();
for ( nPosition = 0; nPosition < nCount; ++nPosition )
{
auto& rSearchItem = pTextList->at( nPosition );
if ( rSearchItem.sTopic == rTopic )
{
// We have found this topic... return a valid pointer.
return &rSearchItem;
}
}
// We haven't found this topic... return a nonvalid pointer.
return nullptr;
}
// debug methods
// addText, updateText
bool ProgressMonitor::impl_debug_checkParameter (
std::u16string_view rTopic,
std::u16string_view rText
) {
if ( rTopic.empty() ) return false; // ""
if ( rText.empty() ) return false; // ""
// Parameter OK ... return true.
return true;
}
// removeText
bool ProgressMonitor::impl_debug_checkParameter ( std::u16string_view rTopic )
{
if ( rTopic.empty() ) return false; // ""
// Parameter OK ... return true.
return true;
}
} // namespace unocontrols
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
stardiv_UnoControls_ProgressMonitor_get_implementation(
css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
{
return cppu::acquire(new unocontrols::ProgressMonitor(context));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */