LCOV - code coverage report
Current view: top level - reportdesign/source/ui/dlg - GroupsSorting.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 727 0.1 %
Date: 2015-06-13 12:38:46 Functions: 2 71 2.8 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "GroupsSorting.hxx"
      20             : #include <connectivity/dbtools.hxx>
      21             : #include <sot/exchange.hxx>
      22             : #include <svtools/editbrowsebox.hxx>
      23             : #include <svtools/imgdef.hxx>
      24             : #include <com/sun/star/beans/XPropertySet.hpp>
      25             : #include <com/sun/star/container/XContainerListener.hpp>
      26             : #include <com/sun/star/report/GroupOn.hpp>
      27             : #include <com/sun/star/sdbc/DataType.hpp>
      28             : 
      29             : #include <tools/debug.hxx>
      30             : #include "RptResId.hrc"
      31             : #include "rptui_slotid.hrc"
      32             : #include "ModuleHelper.hxx"
      33             : #include "helpids.hrc"
      34             : #include "GroupExchange.hxx"
      35             : #include "UITools.hxx"
      36             : #include "UndoActions.hxx"
      37             : #include "uistrings.hrc"
      38             : #include "ReportController.hxx"
      39             : #include "ColumnInfo.hxx"
      40             : 
      41             : #include <cppuhelper/implbase1.hxx>
      42             : #include <comphelper/property.hxx>
      43             : #include <vcl/msgbox.hxx>
      44             : #include <vcl/settings.hxx>
      45             : 
      46             : #include <algorithm>
      47             : 
      48             : #include <cppuhelper/bootstrap.hxx>
      49             : 
      50             : #define HANDLE_ID           0
      51             : #define FIELD_EXPRESSION    1
      52             : #define GROUPS_START_LEN    5
      53             : #define NO_GROUP            -1
      54             : 
      55             : namespace rptui
      56             : {
      57             : using namespace ::com::sun::star;
      58             : using namespace svt;
      59             : using namespace ::comphelper;
      60             : 
      61           0 :     void lcl_addToList_throw( ComboBoxControl& _rListBox, ::std::vector<ColumnInfo>& o_aColumnList,const uno::Reference< container::XNameAccess>& i_xColumns )
      62             :     {
      63           0 :         uno::Sequence< OUString > aEntries = i_xColumns->getElementNames();
      64           0 :         const OUString* pEntries = aEntries.getConstArray();
      65           0 :         sal_Int32 nEntries = aEntries.getLength();
      66           0 :         for ( sal_Int32 i = 0; i < nEntries; ++i, ++pEntries )
      67             :         {
      68           0 :             uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(*pEntries),uno::UNO_QUERY_THROW);
      69           0 :             OUString sLabel;
      70           0 :             if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) )
      71           0 :                 xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel;
      72           0 :             o_aColumnList.push_back( ColumnInfo(*pEntries,sLabel) );
      73           0 :             if ( !sLabel.isEmpty() )
      74           0 :                 _rListBox.InsertEntry( sLabel );
      75             :             else
      76           0 :                 _rListBox.InsertEntry( *pEntries );
      77           0 :         }
      78           0 :     }
      79             : 
      80             : /**
      81             :   * Separated out from OFieldExpressionControl to prevent collision of ref-counted base classes
      82             :   */
      83             : class OFieldExpressionControl;
      84           0 : class OFieldExpressionControlContainerListener : public ::cppu::WeakImplHelper1< container::XContainerListener >
      85             : {
      86             :     VclPtr<OFieldExpressionControl> mpParent;
      87             : public:
      88           0 :     OFieldExpressionControlContainerListener(OFieldExpressionControl* pParent) : mpParent(pParent) {}
      89             : 
      90             :     // XEventListener
      91             :     virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw( ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
      92             :     // XContainerListener
      93             :     virtual void SAL_CALL elementInserted(const ::com::sun::star::container::ContainerEvent& rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      94             :     virtual void SAL_CALL elementReplaced(const ::com::sun::star::container::ContainerEvent& rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      95             :     virtual void SAL_CALL elementRemoved(const ::com::sun::star::container::ContainerEvent& rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      96             : };
      97             : 
      98             : class OFieldExpressionControl : public ::svt::EditBrowseBox
      99             : {
     100             :     ::osl::Mutex                    m_aMutex;
     101             :     ::std::vector<sal_Int32>        m_aGroupPositions;
     102             :     ::std::vector<ColumnInfo>       m_aColumnInfo;
     103             :     VclPtr< ::svt::ComboBoxControl>  m_pComboCell;
     104             :     sal_Int32                       m_nDataPos;
     105             :     sal_Int32                       m_nCurrentPos;
     106             :     ImplSVEvent *                   m_nPasteEvent;
     107             :     ImplSVEvent *                   m_nDeleteEvent;
     108             :     VclPtr<OGroupsSortingDialog>    m_pParent;
     109             :     bool                            m_bIgnoreEvent;
     110             :     OFieldExpressionControlContainerListener aContainerListener;
     111             : 
     112             :     bool SaveModified(bool _bAppend);
     113             : 
     114             : public:
     115             :     OFieldExpressionControl(OGroupsSortingDialog* _pParentDialog, vcl::Window *_pParent);
     116             :     virtual ~OFieldExpressionControl();
     117             :     virtual void dispose() SAL_OVERRIDE;
     118             : 
     119             :     // XContainerListener
     120             :     void SAL_CALL elementInserted(const ::com::sun::star::container::ContainerEvent& rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception);
     121             :     void SAL_CALL elementRemoved(const ::com::sun::star::container::ContainerEvent& rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception);
     122             : 
     123             :     virtual Size GetOptimalSize() const SAL_OVERRIDE;
     124             : 
     125             :     void        fillColumns(const uno::Reference< container::XNameAccess>& _xColumns);
     126             :     void        lateInit();
     127             :     bool    IsDeleteAllowed( );
     128             :     void        DeleteRows();
     129             :     void        cut();
     130             :     void        copy();
     131             :     void        paste();
     132             : 
     133           0 :     inline sal_Int32   getGroupPosition(sal_Int32 _nRow) const { return _nRow != BROWSER_ENDOFSELECTION ? m_aGroupPositions[_nRow] : sal_Int32(NO_GROUP); }
     134             : 
     135           0 :     inline ::svt::ComboBoxControl*  getExpressionControl() const { return m_pComboCell; }
     136             : 
     137             :     /** returns the sequence with the selected groups
     138             :     */
     139             :     uno::Sequence<uno::Any> fillSelectedGroups();
     140             : 
     141             :     /** move groups given by _aGroups
     142             :     */
     143             :     void moveGroups(const uno::Sequence<uno::Any>& _aGroups,sal_Int32 _nRow,bool _bSelect = true);
     144             : 
     145             :     virtual bool CursorMoving(long nNewRow, sal_uInt16 nNewCol) SAL_OVERRIDE;
     146             :     using ::svt::EditBrowseBox::GetRowCount;
     147             : protected:
     148             :     virtual bool IsTabAllowed(bool bForward) const SAL_OVERRIDE;
     149             : 
     150             :     virtual void InitController( ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol ) SAL_OVERRIDE;
     151             :     virtual ::svt::CellController* GetController( long nRow, sal_uInt16 nCol ) SAL_OVERRIDE;
     152             :     virtual void PaintCell( OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColId ) const SAL_OVERRIDE;
     153             :     virtual bool SeekRow( long nRow ) SAL_OVERRIDE;
     154             :     virtual bool SaveModified() SAL_OVERRIDE;
     155             :     virtual OUString GetCellText( long nRow, sal_uInt16 nColId ) const SAL_OVERRIDE;
     156             :     virtual RowStatus GetRowStatus(long nRow) const SAL_OVERRIDE;
     157             : 
     158             :     virtual void KeyInput(const KeyEvent& rEvt) SAL_OVERRIDE;
     159             :     virtual void Command( const CommandEvent& rEvt ) SAL_OVERRIDE;
     160             : 
     161             :     // D&D
     162             :     virtual void     StartDrag( sal_Int8 nAction, const Point& rPosPixel ) SAL_OVERRIDE;
     163             :     virtual sal_Int8 AcceptDrop( const BrowserAcceptDropEvent& rEvt ) SAL_OVERRIDE;
     164             :     virtual sal_Int8 ExecuteDrop( const BrowserExecuteDropEvent& rEvt ) SAL_OVERRIDE;
     165             : 
     166             :     using BrowseBox::AcceptDrop;
     167             :     using BrowseBox::ExecuteDrop;
     168             : 
     169             : private:
     170             : 
     171             :     DECL_LINK( DelayedPaste, void* );
     172             :     DECL_LINK( CBChangeHdl,ComboBox*);
     173             : 
     174             :     void InsertRows( long nRow );
     175             : 
     176             : public:
     177             :     DECL_LINK( DelayedDelete, void* );
     178             : 
     179             : };
     180             : 
     181             : 
     182           0 : void OFieldExpressionControlContainerListener::disposing(const ::com::sun::star::lang::EventObject& ) throw( ::com::sun::star::uno::RuntimeException, std::exception )
     183           0 : {}
     184             : 
     185           0 : void OFieldExpressionControlContainerListener::elementInserted(const ::com::sun::star::container::ContainerEvent& rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception)
     186           0 : { mpParent->elementInserted(rEvent); }
     187             : 
     188           0 : void OFieldExpressionControlContainerListener::elementReplaced(const ::com::sun::star::container::ContainerEvent& ) throw(::com::sun::star::uno::RuntimeException, std::exception)
     189           0 : {}
     190             : 
     191           0 : void OFieldExpressionControlContainerListener::elementRemoved(const ::com::sun::star::container::ContainerEvent& rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception)
     192           0 : { mpParent->elementRemoved(rEvent); }
     193             : 
     194             : 
     195             : // class OFieldExpressionControl
     196           0 : OFieldExpressionControl::OFieldExpressionControl(OGroupsSortingDialog* _pParentDialog, vcl::Window *_pParent)
     197             :     :EditBrowseBox( _pParent, EditBrowseBoxFlags::NONE, WB_TABSTOP,
     198             :                     BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::AUTOSIZE_LASTCOL |
     199           0 :                               BrowserMode::KEEPHIGHLIGHT | BrowserMode::HLINES | BrowserMode::VLINES)
     200             :     ,m_aGroupPositions(GROUPS_START_LEN,-1)
     201             :     ,m_pComboCell(NULL)
     202             :     ,m_nDataPos(-1)
     203             :     ,m_nCurrentPos(-1)
     204             :     ,m_nPasteEvent(0)
     205             :     ,m_nDeleteEvent(0)
     206             :     ,m_pParent(_pParentDialog)
     207             :     ,m_bIgnoreEvent(false)
     208           0 :     ,aContainerListener(this)
     209             : {
     210           0 :     SetBorderStyle(WindowBorderStyle::MONO);
     211           0 : }
     212             : 
     213             : 
     214           0 : OFieldExpressionControl::~OFieldExpressionControl()
     215             : {
     216           0 :     disposeOnce();
     217           0 : }
     218             : 
     219             : 
     220           0 : void OFieldExpressionControl::dispose()
     221             : {
     222           0 :     aContainerListener.WeakImplHelper1::acquire();
     223           0 :     uno::Reference< report::XGroups > xGroups = m_pParent->getGroups();
     224           0 :     xGroups->removeContainerListener(&aContainerListener);
     225             : 
     226             :     // delete events from queue
     227           0 :     if( m_nPasteEvent )
     228           0 :         Application::RemoveUserEvent( m_nPasteEvent );
     229           0 :     if( m_nDeleteEvent )
     230           0 :         Application::RemoveUserEvent( m_nDeleteEvent );
     231             : 
     232           0 :     m_pComboCell.disposeAndClear();
     233           0 :     m_pParent.clear();
     234           0 :     ::svt::EditBrowseBox::dispose();
     235           0 : }
     236             : 
     237           0 : uno::Sequence<uno::Any> OFieldExpressionControl::fillSelectedGroups()
     238             : {
     239           0 :     uno::Sequence<uno::Any> aList;
     240           0 :     ::std::vector<uno::Any> vClipboardList;
     241           0 :     vClipboardList.reserve(GetSelectRowCount());
     242             : 
     243           0 :     uno::Reference<report::XGroups> xGroups = m_pParent->getGroups();
     244           0 :     sal_Int32 nCount = xGroups->getCount();
     245           0 :     if ( nCount >= 1 )
     246             :     {
     247           0 :         for( long nIndex=FirstSelectedRow(); nIndex >= 0 ; nIndex=NextSelectedRow() )
     248             :         {
     249             :             try
     250             :             {
     251           0 :                 if ( m_aGroupPositions[nIndex] != NO_GROUP )
     252             :                 {
     253           0 :                     uno::Reference< report::XGroup> xOrgGroup(xGroups->getByIndex(m_aGroupPositions[nIndex]),uno::UNO_QUERY);
     254             :                     /*uno::Reference< report::XGroup> xCopy = xGroups->createGroup();
     255             :                     ::comphelper::copyProperties(xOrgGroup.get(),xCopy.get());*/
     256           0 :                     vClipboardList.push_back( uno::makeAny(xOrgGroup) );
     257             :                 }
     258             :             }
     259           0 :             catch(uno::Exception&)
     260             :             {
     261             :                 OSL_FAIL("Can not access group!");
     262             :             }
     263             :         }
     264           0 :         if ( !vClipboardList.empty() )
     265           0 :             aList = uno::Sequence< uno::Any >(&vClipboardList[0], vClipboardList.size());
     266             :     }
     267           0 :     return aList;
     268             : }
     269             : 
     270           0 : void OFieldExpressionControl::StartDrag( sal_Int8 /*_nAction*/ , const Point& /*_rPosPixel*/ )
     271             : {
     272           0 :     if ( m_pParent && !m_pParent->isReadOnly( ) )
     273             :     {
     274           0 :         uno::Sequence<uno::Any> aClipboardList = fillSelectedGroups();
     275             : 
     276           0 :         if( aClipboardList.getLength() )
     277             :         {
     278           0 :             OGroupExchange* pData = new OGroupExchange(aClipboardList);
     279           0 :             uno::Reference< ::com::sun::star::datatransfer::XTransferable> xRef = pData;
     280           0 :             pData->StartDrag(this, DND_ACTION_MOVE );
     281           0 :         }
     282             :     }
     283           0 : }
     284             : 
     285           0 : sal_Int8 OFieldExpressionControl::AcceptDrop( const BrowserAcceptDropEvent& rEvt )
     286             : {
     287           0 :     sal_Int8 nAction = DND_ACTION_NONE;
     288           0 :     if ( IsEditing() )
     289             :     {
     290           0 :         sal_Int32 nPos = m_pComboCell->GetSelectEntryPos();
     291           0 :         if ( COMBOBOX_ENTRY_NOTFOUND != nPos || !m_pComboCell->GetText().isEmpty() )
     292           0 :             SaveModified();
     293           0 :         DeactivateCell();
     294             :     }
     295           0 :     if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) && m_pParent->getGroups()->getCount() > 1 && rEvt.GetWindow() == &GetDataWindow() )
     296             :     {
     297           0 :         nAction = DND_ACTION_MOVE;
     298             :     }
     299           0 :     return nAction;
     300             : }
     301             : 
     302           0 : sal_Int8 OFieldExpressionControl::ExecuteDrop( const BrowserExecuteDropEvent& rEvt )
     303             : {
     304           0 :     sal_Int8 nAction = DND_ACTION_NONE;
     305           0 :     if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) )
     306             :     {
     307           0 :         sal_Int32   nRow = GetRowAtYPosPixel(rEvt.maPosPixel.Y(), false);
     308           0 :         SetNoSelection();
     309             : 
     310           0 :         TransferableDataHelper aDropped( rEvt.maDropEvent.Transferable );
     311           0 :         uno::Any aDrop = aDropped.GetAny(OGroupExchange::getReportGroupId(), OUString());
     312           0 :         uno::Sequence< uno::Any > aGroups;
     313           0 :         aDrop >>= aGroups;
     314           0 :         if ( aGroups.getLength() )
     315             :         {
     316           0 :             moveGroups(aGroups,nRow);
     317           0 :             nAction = DND_ACTION_MOVE;
     318           0 :         }
     319             :     }
     320           0 :     return nAction;
     321             : }
     322             : 
     323           0 : void OFieldExpressionControl::moveGroups(const uno::Sequence<uno::Any>& _aGroups,sal_Int32 _nRow,bool _bSelect)
     324             : {
     325           0 :     if ( _aGroups.getLength() )
     326             :     {
     327           0 :         m_bIgnoreEvent = true;
     328             :         {
     329           0 :             sal_Int32 nRow = _nRow;
     330           0 :             const OUString sUndoAction(ModuleRes(RID_STR_UNDO_MOVE_GROUP));
     331           0 :             const UndoContext aUndoContext( m_pParent->m_pController->getUndoManager(), sUndoAction );
     332             : 
     333           0 :             uno::Reference< report::XGroups> xGroups = m_pParent->getGroups();
     334           0 :             const uno::Any* pIter = _aGroups.getConstArray();
     335           0 :             const uno::Any* pEnd  = pIter + _aGroups.getLength();
     336           0 :             for(;pIter != pEnd;++pIter)
     337             :             {
     338           0 :                 uno::Reference< report::XGroup> xGroup(*pIter,uno::UNO_QUERY);
     339           0 :                 if ( xGroup.is() )
     340             :                 {
     341           0 :                     uno::Sequence< beans::PropertyValue > aArgs(1);
     342           0 :                     aArgs[0].Name = PROPERTY_GROUP;
     343           0 :                     aArgs[0].Value <<= xGroup;
     344             :                     // we use this way to create undo actions
     345           0 :                     m_pParent->m_pController->executeChecked(SID_GROUP_REMOVE,aArgs);
     346           0 :                     aArgs.realloc(2);
     347           0 :                     if ( nRow > xGroups->getCount() )
     348           0 :                         nRow = xGroups->getCount();
     349           0 :                     if ( _bSelect )
     350           0 :                         SelectRow(nRow);
     351           0 :                     aArgs[1].Name = PROPERTY_POSITIONY;
     352           0 :                     aArgs[1].Value <<= nRow;
     353           0 :                     m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs);
     354           0 :                     ++nRow;
     355             :                 }
     356           0 :             }
     357             :         }
     358           0 :         m_bIgnoreEvent = false;
     359           0 :         Invalidate();
     360             :     }
     361           0 : }
     362             : 
     363           0 : void OFieldExpressionControl::fillColumns(const uno::Reference< container::XNameAccess>& _xColumns)
     364             : {
     365           0 :     m_pComboCell->Clear();
     366           0 :     if ( _xColumns.is() )
     367           0 :         lcl_addToList_throw(*m_pComboCell,m_aColumnInfo,_xColumns);
     368           0 : }
     369             : 
     370           0 : void OFieldExpressionControl::lateInit()
     371             : {
     372           0 :     uno::Reference< report::XGroups > xGroups = m_pParent->getGroups();
     373           0 :     sal_Int32 nGroupsCount = xGroups->getCount();
     374           0 :     m_aGroupPositions.resize(::std::max<sal_Int32>(nGroupsCount,sal_Int32(GROUPS_START_LEN)),NO_GROUP);
     375           0 :     ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin();
     376           0 :     for (sal_Int32 i = 0; i < nGroupsCount; ++i,++aIter)
     377           0 :         *aIter = i;
     378             : 
     379           0 :     if ( ColCount() == 0 )
     380             :     {
     381           0 :         vcl::Font aFont( GetDataWindow().GetFont() );
     382           0 :         aFont.SetWeight( WEIGHT_NORMAL );
     383           0 :         GetDataWindow().SetFont( aFont );
     384             : 
     385             :         // Font fuer die Ueberschriften auf Light setzen
     386           0 :         aFont = GetFont();
     387           0 :         aFont.SetWeight( WEIGHT_LIGHT );
     388           0 :         SetFont(aFont);
     389             : 
     390           0 :         InsertHandleColumn(static_cast<sal_uInt16>(GetTextWidth(OUString('0')) * 4)/*, sal_True */);
     391           0 :         InsertDataColumn( FIELD_EXPRESSION, OUString(ModuleRes(STR_RPT_EXPRESSION)), 100);
     392             : 
     393           0 :         m_pComboCell = VclPtr<ComboBoxControl>::Create( &GetDataWindow() );
     394           0 :         m_pComboCell->SetSelectHdl(LINK(this,OFieldExpressionControl,CBChangeHdl));
     395           0 :         m_pComboCell->SetHelpId(HID_RPT_FIELDEXPRESSION);
     396             : 
     397           0 :         Control* pControls[] = {m_pComboCell};
     398           0 :         for (size_t i = 0; i < sizeof(pControls)/sizeof(pControls[0]); ++i)
     399             :         {
     400           0 :             pControls[i]->SetGetFocusHdl(LINK(m_pParent, OGroupsSortingDialog, OnControlFocusGot));
     401           0 :             pControls[i]->SetLoseFocusHdl(LINK(m_pParent, OGroupsSortingDialog, OnControlFocusLost));
     402             :         }
     403             : 
     404             : 
     405             :         // set browse mode
     406             :         BrowserMode nMode(BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION  | BrowserMode::KEEPHIGHLIGHT |
     407           0 :                           BrowserMode::HLINES | BrowserMode::VLINES       | BrowserMode::AUTOSIZE_LASTCOL | BrowserMode::AUTO_VSCROLL | BrowserMode::AUTO_HSCROLL);
     408           0 :         if( m_pParent->isReadOnly() )
     409           0 :             nMode |= BrowserMode::HIDECURSOR;
     410           0 :         SetMode(nMode);
     411           0 :         xGroups->addContainerListener(&aContainerListener);
     412             :     }
     413             :     else
     414             :         // not the first call
     415           0 :         RowRemoved(0, GetRowCount());
     416             : 
     417           0 :     RowInserted(0, m_aGroupPositions.size(), true);
     418           0 : }
     419             : 
     420             : 
     421           0 : IMPL_LINK( OFieldExpressionControl, CBChangeHdl, ComboBox*, /*pComboBox*/ )
     422             : {
     423             : 
     424           0 :     SaveModified();
     425           0 :     return 0L;
     426             : }
     427             : 
     428             : 
     429           0 : bool OFieldExpressionControl::IsTabAllowed(bool /*bForward*/) const
     430             : {
     431           0 :     return false;
     432             : }
     433             : 
     434             : 
     435           0 : bool OFieldExpressionControl::SaveModified()
     436             : {
     437           0 :     return SaveModified(true);
     438             : }
     439             : 
     440           0 : bool OFieldExpressionControl::SaveModified(bool _bAppendRow)
     441             : {
     442           0 :     sal_Int32 nRow = GetCurRow();
     443           0 :     if ( nRow != BROWSER_ENDOFSELECTION )
     444             :     {
     445             :         try
     446             :         {
     447           0 :             bool bAppend = false;
     448           0 :             uno::Reference< report::XGroup> xGroup;
     449           0 :             if ( m_aGroupPositions[nRow] == NO_GROUP )
     450             :             {
     451           0 :                 bAppend = true;
     452           0 :                 OUString sUndoAction(ModuleRes(RID_STR_UNDO_APPEND_GROUP));
     453           0 :                 m_pParent->m_pController->getUndoManager().EnterListAction( sUndoAction, OUString() );
     454           0 :                 xGroup = m_pParent->getGroups()->createGroup();
     455           0 :                 xGroup->setHeaderOn(sal_True);
     456             : 
     457           0 :                 uno::Sequence< beans::PropertyValue > aArgs(2);
     458           0 :                 aArgs[0].Name = PROPERTY_GROUP;
     459           0 :                 aArgs[0].Value <<= xGroup;
     460             :                 // find position where to insert the new group
     461           0 :                 sal_Int32 nGroupPos = 0;
     462           0 :                 ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin();
     463           0 :                 ::std::vector<sal_Int32>::iterator aEnd  = m_aGroupPositions.begin() + nRow;
     464           0 :                 for(;aIter != aEnd;++aIter)
     465           0 :                     if ( *aIter != NO_GROUP )
     466           0 :                         nGroupPos = *aIter + 1;
     467           0 :                 aArgs[1].Name = PROPERTY_POSITIONY;
     468           0 :                 aArgs[1].Value <<= nGroupPos;
     469           0 :                 m_bIgnoreEvent = true;
     470           0 :                 m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs);
     471           0 :                 m_bIgnoreEvent = false;
     472             :                 OSL_ENSURE(*aIter == NO_GROUP ,"Illegal iterator!");
     473           0 :                 *aIter++ = nGroupPos;
     474             : 
     475           0 :                 aEnd  = m_aGroupPositions.end();
     476           0 :                 for(;aIter != aEnd;++aIter)
     477           0 :                     if ( *aIter != NO_GROUP )
     478           0 :                         ++*aIter;
     479             :             }
     480             :             else
     481           0 :                 xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
     482           0 :             if ( xGroup.is() )
     483             :             {
     484           0 :                 sal_Int32 nPos = m_pComboCell->GetSelectEntryPos();
     485           0 :                 OUString sExpression;
     486           0 :                 if ( COMBOBOX_ENTRY_NOTFOUND == nPos )
     487           0 :                     sExpression = m_pComboCell->GetText();
     488             :                 else
     489             :                 {
     490           0 :                     sExpression = m_aColumnInfo[nPos].sColumnName;
     491             :                 }
     492           0 :                 xGroup->setExpression( sExpression );
     493             : 
     494           0 :                 ::rptui::adjustSectionName(xGroup,nPos);
     495             : 
     496           0 :                 if ( bAppend )
     497           0 :                     m_pParent->m_pController->getUndoManager().LeaveListAction();
     498             :             }
     499             : 
     500           0 :             if ( Controller() )
     501           0 :                 Controller()->ClearModified();
     502           0 :             if ( _bAppendRow && GetRowCount() == m_pParent->getGroups()->getCount() )
     503             :             {
     504           0 :                 RowInserted( GetRowCount()-1);
     505           0 :                 m_aGroupPositions.push_back(NO_GROUP);
     506             :             }
     507             : 
     508           0 :             GoToRow(nRow);
     509           0 :             m_pParent->DisplayData(nRow);
     510             :         }
     511           0 :         catch(uno::Exception&)
     512             :         {
     513             :             OSL_FAIL("OFieldExpressionControl::SaveModified: Exception caught!");
     514             :         }
     515             :     }
     516             : 
     517           0 :     return true;
     518             : }
     519             : 
     520           0 : OUString OFieldExpressionControl::GetCellText( long nRow, sal_uInt16 /*nColId*/ ) const
     521             : {
     522           0 :     OUString sText;
     523           0 :     if ( nRow != BROWSER_ENDOFSELECTION && m_aGroupPositions[nRow] != NO_GROUP )
     524             :     {
     525             :         try
     526             :         {
     527           0 :             uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
     528           0 :             OUString sExpression = xGroup->getExpression();
     529             : 
     530           0 :             for(::std::vector<ColumnInfo>::const_iterator aIter = m_aColumnInfo.begin(); aIter != m_aColumnInfo.end();++aIter)
     531             :             {
     532           0 :                 if ( aIter->sColumnName == sExpression )
     533             :                 {
     534           0 :                     if ( !aIter->sLabel.isEmpty() )
     535           0 :                         sExpression = aIter->sLabel;
     536           0 :                     break;
     537             :                 }
     538             :             }
     539           0 :             sText = sExpression;
     540             :         }
     541           0 :         catch (const uno::Exception&)
     542             :         {
     543             :             OSL_FAIL("Exception caught while getting expression value from the group");
     544             :         }
     545             :     }
     546           0 :     return sText;
     547             : }
     548             : 
     549             : 
     550           0 : void OFieldExpressionControl::InitController( CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColumnId )
     551             : {
     552             : 
     553           0 :     m_pComboCell->SetText( GetCellText( nRow, nColumnId ) );
     554           0 : }
     555             : 
     556           0 : bool OFieldExpressionControl::CursorMoving(long nNewRow, sal_uInt16 nNewCol)
     557             : {
     558             : 
     559           0 :     if (!EditBrowseBox::CursorMoving(nNewRow, nNewCol))
     560           0 :         return false;
     561           0 :     m_nDataPos = nNewRow;
     562           0 :     long nOldDataPos = GetCurRow();
     563           0 :     InvalidateStatusCell( m_nDataPos );
     564           0 :     InvalidateStatusCell( nOldDataPos );
     565             : 
     566           0 :     m_pParent->SaveData( nOldDataPos );
     567           0 :     m_pParent->DisplayData( m_nDataPos );
     568           0 :     return true;
     569             : }
     570             : 
     571           0 : CellController* OFieldExpressionControl::GetController( long /*nRow*/, sal_uInt16 /*nColumnId*/ )
     572             : {
     573           0 :     ComboBoxCellController* pCellController = new ComboBoxCellController( m_pComboCell );
     574           0 :     pCellController->GetComboBox().SetReadOnly(!m_pParent->m_pController->isEditable());
     575           0 :     return pCellController;
     576             : }
     577             : 
     578             : 
     579           0 : bool OFieldExpressionControl::SeekRow( long _nRow )
     580             : {
     581             :     // die Basisklasse braucht den Aufruf, da sie sich dort merkt, welche Zeile gepainted wird
     582           0 :     EditBrowseBox::SeekRow(_nRow);
     583           0 :     m_nCurrentPos = _nRow;
     584           0 :     return true;
     585             : }
     586             : 
     587             : 
     588           0 : void OFieldExpressionControl::PaintCell( OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId ) const
     589             : {
     590           0 :     OUString aText  =GetCellText( m_nCurrentPos, nColumnId );
     591             : 
     592           0 :     Point aPos( rRect.TopLeft() );
     593           0 :     Size aTextSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight() );
     594             : 
     595           0 :     if( aPos.X() < rRect.Left() || aPos.X() + aTextSize.Width() > rRect.Right() ||
     596           0 :         aPos.Y() < rRect.Top() || aPos.Y() + aTextSize.Height() > rRect.Bottom() )
     597           0 :         rDev.SetClipRegion(vcl::Region(rRect));
     598             : 
     599           0 :     rDev.DrawText( aPos, aText );
     600             : 
     601           0 :     if( rDev.IsClipRegion() )
     602           0 :         rDev.SetClipRegion();
     603           0 : }
     604             : 
     605           0 : EditBrowseBox::RowStatus OFieldExpressionControl::GetRowStatus(long nRow) const
     606             : {
     607           0 :     if (nRow >= 0 && nRow == m_nDataPos)
     608           0 :         return EditBrowseBox::CURRENT;
     609           0 :     if ( nRow != BROWSER_ENDOFSELECTION && nRow < static_cast<long>(m_aGroupPositions.size()) && m_aGroupPositions[nRow] != NO_GROUP )
     610             :     {
     611             :         try
     612             :         {
     613           0 :             uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
     614           0 :             return (xGroup->getHeaderOn() || xGroup->getFooterOn())? EditBrowseBox::HEADERFOOTER : EditBrowseBox::CLEAN;
     615             :         }
     616           0 :         catch(uno::Exception&)
     617             :         {
     618             :             OSL_FAIL("Exception cathced while try to get a group!");
     619             :         }
     620             :     }
     621           0 :     return EditBrowseBox::CLEAN;
     622             : }
     623             : 
     624             : // XContainerListener
     625             : 
     626           0 : void SAL_CALL OFieldExpressionControl::elementInserted(const container::ContainerEvent& evt) throw(uno::RuntimeException, std::exception)
     627             : {
     628           0 :     if ( m_bIgnoreEvent )
     629           0 :         return;
     630           0 :     SolarMutexGuard aSolarGuard;
     631           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     632           0 :     sal_Int32 nGroupPos = 0;
     633           0 :     if ( evt.Accessor >>= nGroupPos )
     634             :     {
     635           0 :         if ( nGroupPos >= GetRowCount() )
     636             :         {
     637           0 :             sal_Int32 nAddedRows = nGroupPos - GetRowCount();
     638           0 :             RowInserted(nAddedRows);
     639           0 :             for (sal_Int32 i = 0; i < nAddedRows; ++i)
     640           0 :                 m_aGroupPositions.push_back(NO_GROUP);
     641           0 :             m_aGroupPositions[nGroupPos] = nGroupPos;
     642             :         }
     643             :         else
     644             :         {
     645           0 :             ::std::vector<sal_Int32>::iterator aFind = m_aGroupPositions.begin()+ nGroupPos;
     646           0 :             if ( aFind == m_aGroupPositions.end() )
     647           0 :                 aFind = ::std::find(m_aGroupPositions.begin(),m_aGroupPositions.end(),NO_GROUP);
     648             : 
     649           0 :             if ( aFind != m_aGroupPositions.end() )
     650             :             {
     651           0 :                 if ( *aFind != NO_GROUP )
     652           0 :                     aFind = m_aGroupPositions.insert(aFind,nGroupPos);
     653             :                 else
     654           0 :                     *aFind = nGroupPos;
     655             : 
     656           0 :                 ::std::vector<sal_Int32>::iterator aEnd  = m_aGroupPositions.end();
     657           0 :                 for(++aFind;aFind != aEnd;++aFind)
     658           0 :                     if ( *aFind != NO_GROUP )
     659           0 :                         ++*aFind;
     660             :             }
     661             :         }
     662           0 :         Invalidate();
     663           0 :     }
     664             : }
     665             : 
     666           0 : void SAL_CALL OFieldExpressionControl::elementRemoved(const container::ContainerEvent& evt) throw(uno::RuntimeException, std::exception)
     667             : {
     668           0 :     SolarMutexGuard aSolarGuard;
     669           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     670             : 
     671           0 :     if ( m_bIgnoreEvent )
     672           0 :         return;
     673             : 
     674           0 :     sal_Int32 nGroupPos = 0;
     675           0 :     if ( evt.Accessor >>= nGroupPos )
     676             :     {
     677           0 :         ::std::vector<sal_Int32>::iterator aFind = ::std::find(m_aGroupPositions.begin(),m_aGroupPositions.end(),nGroupPos);
     678           0 :         if ( aFind != m_aGroupPositions.end() )
     679             :         {
     680           0 :             *aFind = NO_GROUP;
     681           0 :             ::std::vector<sal_Int32>::iterator aEnd  = m_aGroupPositions.end();
     682           0 :             for(++aFind;aFind != aEnd;++aFind)
     683           0 :                 if ( *aFind != NO_GROUP )
     684           0 :                     --*aFind;
     685           0 :             Invalidate();
     686             :         }
     687           0 :     }
     688             : }
     689             : 
     690           0 : bool OFieldExpressionControl::IsDeleteAllowed( )
     691             : {
     692           0 :     return !m_pParent->isReadOnly() && GetSelectRowCount() > 0;
     693             : }
     694             : 
     695           0 : void OFieldExpressionControl::KeyInput( const KeyEvent& rEvt )
     696             : {
     697           0 :     if (IsDeleteAllowed())
     698             :     {
     699           0 :         if (rEvt.GetKeyCode().GetCode() == KEY_DELETE &&    // Delete rows
     700           0 :             !rEvt.GetKeyCode().IsShift() &&
     701           0 :             !rEvt.GetKeyCode().IsMod1())
     702             :         {
     703           0 :             DeleteRows();
     704           0 :             return;
     705             :         }
     706             :     }
     707           0 :     EditBrowseBox::KeyInput(rEvt);
     708             : }
     709             : 
     710           0 : void OFieldExpressionControl::Command(const CommandEvent& rEvt)
     711             : {
     712           0 :     switch (rEvt.GetCommand())
     713             :     {
     714             :         case CommandEventId::ContextMenu:
     715             :         {
     716           0 :             if (!rEvt.IsMouseEvent())
     717             :             {
     718           0 :                 EditBrowseBox::Command(rEvt);
     719           0 :                 return;
     720             :             }
     721             : 
     722           0 :             sal_uInt16 nColId = GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X());
     723             : 
     724           0 :             if ( nColId == HANDLE_ID )
     725             :             {
     726           0 :                 PopupMenu aContextMenu(ModuleRes(RID_GROUPSROWPOPUPMENU));
     727           0 :                 bool bEnable = false;
     728           0 :                 long nIndex = FirstSelectedRow();
     729           0 :                 while( nIndex >= 0 && !bEnable )
     730             :                 {
     731           0 :                     if ( m_aGroupPositions[nIndex] != NO_GROUP )
     732           0 :                         bEnable = true;
     733           0 :                     nIndex = NextSelectedRow();
     734             :                 }
     735           0 :                 aContextMenu.EnableItem( SID_DELETE, IsDeleteAllowed() && bEnable );
     736           0 :                 switch (aContextMenu.Execute(this, rEvt.GetMousePosPixel()))
     737             :                 {
     738             :                     case SID_CUT:
     739           0 :                         cut();
     740           0 :                         break;
     741             :                     case SID_COPY:
     742           0 :                         copy();
     743           0 :                         break;
     744             :                     case SID_PASTE:
     745           0 :                         paste();
     746           0 :                         break;
     747             : 
     748             :                     case SID_DELETE:
     749           0 :                         if( m_nDeleteEvent )
     750           0 :                             Application::RemoveUserEvent( m_nDeleteEvent );
     751           0 :                         m_nDeleteEvent = Application::PostUserEvent( LINK(this, OFieldExpressionControl, DelayedDelete), NULL, true );
     752           0 :                         break;
     753             :                     default:
     754           0 :                         break;
     755           0 :                 }
     756             :             }
     757             :             // run through
     758             :         }
     759             :         default:
     760           0 :             EditBrowseBox::Command(rEvt);
     761             :     }
     762             : 
     763             : }
     764             : 
     765           0 : void OFieldExpressionControl::DeleteRows()
     766             : {
     767             : 
     768           0 :     bool bIsEditing = IsEditing();
     769           0 :     if (bIsEditing)
     770             :     {
     771           0 :         DeactivateCell();
     772             :     }
     773           0 :     long nIndex = FirstSelectedRow();
     774           0 :     if (nIndex == -1)
     775             :     {
     776           0 :         nIndex = GetCurRow();
     777             :     }
     778           0 :     bool bFirstTime = true;
     779             : 
     780           0 :     long nOldDataPos = nIndex;
     781           0 :     uno::Sequence< beans::PropertyValue > aArgs(1);
     782           0 :     aArgs[0].Name = PROPERTY_GROUP;
     783           0 :     m_bIgnoreEvent = true;
     784           0 :     while( nIndex >= 0 )
     785             :     {
     786           0 :         if ( m_aGroupPositions[nIndex] != NO_GROUP )
     787             :         {
     788           0 :             if ( bFirstTime )
     789             :             {
     790           0 :                 bFirstTime = false;
     791           0 :                 OUString sUndoAction(ModuleRes(RID_STR_UNDO_REMOVE_SELECTION));
     792           0 :                 m_pParent->m_pController->getUndoManager().EnterListAction( sUndoAction, OUString() );
     793             :             }
     794             : 
     795           0 :             sal_Int32 nGroupPos = m_aGroupPositions[nIndex];
     796           0 :             uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(nGroupPos);
     797           0 :             aArgs[0].Value <<= xGroup;
     798             :             // we use this way to create undo actions
     799           0 :             m_pParent->m_pController->executeChecked(SID_GROUP_REMOVE,aArgs);
     800             : 
     801           0 :             ::std::vector<sal_Int32>::iterator aFind = ::std::find(m_aGroupPositions.begin(),m_aGroupPositions.end(),nGroupPos);
     802           0 :             if (aFind != m_aGroupPositions.end())
     803             :             {
     804           0 :                 *aFind = NO_GROUP;
     805           0 :                 ::std::vector<sal_Int32>::iterator aEnd  = m_aGroupPositions.end();
     806           0 :                 for(++aFind;aFind != aEnd;++aFind)
     807           0 :                     if ( *aFind != NO_GROUP )
     808           0 :                         --*aFind;
     809           0 :             }
     810             :         }
     811           0 :         nIndex = NextSelectedRow();
     812             :     }
     813             : 
     814           0 :     if ( !bFirstTime )
     815           0 :         m_pParent->m_pController->getUndoManager().LeaveListAction();
     816             : 
     817           0 :     m_nDataPos = GetCurRow();
     818           0 :     InvalidateStatusCell( nOldDataPos );
     819           0 :     InvalidateStatusCell( m_nDataPos );
     820           0 :     ActivateCell();
     821           0 :     m_pParent->DisplayData( m_nDataPos );
     822           0 :     m_bIgnoreEvent = false;
     823           0 :     Invalidate();
     824           0 : }
     825             : 
     826             : 
     827           0 : void OFieldExpressionControl::cut()
     828             : {
     829           0 :     copy();
     830           0 :     DeleteRows();
     831           0 : }
     832             : 
     833             : 
     834           0 : void OFieldExpressionControl::copy()
     835             : {
     836             : 
     837             :     // set to the right row and save it
     838           0 :     m_pParent->SaveData( m_nDataPos );
     839             : 
     840           0 :     uno::Sequence<uno::Any> aClipboardList = fillSelectedGroups();
     841             : 
     842           0 :     if( aClipboardList.getLength() )
     843             :     {
     844           0 :         OGroupExchange* pData = new OGroupExchange(aClipboardList);
     845           0 :         uno::Reference< ::com::sun::star::datatransfer::XTransferable> xRef = pData;
     846           0 :         pData->CopyToClipboard(GetParent());
     847           0 :     }
     848           0 : }
     849             : 
     850             : 
     851           0 : void OFieldExpressionControl::paste()
     852             : {
     853           0 :     TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
     854           0 :     if(aTransferData.HasFormat(OGroupExchange::getReportGroupId()))
     855             :     {
     856           0 :         if( m_nPasteEvent )
     857           0 :             Application::RemoveUserEvent( m_nPasteEvent );
     858           0 :         m_nPasteEvent = Application::PostUserEvent( LINK(this, OFieldExpressionControl, DelayedPaste), NULL, true );
     859           0 :     }
     860           0 : }
     861             : 
     862           0 : IMPL_LINK_NOARG( OFieldExpressionControl, DelayedPaste )
     863             : {
     864           0 :     m_nPasteEvent = 0;
     865             : 
     866           0 :     sal_Int32 nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : GetCurRow();
     867             : 
     868           0 :     InsertRows( nPastePosition );
     869           0 :     SetNoSelection();
     870           0 :     GoToRow( nPastePosition );
     871             : 
     872           0 :     return 0;
     873             : }
     874             : 
     875           0 : IMPL_LINK_NOARG( OFieldExpressionControl, DelayedDelete )
     876             : {
     877           0 :     m_nDeleteEvent = 0;
     878           0 :     DeleteRows();
     879           0 :     return 0;
     880             : }
     881             : 
     882           0 : void OFieldExpressionControl::InsertRows( long nRow )
     883             : {
     884             : 
     885           0 :     sal_Int32 nSize = 0;
     886             : 
     887             :     // get rows from clipboard
     888           0 :     TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
     889           0 :     if(aTransferData.HasFormat(OGroupExchange::getReportGroupId()))
     890             :     {
     891           0 :         datatransfer::DataFlavor aFlavor;
     892           0 :         SotExchange::GetFormatDataFlavor(OGroupExchange::getReportGroupId(), aFlavor);
     893           0 :         uno::Sequence< uno::Any > aGroups;
     894             : 
     895           0 :         if ((aTransferData.GetAny(aFlavor, OUString()) >>= aGroups) && aGroups.getLength())
     896             :         {
     897           0 :             m_bIgnoreEvent = false;
     898             :             {
     899           0 :                 const OUString sUndoAction(ModuleRes(RID_STR_UNDO_APPEND_GROUP));
     900           0 :                 const UndoContext aUndoContext( m_pParent->m_pController->getUndoManager(), sUndoAction );
     901             : 
     902           0 :                 uno::Reference<report::XGroups> xGroups = m_pParent->getGroups();
     903           0 :                 sal_Int32 nGroupPos = 0;
     904           0 :                 ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin();
     905           0 :                 ::std::vector<sal_Int32>::size_type nRowPos = static_cast< ::std::vector<sal_Int32>::size_type >(nRow);
     906           0 :                 if ( nRowPos < m_aGroupPositions.size() )
     907             :                 {
     908           0 :                     ::std::vector<sal_Int32>::iterator aEnd  = m_aGroupPositions.begin() + nRowPos;
     909           0 :                     for(;aIter != aEnd;++aIter)
     910             :                     {
     911           0 :                         if ( *aIter != NO_GROUP )
     912           0 :                             nGroupPos = *aIter;
     913             :                     }
     914             :                 }
     915           0 :                 for(sal_Int32 i=0;i < aGroups.getLength();++i,++nSize)
     916             :                 {
     917           0 :                     uno::Sequence< beans::PropertyValue > aArgs(2);
     918           0 :                     aArgs[0].Name = PROPERTY_GROUP;
     919           0 :                     aArgs[0].Value = aGroups[i];
     920           0 :                     aArgs[1].Name = PROPERTY_POSITIONY;
     921           0 :                     aArgs[1].Value <<= nGroupPos;
     922           0 :                     m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs);
     923             : 
     924           0 :                     ::std::vector<sal_Int32>::iterator aInsertPos = m_aGroupPositions.insert(aIter,nGroupPos);
     925           0 :                     ++aInsertPos;
     926           0 :                     aIter = aInsertPos;
     927           0 :                     ::std::vector<sal_Int32>::iterator aEnd  = m_aGroupPositions.end();
     928           0 :                     for(;aInsertPos != aEnd;++aInsertPos)
     929           0 :                         if ( *aInsertPos != NO_GROUP )
     930           0 :                             ++*aInsertPos;
     931           0 :                 }
     932             :             }
     933           0 :             m_bIgnoreEvent = true;
     934           0 :         }
     935             :     }
     936             : 
     937           0 :     RowInserted( nRow, nSize, true );
     938           0 : }
     939             : 
     940           0 : Size OFieldExpressionControl::GetOptimalSize() const
     941             : {
     942           0 :     return LogicToPixel(Size(106, 75), MAP_APPFONT);
     943             : }
     944             : 
     945             : // class OGroupsSortingDialog
     946           0 : OGroupsSortingDialog::OGroupsSortingDialog(vcl::Window* _pParent, bool _bReadOnly,
     947             :                                            OReportController* _pController)
     948             :     : FloatingWindow(_pParent, "FloatingSort", "modules/dbreport/ui/floatingsort.ui")
     949             :     , OPropertyChangeListener(m_aMutex)
     950             :     , m_pController(_pController)
     951             :     , m_pCurrentGroupListener(NULL)
     952           0 :     , m_xGroups(m_pController->getReportDefinition()->getGroups())
     953           0 :     , m_bReadOnly(_bReadOnly)
     954             : {
     955           0 :     get(m_pToolBox, "toolbox");
     956           0 :     m_nMoveUpId = m_pToolBox->GetItemId(0);
     957           0 :     m_nMoveDownId = m_pToolBox->GetItemId(1);
     958           0 :     m_nDeleteId = m_pToolBox->GetItemId(2);
     959           0 :     get(m_pOrderLst, "sorting");
     960           0 :     get(m_pHeaderLst, "header");
     961           0 :     get(m_pFooterLst, "footer");
     962           0 :     get(m_pGroupOnLst, "group");
     963           0 :     get(m_pGroupIntervalEd, "interval");
     964           0 :     get(m_pKeepTogetherLst, "keep");
     965           0 :     get(m_pHelpWindow, "helptext");
     966           0 :     m_pHelpWindow->set_height_request(GetTextHeight() * 4);
     967           0 :     get(m_pProperties, "properties");
     968           0 :     m_pFieldExpression = VclPtr<OFieldExpressionControl>::Create(this, get<vcl::Window>("box"));
     969           0 :     m_pFieldExpression->set_hexpand(true);
     970           0 :     m_pFieldExpression->set_vexpand(true);
     971             : 
     972           0 :     Control* pControlsLst[] = { m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pKeepTogetherLst, m_pOrderLst, m_pGroupIntervalEd};
     973           0 :     for (size_t i = 0; i < sizeof (pControlsLst) / sizeof (pControlsLst[0]); ++i)
     974             :     {
     975           0 :         pControlsLst[i]->SetGetFocusHdl(LINK(this, OGroupsSortingDialog, OnControlFocusGot));
     976           0 :         pControlsLst[i]->SetLoseFocusHdl(LINK(this, OGroupsSortingDialog, OnControlFocusLost));
     977           0 :         pControlsLst[i]->Show(true);
     978             :     }
     979             : 
     980           0 :     for (size_t i = 0; i < (sizeof (pControlsLst) / sizeof (pControlsLst[0])) - 1; ++i)
     981           0 :         static_cast<ListBox*>(pControlsLst[i])->SetSelectHdl(LINK(this,OGroupsSortingDialog,LBChangeHdl));
     982             : 
     983           0 :     m_pReportListener = new OPropertyChangeMultiplexer(this,m_pController->getReportDefinition().get());
     984           0 :     m_pReportListener->addProperty(PROPERTY_COMMAND);
     985           0 :     m_pReportListener->addProperty(PROPERTY_COMMANDTYPE);
     986             : 
     987           0 :     m_pFieldExpression->lateInit();
     988           0 :     fillColumns();
     989           0 :     m_pFieldExpression->Show();
     990             : 
     991           0 :     m_pHelpWindow->SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
     992             : 
     993           0 :     m_pToolBox->SetStyle(m_pToolBox->GetStyle()|WB_LINESPACING);
     994           0 :     m_pToolBox->SetSelectHdl(LINK(this, OGroupsSortingDialog, OnFormatAction));
     995             : 
     996           0 :     checkButtons(0);
     997             : 
     998           0 :     Show();
     999           0 : }
    1000             : 
    1001           0 : OGroupsSortingDialog::~OGroupsSortingDialog()
    1002             : {
    1003           0 :     disposeOnce();
    1004           0 : }
    1005             : 
    1006           0 : void OGroupsSortingDialog::dispose()
    1007             : {
    1008           0 :     m_xColumns.clear();
    1009           0 :     m_pReportListener->dispose();
    1010           0 :     if ( m_pCurrentGroupListener.is() )
    1011           0 :         m_pCurrentGroupListener->dispose();
    1012           0 :     m_pToolBox.clear();
    1013           0 :     m_pProperties.clear();
    1014           0 :     m_pOrderLst.clear();
    1015           0 :     m_pHeaderLst.clear();
    1016           0 :     m_pFooterLst.clear();
    1017           0 :     m_pGroupOnLst.clear();
    1018           0 :     m_pGroupIntervalEd.clear();
    1019           0 :     m_pKeepTogetherLst.clear();
    1020           0 :     m_pHelpWindow.clear();
    1021           0 :     m_pFieldExpression.disposeAndClear();
    1022           0 :     FloatingWindow::dispose();
    1023           0 : }
    1024             : 
    1025           0 : void OGroupsSortingDialog::UpdateData( )
    1026             : {
    1027           0 :     m_pFieldExpression->Invalidate();
    1028           0 :     long nCurRow = m_pFieldExpression->GetCurRow();
    1029           0 :     m_pFieldExpression->DeactivateCell();
    1030           0 :     m_pFieldExpression->ActivateCell(nCurRow, m_pFieldExpression->GetCurColumnId());
    1031           0 :     DisplayData(nCurRow);
    1032           0 : }
    1033             : 
    1034           0 : void OGroupsSortingDialog::DisplayData( sal_Int32 _nRow )
    1035             : {
    1036           0 :     sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(_nRow);
    1037           0 :     bool bEmpty = nGroupPos == NO_GROUP;
    1038           0 :     m_pProperties->Enable(!bEmpty);
    1039             : 
    1040           0 :     checkButtons(_nRow);
    1041             : 
    1042           0 :     if ( m_pCurrentGroupListener.is() )
    1043           0 :         m_pCurrentGroupListener->dispose();
    1044           0 :     m_pCurrentGroupListener = NULL;
    1045           0 :     if ( !bEmpty && nGroupPos != NO_GROUP )
    1046             :     {
    1047           0 :         uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);
    1048             : 
    1049           0 :         m_pCurrentGroupListener = new OPropertyChangeMultiplexer(this,xGroup.get());
    1050           0 :         m_pCurrentGroupListener->addProperty(PROPERTY_HEADERON);
    1051           0 :         m_pCurrentGroupListener->addProperty(PROPERTY_FOOTERON);
    1052             : 
    1053           0 :         displayGroup(xGroup);
    1054             :     }
    1055           0 : }
    1056             : 
    1057           0 : void OGroupsSortingDialog::SaveData( sal_Int32 _nRow)
    1058             : {
    1059           0 :     sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(_nRow);
    1060           0 :     if ( nGroupPos == NO_GROUP )
    1061           0 :         return;
    1062             : 
    1063           0 :     uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);
    1064           0 :     if ( m_pHeaderLst->IsValueChangedFromSaved() )
    1065           0 :         xGroup->setHeaderOn( m_pHeaderLst->GetSelectEntryPos() == 0 );
    1066           0 :     if ( m_pFooterLst->IsValueChangedFromSaved() )
    1067           0 :         xGroup->setFooterOn( m_pFooterLst->GetSelectEntryPos() == 0 );
    1068           0 :     if ( m_pKeepTogetherLst->IsValueChangedFromSaved() )
    1069           0 :         xGroup->setKeepTogether( m_pKeepTogetherLst->GetSelectEntryPos() );
    1070           0 :     if ( m_pGroupOnLst->IsValueChangedFromSaved() )
    1071             :     {
    1072           0 :         sal_Int16 nGroupOn = static_cast<sal_Int16>(reinterpret_cast<sal_IntPtr>(m_pGroupOnLst->GetSelectEntryData()));
    1073           0 :         xGroup->setGroupOn( nGroupOn );
    1074             :     }
    1075           0 :     if ( m_pGroupIntervalEd->IsValueChangedFromSaved() )
    1076             :     {
    1077           0 :         xGroup->setGroupInterval( static_cast<sal_Int32>(m_pGroupIntervalEd->GetValue()) );
    1078           0 :         m_pGroupIntervalEd->SaveValue();
    1079             :     }
    1080           0 :     if ( m_pOrderLst->IsValueChangedFromSaved() )
    1081           0 :         xGroup->setSortAscending( m_pOrderLst->GetSelectEntryPos() == 0 );
    1082             : 
    1083           0 :     ListBox* pControls[] = { m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pKeepTogetherLst, m_pOrderLst};
    1084           0 :     for (size_t i = 0; i < sizeof(pControls)/sizeof(pControls[0]); ++i)
    1085           0 :         pControls[i]->SaveValue();
    1086             : }
    1087             : 
    1088             : 
    1089           0 : sal_Int32 OGroupsSortingDialog::getColumnDataType(const OUString& _sColumnName)
    1090             : {
    1091           0 :     sal_Int32 nDataType = sdbc::DataType::VARCHAR;
    1092             :     try
    1093             :     {
    1094           0 :         if ( !m_xColumns.is() )
    1095           0 :             fillColumns();
    1096           0 :         if ( m_xColumns.is() && m_xColumns->hasByName(_sColumnName) )
    1097             :         {
    1098           0 :             uno::Reference< beans::XPropertySet> xColumn(m_xColumns->getByName(_sColumnName),uno::UNO_QUERY);
    1099           0 :             if ( xColumn.is() )
    1100           0 :                 xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
    1101             :         }
    1102             :     }
    1103           0 :     catch(uno::Exception&)
    1104             :     {
    1105             :         OSL_FAIL("Exception caught while getting the type of a column");
    1106             :     }
    1107             : 
    1108           0 :     return nDataType;
    1109             : }
    1110             : 
    1111           0 : IMPL_LINK(OGroupsSortingDialog, OnControlFocusGot, Control*, pControl )
    1112             : {
    1113           0 :     if ( m_pFieldExpression && m_pFieldExpression->getExpressionControl() )
    1114             :     {
    1115           0 :         Control* pControls[] = { m_pFieldExpression->getExpressionControl(), m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pGroupIntervalEd, m_pKeepTogetherLst, m_pOrderLst};
    1116           0 :         for (size_t i = 0; i < sizeof(pControls)/sizeof(pControls[0]); ++i)
    1117             :         {
    1118           0 :             if ( pControl == pControls[i] )
    1119             :             {
    1120           0 :                 ListBox* pListBox = dynamic_cast< ListBox* >( pControl );
    1121           0 :                 if ( pListBox )
    1122           0 :                     pListBox->SaveValue();
    1123           0 :                 NumericField* pNumericField = dynamic_cast< NumericField* >( pControl );
    1124           0 :                 if ( pNumericField )
    1125           0 :                     pNumericField->SaveValue();
    1126           0 :                 showHelpText(static_cast<sal_uInt16>(i+STR_RPT_HELP_FIELD));
    1127           0 :                 break;
    1128             :             }
    1129             :         }
    1130             :     }
    1131           0 :     return 0L;
    1132             : }
    1133             : 
    1134           0 : IMPL_LINK(OGroupsSortingDialog, OnControlFocusLost, Control*, pControl )
    1135             : {
    1136           0 :     if (m_pFieldExpression && pControl == m_pGroupIntervalEd)
    1137             :     {
    1138           0 :         if ( m_pGroupIntervalEd->IsModified() )
    1139           0 :             SaveData(m_pFieldExpression->GetCurRow());
    1140             :     }
    1141           0 :     return 0L;
    1142             : }
    1143             : 
    1144           0 : IMPL_LINK_NOARG_TYPED( OGroupsSortingDialog, OnFormatAction, ToolBox*, void )
    1145             : {
    1146             : 
    1147           0 :     sal_uInt16 nCommand = m_pToolBox->GetCurItemId();
    1148             : 
    1149           0 :     if ( m_pFieldExpression )
    1150             :     {
    1151           0 :         long nIndex = m_pFieldExpression->GetCurrRow();
    1152           0 :         sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(nIndex);
    1153           0 :         uno::Sequence<uno::Any> aClipboardList;
    1154           0 :         if ( nIndex >= 0 && nGroupPos != NO_GROUP )
    1155             :         {
    1156           0 :             aClipboardList.realloc(1);
    1157           0 :             aClipboardList[0] = m_xGroups->getByIndex(nGroupPos);
    1158             :         }
    1159           0 :         if ( nCommand == m_nMoveUpId )
    1160             :         {
    1161           0 :             --nIndex;
    1162             :         }
    1163           0 :         if ( nCommand == m_nMoveDownId )
    1164             :         {
    1165           0 :             ++nIndex;
    1166             :         }
    1167           0 :         if ( nCommand == m_nDeleteId )
    1168             :         {
    1169           0 :             Application::PostUserEvent( LINK(m_pFieldExpression, OFieldExpressionControl, DelayedDelete), NULL, true );
    1170             :         }
    1171             :         else
    1172             :         {
    1173           0 :             if ( nIndex >= 0 && aClipboardList.getLength() )
    1174             :             {
    1175           0 :                 m_pFieldExpression->SetNoSelection();
    1176           0 :                 m_pFieldExpression->moveGroups(aClipboardList,nIndex,false);
    1177           0 :                 m_pFieldExpression->DeactivateCell();
    1178           0 :                 m_pFieldExpression->GoToRow(nIndex);
    1179           0 :                 m_pFieldExpression->ActivateCell(nIndex, m_pFieldExpression->GetCurColumnId());
    1180           0 :                 DisplayData(nIndex);
    1181             :             }
    1182           0 :         }
    1183             :     }
    1184           0 : }
    1185             : 
    1186           0 : IMPL_LINK( OGroupsSortingDialog, LBChangeHdl, ListBox*, pListBox )
    1187             : {
    1188           0 :     if ( pListBox->IsValueChangedFromSaved() )
    1189             :     {
    1190           0 :         sal_Int32 nRow = m_pFieldExpression->GetCurRow();
    1191           0 :         sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(nRow);
    1192           0 :         if (pListBox != m_pHeaderLst && pListBox != m_pFooterLst)
    1193             :         {
    1194           0 :             if ( pListBox->IsValueChangedFromSaved() )
    1195           0 :                 SaveData(nRow);
    1196           0 :             if ( pListBox == m_pGroupOnLst )
    1197           0 :                 m_pGroupIntervalEd->Enable( pListBox->GetSelectEntryPos() != 0 );
    1198             :         }
    1199           0 :         else if ( nGroupPos != NO_GROUP )
    1200             :         {
    1201           0 :             uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);
    1202           0 :             uno::Sequence< beans::PropertyValue > aArgs(2);
    1203           0 :             aArgs[1].Name = PROPERTY_GROUP;
    1204           0 :             aArgs[1].Value <<= xGroup;
    1205             : 
    1206           0 :             if ( m_pHeaderLst  == pListBox )
    1207           0 :                 aArgs[0].Name = PROPERTY_HEADERON;
    1208             :             else
    1209           0 :                 aArgs[0].Name = PROPERTY_FOOTERON;
    1210             : 
    1211           0 :             aArgs[0].Value <<= pListBox->GetSelectEntryPos() == 0;
    1212           0 :             m_pController->executeChecked(m_pHeaderLst  == pListBox ? SID_GROUPHEADER : SID_GROUPFOOTER,aArgs);
    1213           0 :             m_pFieldExpression->InvalidateHandleColumn();
    1214             :         }
    1215             :     }
    1216           0 :     return 1L;
    1217             : }
    1218             : 
    1219           0 : void OGroupsSortingDialog::showHelpText(sal_uInt16 _nResId)
    1220             : {
    1221           0 :     m_pHelpWindow->SetText(OUString(ModuleRes(_nResId)));
    1222           0 : }
    1223             : 
    1224           0 : void OGroupsSortingDialog::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw(uno::RuntimeException, std::exception)
    1225             : {
    1226           0 :     uno::Reference< report::XGroup > xGroup(_rEvent.Source,uno::UNO_QUERY);
    1227           0 :     if ( xGroup.is() )
    1228           0 :         displayGroup(xGroup);
    1229             :     else
    1230           0 :         fillColumns();
    1231           0 : }
    1232             : 
    1233           0 : void OGroupsSortingDialog::fillColumns()
    1234             : {
    1235           0 :     m_xColumns = m_pController->getColumns();
    1236           0 :     m_pFieldExpression->fillColumns(m_xColumns);
    1237           0 : }
    1238             : 
    1239           0 : void OGroupsSortingDialog::displayGroup(const uno::Reference<report::XGroup>& _xGroup)
    1240             : {
    1241           0 :     m_pHeaderLst->SelectEntryPos(_xGroup->getHeaderOn() ? 0 : 1 );
    1242           0 :     m_pFooterLst->SelectEntryPos(_xGroup->getFooterOn() ? 0 : 1 );
    1243           0 :     sal_Int32 nDataType = getColumnDataType(_xGroup->getExpression());
    1244             : 
    1245             :     // first clear whole group on list
    1246           0 :     while(m_pGroupOnLst->GetEntryCount() > 1 )
    1247             :     {
    1248           0 :         m_pGroupOnLst->RemoveEntry(1);
    1249             :     }
    1250             : 
    1251           0 :     switch(nDataType)
    1252             :     {
    1253             :         case sdbc::DataType::LONGVARCHAR:
    1254             :         case sdbc::DataType::VARCHAR:
    1255             :         case sdbc::DataType::CHAR:
    1256           0 :             m_pGroupOnLst->InsertEntry(OUString(ModuleRes(STR_RPT_PREFIXCHARS)));
    1257           0 :             m_pGroupOnLst->SetEntryData(1,reinterpret_cast<void*>(report::GroupOn::PREFIX_CHARACTERS));
    1258           0 :             break;
    1259             :         case sdbc::DataType::DATE:
    1260             :         case sdbc::DataType::TIME:
    1261             :         case sdbc::DataType::TIMESTAMP:
    1262             :             {
    1263           0 :                 sal_uInt16 nIds[] = { STR_RPT_YEAR, STR_RPT_QUARTER,STR_RPT_MONTH,STR_RPT_WEEK,STR_RPT_DAY,STR_RPT_HOUR,STR_RPT_MINUTE };
    1264           0 :                 for (sal_uInt16 i = 0; i < sizeof (nIds) / sizeof (nIds[0]); ++i)
    1265             :                 {
    1266           0 :                     m_pGroupOnLst->InsertEntry(OUString(ModuleRes(nIds[i])));
    1267           0 :                     m_pGroupOnLst->SetEntryData(i+1,reinterpret_cast<void*>(i+2));
    1268             :                 }
    1269             :             }
    1270           0 :             break;
    1271             :         default:
    1272           0 :             m_pGroupOnLst->InsertEntry(OUString(ModuleRes(STR_RPT_INTERVAL)));
    1273           0 :             m_pGroupOnLst->SetEntryData(1,reinterpret_cast<void*>(report::GroupOn::INTERVAL));
    1274           0 :             break;
    1275             :     }
    1276           0 :     sal_Int32 nPos = 0;
    1277           0 :     switch(_xGroup->getGroupOn())
    1278             :     {
    1279             :         case report::GroupOn::DEFAULT:
    1280           0 :             nPos = 0;
    1281           0 :             break;
    1282             :         case report::GroupOn::PREFIX_CHARACTERS:
    1283           0 :             nPos = 1;
    1284           0 :             break;
    1285             :         case report::GroupOn::YEAR:
    1286           0 :             nPos = 1;
    1287           0 :             break;
    1288             :         case report::GroupOn::QUARTAL:
    1289           0 :             nPos = 2;
    1290           0 :             break;
    1291             :         case report::GroupOn::MONTH:
    1292           0 :             nPos = 3;
    1293           0 :             break;
    1294             :         case report::GroupOn::WEEK:
    1295           0 :             nPos = 4;
    1296           0 :             break;
    1297             :         case report::GroupOn::DAY:
    1298           0 :             nPos = 5;
    1299           0 :             break;
    1300             :         case report::GroupOn::HOUR:
    1301           0 :             nPos = 6;
    1302           0 :             break;
    1303             :         case report::GroupOn::MINUTE:
    1304           0 :             nPos = 7;
    1305           0 :             break;
    1306             :         case report::GroupOn::INTERVAL:
    1307           0 :             nPos = 1;
    1308           0 :             break;
    1309             :         default:
    1310           0 :             nPos = 0;
    1311             :     }
    1312           0 :     m_pGroupOnLst->SelectEntryPos(nPos);
    1313           0 :     m_pGroupIntervalEd->SetText(OUString::number(_xGroup->getGroupInterval()));
    1314           0 :     m_pGroupIntervalEd->SaveValue();
    1315           0 :     m_pGroupIntervalEd->Enable( nPos != 0 );
    1316           0 :     m_pKeepTogetherLst->SelectEntryPos(_xGroup->getKeepTogether());
    1317           0 :     m_pOrderLst->SelectEntryPos(_xGroup->getSortAscending() ? 0 : 1);
    1318             : 
    1319           0 :     ListBox* pControls[] = { m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pKeepTogetherLst, m_pOrderLst};
    1320           0 :     for (size_t i = 0; i < sizeof(pControls)/sizeof(pControls[0]); ++i)
    1321           0 :         pControls[i]->SaveValue();
    1322             : 
    1323           0 :     ListBox* pControlsLst2[] = { m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pKeepTogetherLst, m_pOrderLst};
    1324           0 :     bool bReadOnly = !m_pController->isEditable();
    1325           0 :     for (size_t i = 0; i < sizeof(pControlsLst2)/sizeof(pControlsLst2[0]); ++i)
    1326           0 :         pControlsLst2[i]->SetReadOnly(bReadOnly);
    1327           0 :     m_pGroupIntervalEd->SetReadOnly(bReadOnly);
    1328           0 : }
    1329             : 
    1330           0 : void OGroupsSortingDialog::checkButtons(sal_Int32 _nRow)
    1331             : {
    1332           0 :     sal_Int32 nGroupCount = m_xGroups->getCount();
    1333           0 :     sal_Int32 nRowCount = m_pFieldExpression->GetRowCount();
    1334           0 :     bool bEnabled = nGroupCount > 1;
    1335             : 
    1336           0 :     if (bEnabled && _nRow > 0 )
    1337             :     {
    1338           0 :         m_pToolBox->EnableItem(m_nMoveUpId, true);
    1339             :     }
    1340             :     else
    1341             :     {
    1342           0 :         m_pToolBox->EnableItem(m_nMoveUpId, false);
    1343             :     }
    1344           0 :     if (bEnabled && _nRow < (nRowCount - 1) )
    1345             :     {
    1346           0 :         m_pToolBox->EnableItem(m_nMoveDownId, true);
    1347             :     }
    1348             :     else
    1349             :     {
    1350           0 :         m_pToolBox->EnableItem(m_nMoveDownId, false);
    1351             :     }
    1352             : 
    1353           0 :     sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(_nRow);
    1354           0 :     if ( nGroupPos != NO_GROUP )
    1355             :     {
    1356           0 :         bool bEnableDelete = nGroupCount > 0;
    1357           0 :         m_pToolBox->EnableItem(m_nDeleteId, bEnableDelete);
    1358             :     }
    1359             :     else
    1360             :     {
    1361           0 :         m_pToolBox->EnableItem(m_nDeleteId, false);
    1362             :     }
    1363           0 : }
    1364             : 
    1365           3 : } // rptui
    1366             : 
    1367             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11