blob: e92375c79ca4a302f1cd5cafeba28cf4d7fe6fb6 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#include "scitems.hxx"
#include <memory> //auto_ptr
#include <editeng/adjitem.hxx>
#include <svx/algitem.hxx>
#include <svx/dbexch.hrc>
#include <editeng/editview.hxx>
#include <editeng/editstat.hxx>
#include <editeng/flditem.hxx>
#include <svx/svdetc.hxx>
#include <editeng/editobj.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/docfile.hxx>
#include <svl/stritem.hxx>
#include <svtools/svlbox.hxx>
#include <svtools/svtabbx.hxx>
#include <svl/urlbmk.hxx>
#include <tools/urlobj.hxx>
#include <vcl/cursor.hxx>
#include <vcl/sound.hxx>
#include <vcl/graph.hxx>
#include <vcl/hatch.hxx>
#include <sot/formats.hxx>
#include <sot/clsids.hxx>
#include <svx/svdview.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
#include <editeng/outliner.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
#include <svx/svditer.hxx>
#include <svx/svdocapt.hxx>
#include <svx/svdpagv.hxx>
#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
#include <com/sun/star/sheet/DataPilotTableResultData.hpp>
#include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
#include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
#include <com/sun/star/sheet/MemberResultFlags.hpp>
#include <com/sun/star/awt/KeyModifier.hpp>
#include <com/sun/star/awt/MouseButton.hpp>
#include <com/sun/star/script/vba/VBAEventId.hpp>
#include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
#include "gridwin.hxx"
#include "tabvwsh.hxx"
#include "docsh.hxx"
#include "viewdata.hxx"
#include "tabview.hxx"
#include "select.hxx"
#include "scmod.hxx"
#include "document.hxx"
#include "attrib.hxx"
#include "dbcolect.hxx"
#include "stlpool.hxx"
#include "printfun.hxx"
#include "cbutton.hxx"
#include "sc.hrc"
#include "globstr.hrc"
#include "editutil.hxx"
#include "scresid.hxx"
#include "inputhdl.hxx"
#include "uiitems.hxx" // Filter-Dialog - auslagern !!!
#include "filtdlg.hxx"
#include "impex.hxx" // Sylk-ID fuer CB
#include "cell.hxx" // fuer Edit-Felder
#include "patattr.hxx"
#include "notemark.hxx"
#include "rfindlst.hxx"
#include "docpool.hxx"
#include "output.hxx"
#include "docfunc.hxx"
#include "dbdocfun.hxx"
#include "dpobject.hxx"
#include "dpoutput.hxx"
#include "transobj.hxx"
#include "drwtrans.hxx"
#include "seltrans.hxx"
#include "sizedev.hxx"
#include "AccessibilityHints.hxx"
#include "dpsave.hxx"
#include "viewuno.hxx"
#include "compiler.hxx"
#include "editable.hxx"
#include "fillinfo.hxx"
#include "scitems.hxx"
#include "userdat.hxx"
#include "drwlayer.hxx"
#include "attrib.hxx"
#include "validat.hxx"
#include "tabprotection.hxx"
#include "postit.hxx"
#include "dpcontrol.hxx"
#include "cellsuno.hxx"
#include "drawview.hxx"
#include <svx/sdrpagewindow.hxx>
#include <svx/sdr/overlay/overlaymanager.hxx>
#include <vcl/svapp.hxx>
#include <svx/sdr/overlay/overlayselection.hxx>
using namespace com::sun::star;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Any;
const sal_uInt8 SC_NESTEDBUTTON_NONE = 0;
const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1;
const sal_uInt8 SC_NESTEDBUTTON_UP = 2;
#define SC_AUTOFILTER_ALL 0
#define SC_AUTOFILTER_TOP10 1
#define SC_AUTOFILTER_CUSTOM 2
// Modi fuer die FilterListBox
enum ScFilterBoxMode
{
SC_FILTERBOX_FILTER,
SC_FILTERBOX_DATASELECT,
SC_FILTERBOX_SCENARIO,
SC_FILTERBOX_PAGEFIELD
};
extern SfxViewShell* pScActiveViewShell; // global.cxx
extern sal_uInt16 nScClickMouseModifier; // global.cxx
extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
#define SC_FILTERLISTBOX_LINES 12
// ============================================================================
ScGridWindow::VisibleRange::VisibleRange() :
mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW)
{
}
bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const
{
return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2;
}
// ============================================================================
class ScFilterListBox : public ListBox
{
private:
ScGridWindow* pGridWin;
SCCOL nCol;
SCROW nRow;
sal_Bool bButtonDown;
sal_Bool bInit;
sal_Bool bCancelled;
sal_Bool bInSelect;
bool mbListHasDates;
sal_uLong nSel;
ScFilterBoxMode eMode;
protected:
virtual void LoseFocus();
void SelectHdl();
public:
ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode );
~ScFilterListBox();
virtual long PreNotify( NotifyEvent& rNEvt );
virtual void Select();
SCCOL GetCol() const { return nCol; }
SCROW GetRow() const { return nRow; }
ScFilterBoxMode GetMode() const { return eMode; }
sal_Bool IsDataSelect() const { return (eMode == SC_FILTERBOX_DATASELECT); }
void EndInit();
sal_Bool IsInInit() const { return bInit; }
void SetCancelled() { bCancelled = sal_True; }
sal_Bool IsInSelect() const { return bInSelect; }
void SetListHasDates(bool b) { mbListHasDates = b; }
bool HasDates() const { return mbListHasDates; }
};
//-------------------------------------------------------------------
// ListBox in einem FloatingWindow (pParent)
ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ) :
ListBox( pParent, WB_AUTOHSCROLL ),
pGridWin( pGrid ),
nCol( nNewCol ),
nRow( nNewRow ),
bButtonDown( sal_False ),
bInit( sal_True ),
bCancelled( sal_False ),
bInSelect( sal_False ),
mbListHasDates(false),
nSel( 0 ),
eMode( eNewMode )
{
}
__EXPORT ScFilterListBox::~ScFilterListBox()
{
if (IsMouseCaptured())
ReleaseMouse();
}
void ScFilterListBox::EndInit()
{
sal_uInt16 nPos = GetSelectEntryPos();
if ( LISTBOX_ENTRY_NOTFOUND == nPos )
nSel = 0;
else
nSel = nPos;
bInit = sal_False;
}
void __EXPORT ScFilterListBox::LoseFocus()
{
#ifndef UNX
Hide();
#endif
}
// -----------------------------------------------------------------------
long ScFilterListBox::PreNotify( NotifyEvent& rNEvt )
{
long nDone = 0;
if ( rNEvt.GetType() == EVENT_KEYINPUT )
{
KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
KeyCode aCode = aKeyEvt.GetKeyCode();
if ( !aCode.GetModifier() ) // ohne alle Modifiers
{
sal_uInt16 nKey = aCode.GetCode();
if ( nKey == KEY_RETURN )
{
SelectHdl(); // auswaehlen
nDone = 1;
}
else if ( nKey == KEY_ESCAPE )
{
pGridWin->ClickExtern(); // loescht die List-Box !!!
nDone = 1;
}
}
}
return nDone ? nDone : ListBox::PreNotify( rNEvt );
}
void __EXPORT ScFilterListBox::Select()
{
ListBox::Select();
SelectHdl();
}
void __EXPORT ScFilterListBox::SelectHdl()
{
if ( !IsTravelSelect() && !bInit && !bCancelled )
{
sal_uInt16 nPos = GetSelectEntryPos();
if ( LISTBOX_ENTRY_NOTFOUND != nPos )
{
nSel = nPos;
if (!bButtonDown)
{
// #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect
bInSelect = sal_True;
pGridWin->FilterSelect( nSel );
bInSelect = sal_False;
}
}
}
}
// ============================================================================
// use a System floating window for the above filter listbox
class ScFilterFloatingWindow : public FloatingWindow
{
public:
ScFilterFloatingWindow( Window* pParent, WinBits nStyle = WB_STDFLOATWIN );
virtual ~ScFilterFloatingWindow();
// required for System FloatingWindows that will not process KeyInput by themselves
virtual Window* GetPreferredKeyInputWindow();
};
ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) :
FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater
{}
ScFilterFloatingWindow::~ScFilterFloatingWindow()
{
EndPopupMode();
}
Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow()
{
// redirect keyinput in the child window
return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL; // will be the FilterBox
}
// ============================================================================
sal_Bool lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange )
{
// wenn es ein editierbarer Bereich ist, und rechts unten eine Matrix-Zelle
// mit Origin links oben liegt, enthaelt der Bereich genau die Matrix.
//! Direkt die MatrixEdges Funktionen von der Column herausreichen ???
if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(),
rRange.aEnd.Col(),rRange.aEnd.Row() ) )
return sal_False;
ScAddress aPos;
const ScBaseCell* pCell = pDoc->GetCell( rRange.aEnd );
return ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
((ScFormulaCell*)pCell)->GetMatrixOrigin(aPos) && aPos == rRange.aStart );
}
void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData )
{
if (!pView && !pPV && !pDrDoc && !pViewData)
return;
ScDocument& rDoc = *pViewData->GetDocument();
ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
ScPostIt* pNote = rDoc.GetNote( aCellPos );
SdrObject* pObj = pNote ? pNote->GetCaption() : 0;
if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) )
{
const ScProtectionAttr* pProtAttr = static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) );
bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ;
bool bProtectDoc = rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ;
// unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged()
pView->LockInternalLayer( bProtectDoc && bProtectAttr );
}
}
sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell )
{
sal_Bool bFound = sal_False;
do
{
pDoc->GetCell( rPosX, rPosY, nTab, rpCell );
if ( !rpCell || rpCell->GetCellType() == CELLTYPE_NOTE )
{
if ( rPosX <= 0 )
return sal_False; // alles leer bis links
else
--rPosX; // weitersuchen
}
else if ( rpCell->GetCellType() == CELLTYPE_EDIT)
bFound = sal_True;
else if (rpCell->GetCellType() == CELLTYPE_FORMULA &&
static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell())
bFound = sal_True;
else
return sal_False; // andere Zelle
}
while ( !bFound );
return bFound;
}
// ---------------------------------------------------------------------------
// WB_DIALOGCONTROL noetig fuer UNO-Controls
ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos )
: Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ),
DropTargetHelper( this ),
DragSourceHelper( this ),
mpOOCursors( NULL ),
mpOOSelection( NULL ),
mpOOAutoFill( NULL ),
mpOODragRect( NULL ),
mpOOHeader( NULL ),
mpOOShrink( NULL ),
mpAutoFillRect(static_cast<Rectangle*>(NULL)),
pViewData( pData ),
eWhich( eWhichPos ),
pNoteMarker( NULL ),
pFilterBox( NULL ),
pFilterFloat( NULL ),
mpDPFieldPopup(NULL),
mpFilterButton(NULL),
nCursorHideCount( 0 ),
bMarking( sal_False ),
nButtonDown( 0 ),
bEEMouse( sal_False ),
nMouseStatus( SC_GM_NONE ),
nNestedButtonState( SC_NESTEDBUTTON_NONE ),
bDPMouse( sal_False ),
bRFMouse( sal_False ),
nPagebreakMouse( SC_PD_NONE ),
bPagebreakDrawn( sal_False ),
nPageScript( 0 ),
bDragRect( sal_False ),
meDragInsertMode( INS_NONE ),
nCurrentPointer( 0 ),
bIsInScroll( sal_False ),
bIsInPaint( sal_False ),
aComboButton( this ),
aCurMousePos( 0,0 ),
nPaintCount( 0 ),
bNeedsRepaint( sal_False ),
bAutoMarkVisible( sal_False ),
bListValButton( sal_False )
{
switch(eWhich)
{
case SC_SPLIT_TOPLEFT:
eHWhich = SC_SPLIT_LEFT;
eVWhich = SC_SPLIT_TOP;
break;
case SC_SPLIT_TOPRIGHT:
eHWhich = SC_SPLIT_RIGHT;
eVWhich = SC_SPLIT_TOP;
break;
case SC_SPLIT_BOTTOMLEFT:
eHWhich = SC_SPLIT_LEFT;
eVWhich = SC_SPLIT_BOTTOM;
break;
case SC_SPLIT_BOTTOMRIGHT:
eHWhich = SC_SPLIT_RIGHT;
eVWhich = SC_SPLIT_BOTTOM;
break;
default:
DBG_ERROR("GridWindow: falsche Position");
}
SetBackground();
SetMapMode(pViewData->GetLogicMode(eWhich));
// EnableDrop();
EnableChildTransparentMode();
SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
SetHelpId( HID_SC_WIN_GRIDWIN );
SetUniqueId( HID_SC_WIN_GRIDWIN );
SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
EnableRTL( sal_False );
}
__EXPORT ScGridWindow::~ScGridWindow()
{
// #114409#
ImpDestroyOverlayObjects();
delete pFilterBox;
delete pFilterFloat;
delete pNoteMarker;
}
void __EXPORT ScGridWindow::Resize( const Size& )
{
// gar nix
}
void ScGridWindow::ClickExtern()
{
do
{
// #i81298# don't delete the filter box when called from its select handler
// (possible through row header size update)
// #i84277# when initializing the filter box, a Basic error can deactivate the view
if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
{
break;
}
DELETEZ(pFilterBox);
DELETEZ(pFilterFloat);
}
while (false);
if (mpDPFieldPopup.get())
{
mpDPFieldPopup->close(false);
mpDPFieldPopup.reset();
}
}
IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG )
{
if (pFilterBox)
pFilterBox->SetCancelled(); // nicht mehr auswaehlen
GrabFocus();
return 0;
}
IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
{
if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
return 0;
}
void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, sal_Bool bHasSelection, const String& rStr )
{
//! gridwin2 ?
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
if ( pDPObj && nCol > 0 )
{
// look for the dimension header left of the drop-down arrow
sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
{
ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
sal_Bool bIsDataLayout;
String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
if ( !bIsDataLayout )
{
ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
if ( bHasSelection )
pDim->SetCurrentPage( &rStr );
else
pDim->SetCurrentPage( NULL );
ScDPObject aNewObj( *pDPObj );
aNewObj.SetSaveData( aSaveData );
ScDBDocFunc aFunc( *pViewData->GetDocShell() );
aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False );
pViewData->GetView()->CursorPosChanged(); // shells may be switched
}
}
}
}
void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
{
//! merge position/size handling with DoAutoFilterMenue
delete pFilterBox;
delete pFilterFloat;
sal_uInt16 i;
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
long nSizeX = 0;
long nSizeY = 0;
long nHeight = 0;
pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
if ( bLayoutRTL )
aPos.X() -= nSizeX;
Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
aPos.X() -= 1;
aPos.Y() += nSizeY - 1;
pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // not resizable etc.
pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_PAGEFIELD );
if ( bLayoutRTL )
pFilterBox->EnableMirroring();
nSizeX += 1;
{
Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
nHeight = GetTextHeight();
nHeight *= SC_FILTERLISTBOX_LINES;
SetMapMode( aOldMode );
SetFont( aOldFont );
}
// SetSize comes later
TypedScStrCollection aStrings( 128, 128 );
// get list box entries and selection
sal_Bool bHasCurrentPage = sal_False;
String aCurrentPage;
ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
if ( pDPObj && nCol > 0 )
{
// look for the dimension header left of the drop-down arrow
sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
{
pDPObj->FillPageList( aStrings, nField );
// get current page from SaveData
ScDPSaveData* pSaveData = pDPObj->GetSaveData();
sal_Bool bIsDataLayout;
String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
if ( pSaveData && !bIsDataLayout )
{
ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName);
if ( pDim && pDim->HasCurrentPage() )
{
aCurrentPage = pDim->GetCurrentPage();
bHasCurrentPage = sal_True;
}
}
}
}
// include all entry widths for the size of the drop-down
long nMaxText = 0;
sal_uInt16 nCount = aStrings.GetCount();
for (i=0; i<nCount; i++)
{
TypedStrData* pData = aStrings[i];
long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
if ( nTextWidth > nMaxText )
nMaxText = nTextWidth;
}
// add scrollbar width if needed (string entries are counted here)
// (scrollbar is shown if the box is exactly full?)
if ( nCount >= SC_FILTERLISTBOX_LINES )
nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
nMaxText += 4; // for borders
if ( nMaxText > nSizeX )
nSizeX = nMaxText; // just modify width - starting position is unchanged
// adjust position and size to window
Size aParentSize = GetParent()->GetOutputSizePixel();
Size aSize( nSizeX, nHeight );
if ( aSize.Height() > aParentSize.Height() )
aSize.Height() = aParentSize.Height();
if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
aPos.Y() = aParentSize.Height() - aSize.Height();
pFilterBox->SetSizePixel( aSize );
pFilterBox->Show(); // Show must be called before SetUpdateMode
pFilterBox->SetUpdateMode(sal_False);
pFilterFloat->SetOutputSizePixel( aSize );
pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
// fill the list box
sal_Bool bWait = ( nCount > 100 );
if (bWait)
EnterWait();
for (i=0; i<nCount; i++)
pFilterBox->InsertEntry( aStrings[i]->GetString() );
pFilterBox->SetSeparatorPos( 0 );
if (bWait)
LeaveWait();
pFilterBox->SetUpdateMode(sal_True);
sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND;
if (bHasCurrentPage)
nSelPos = pFilterBox->GetEntryPos( aCurrentPage );
if ( nSelPos == LISTBOX_ENTRY_NOTFOUND )
nSelPos = 0; // first entry
pFilterBox->GrabFocus();
// call Select after GrabFocus, so the focus rectangle ends up in the right position
if ( nSelPos != LISTBOX_ENTRY_NOTFOUND )
pFilterBox->SelectEntryPos( nSelPos );
pFilterBox->EndInit();
nMouseStatus = SC_GM_FILTER;
CaptureMouse();
}
void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
{
SCTAB nTab = pViewData->GetTabNo();
ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
if (!pDPObj)
return;
// Get the geometry of the cell.
Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
long nSizeX, nSizeY;
pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
Size aScrSize(nSizeX-1, nSizeY-1);
DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
}
void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange )
{
delete pFilterBox;
delete pFilterFloat;
SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons
SCROW nRow = rScenRange.aStart.Row();
if (nRow == 0)
{
nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb
if (nRow>MAXROW) nRow = MAXROW;
//! Texthoehe addieren (wenn sie an der View gespeichert ist...)
}
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
long nSizeX = 0;
long nSizeY = 0;
long nHeight = 0;
pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
if ( bLayoutRTL )
aPos.X() -= nSizeX;
Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
aCellRect.Top() -= nSizeY;
aCellRect.Bottom() -= nSizeY - 1;
// Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
// (wenn die Linie verdeckt wird, sieht es komisch aus...)
pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
if ( bLayoutRTL )
pFilterBox->EnableMirroring();
nSizeX += 1;
{
Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
nHeight = GetTextHeight();
nHeight *= SC_FILTERLISTBOX_LINES;
SetMapMode( aOldMode );
SetFont( aOldFont );
}
// SetSize spaeter
/*
pFilterBox->SetSelectionMode( SINGLE_SELECTION );
pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
*/
// ParentSize Abfrage fehlt
Size aSize( nSizeX, nHeight );
pFilterBox->SetSizePixel( aSize );
pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
pFilterBox->SetUpdateMode(sal_False);
// SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht
// Listbox fuellen
long nMaxText = 0;
String aCurrent;
String aTabName;
SCTAB nTabCount = pDoc->GetTableCount();
SCTAB nEntryCount = 0;
for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
{
if (pDoc->HasScenarioRange( i, rScenRange ))
if (pDoc->GetName( i, aTabName ))
{
pFilterBox->InsertEntry( aTabName );
if (pDoc->IsActiveScenario(i))
aCurrent = aTabName;
long nTextWidth = pFilterBox->GetTextWidth( aTabName );
if ( nTextWidth > nMaxText )
nMaxText = nTextWidth;
++nEntryCount;
}
}
if (nEntryCount > SC_FILTERLISTBOX_LINES)
nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
nMaxText += 4; // fuer Rand
if ( nMaxText > 300 )
nMaxText = 300; // auch nicht uebertreiben (Pixel)
if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse anpassen
{
long nDiff = nMaxText - nSizeX;
aSize = Size( nMaxText, nHeight );
pFilterBox->SetSizePixel( aSize );
pFilterFloat->SetOutputSizePixel( aSize );
if ( !bLayoutRTL )
{
// also move popup position
long nNewX = aCellRect.Left() - nDiff;
if ( nNewX < 0 )
nNewX = 0;
aCellRect.Left() = nNewX;
}
}
pFilterFloat->SetOutputSizePixel( aSize );
pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
pFilterBox->SetUpdateMode(sal_True);
pFilterBox->GrabFocus();
// Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
//! SvLBoxEntry* pSelect = NULL;
sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND;
if (aCurrent.Len())
{
nPos = pFilterBox->GetEntryPos( aCurrent );
//! pSelect = pFilterBox->GetEntry( nPos );
}
if (/*!pSelect*/ LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
nPos = 0;
//! pSelect = pFilterBox->GetEntry(0); // einer sollte immer selektiert sein
if (/*pSelect*/ LISTBOX_ENTRY_NOTFOUND != nPos )
pFilterBox->SelectEntryPos(nPos);
pFilterBox->EndInit();
// Szenario-Auswahl kommt aus MouseButtonDown:
// der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
nMouseStatus = SC_GM_FILTER;
CaptureMouse();
}
sal_Bool ScGridWindow::HasScenarioRange( sal_uInt16 nCol, sal_Int32 nRow, ScRange& rScenRange )
{
ScDocument* pDoc = pViewData->GetDocument();
sal_uInt16 nTab = pViewData->GetTabNo();
sal_uInt16 nTabCount = pDoc->GetTableCount();
if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
{
sal_uInt16 i;
ScMarkData aMarks;
for (i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME );
ScRangeList aRanges;
aMarks.FillRangeListWithMarks( &aRanges, sal_False );
sal_uInt16 nRangeCount = (sal_uInt16)aRanges.Count();
for (i=0; i<nRangeCount; i++)
{
ScRange aRange = *aRanges.GetObject(i);
pDoc->ExtendTotalMerge( aRange );
sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 );
sal_Bool bIsInScen = sal_False;
if ( bTextBelow )
{
bIsInScen = (aRange.aStart.Col() == nCol && aRange.aEnd.Row() == nRow-1);
}
else
{
bIsInScen = (aRange.aStart.Col() == nCol && aRange.aStart.Row() == nRow+1);
}
if (bIsInScen)
{
rScenRange = aRange;
return sal_True;
}
}
}
return sal_False;
}
void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, sal_Bool bDataSelect )
{
delete pFilterBox;
delete pFilterFloat;
sal_uInt16 i;
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
long nSizeX = 0;
long nSizeY = 0;
long nHeight = 0;
pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
// The button height should not use the merged cell height, should still use single row height
nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY());
Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
if ( bLayoutRTL )
aPos.X() -= nSizeX;
Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
aPos.X() -= 1;
aPos.Y() += nSizeY - 1;
pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
pFilterBox = new ScFilterListBox(
pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
if ( bLayoutRTL )
pFilterBox->EnableMirroring();
nSizeX += 1;
{
Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
nHeight = GetTextHeight();
nHeight *= SC_FILTERLISTBOX_LINES;
SetMapMode( aOldMode );
SetFont( aOldFont );
}
// SetSize spaeter
/*
pFilterBox->SetSelectionMode( SINGLE_SELECTION );
pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
*/
sal_Bool bEmpty = sal_False;
TypedScStrCollection aStrings( 128, 128 );
if ( bDataSelect ) // Auswahl-Liste
{
// Liste fuellen
aStrings.SetCaseSensitive( sal_True );
pDoc->GetDataEntries( nCol, nRow, nTab, aStrings );
if ( aStrings.GetCount() == 0 )
bEmpty = sal_True;
}
else // AutoFilter
{
//! wird der Titel ueberhaupt ausgewertet ???
String aString;
pDoc->GetString( nCol, nRow, nTab, aString );
pFilterBox->SetText( aString );
long nMaxText = 0;
// default entries
static const sal_uInt16 nDefIDs[] = { SCSTR_ALLFILTER, SCSTR_TOP10FILTER, SCSTR_STDFILTER };
const sal_uInt16 nDefCount = sizeof(nDefIDs) / sizeof(sal_uInt16);
for (i=0; i<nDefCount; i++)
{
String aEntry( (ScResId) nDefIDs[i] );
pFilterBox->InsertEntry( aEntry );
long nTextWidth = pFilterBox->GetTextWidth( aEntry );
if ( nTextWidth > nMaxText )
nMaxText = nTextWidth;
}
pFilterBox->SetSeparatorPos( nDefCount - 1 );
// get list entries
bool bHasDates = false;
pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
pFilterBox->SetListHasDates(bHasDates);
// check widths of numerical entries (string entries are not included)
// so all numbers are completely visible
sal_uInt16 nCount = aStrings.GetCount();
for (i=0; i<nCount; i++)
{
TypedStrData* pData = aStrings[i];
if ( !pData->IsStrData() ) // only numerical entries
{
long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
if ( nTextWidth > nMaxText )
nMaxText = nTextWidth;
}
}
// add scrollbar width if needed (string entries are counted here)
// (scrollbar is shown if the box is exactly full?)
if ( nCount + nDefCount >= SC_FILTERLISTBOX_LINES )
nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
nMaxText += 4; // for borders
if ( nMaxText > nSizeX )
nSizeX = nMaxText; // just modify width - starting position is unchanged
}
if (!bEmpty)
{
// Position und Groesse an Fenster anpassen
//! vorher Abfrage, ob die Eintraege hineinpassen (Breite)
Size aParentSize = GetParent()->GetOutputSizePixel();
Size aSize( nSizeX, nHeight );
if ( aSize.Height() > aParentSize.Height() )
aSize.Height() = aParentSize.Height();
if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
aPos.Y() = aParentSize.Height() - aSize.Height();
pFilterBox->SetSizePixel( aSize );
pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
pFilterBox->SetUpdateMode(sal_False);
pFilterFloat->SetOutputSizePixel( aSize );
pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
// Listbox fuellen
sal_uInt16 nCount = aStrings.GetCount();
sal_Bool bWait = ( nCount > 100 );
if (bWait)
EnterWait();
for (i=0; i<nCount; i++)
pFilterBox->InsertEntry( aStrings[i]->GetString() );
if (bWait)
LeaveWait();
pFilterBox->SetUpdateMode(sal_True);
}
//! SvLBoxEntry* pSelect = NULL;
sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND;
if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren
{
ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
if (pDBData)
{
ScQueryParam aParam;
pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
sal_Bool bValid = sal_True;
for (SCSIZE j=0; j<MAXQUERY && bValid; j++) // bisherige Filter-Einstellungen
if (aParam.GetEntry(j).bDoQuery)
{
//! Abfrage mit DrawButtons zusammenfassen!
ScQueryEntry& rEntry = aParam.GetEntry(j);
if (j>0)
if (rEntry.eConnect != SC_AND)
bValid = sal_False;
if (rEntry.nField == nCol)
{
if (rEntry.eOp == SC_EQUAL)
{
String* pStr = rEntry.pStr;
if (pStr)
{
nSelPos = pFilterBox->GetEntryPos( *pStr );
//! pSelect = pFilterBox->GetEntry( nPos );
}
}
else if (rEntry.eOp == SC_TOPVAL && rEntry.pStr &&
rEntry.pStr->EqualsAscii("10"))
nSelPos = SC_AUTOFILTER_TOP10;
else
nSelPos = SC_AUTOFILTER_CUSTOM;
}
}
if (!bValid)
nSelPos = SC_AUTOFILTER_CUSTOM;
}
}
else
{
sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr(
nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue();
if ( nIndex )
{
const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
if (pData)
{
TypedStrData* pNew = NULL;
String aDocStr;
pDoc->GetString( nCol, nRow, nTab, aDocStr );
if ( pDoc->HasValueData( nCol, nRow, nTab ) )
{
double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab));
pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE );
}
else
pNew = new TypedStrData( aDocStr, 0.0, SC_STRTYPE_STANDARD );
bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING);
if ( bSortList )
{
sal_uInt16 nStrIndex;
if (aStrings.Search(pNew,nStrIndex))
nSelPos = nStrIndex;
}
else
{
sal_uInt16 nCount = aStrings.GetCount();
for (i = 0; ((i < nCount) && ( LISTBOX_ENTRY_NOTFOUND == nSelPos)); i++)
{
if ( aStrings.Compare(aStrings[i], pNew)==0 )
nSelPos = i;
}
}
delete pNew;
}
}
}
// neu (309): irgendwas muss immer selektiert sein:
if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect)
nSelPos = 0;
// keine leere Auswahl-Liste anzeigen:
if ( bEmpty )
{
DELETEZ(pFilterBox); // war nix
DELETEZ(pFilterFloat);
Sound::Beep(); // bemerkbar machen
}
else
{
// pFilterBox->Show(); // schon vorne
pFilterBox->GrabFocus();
// Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
pFilterBox->SelectEntryPos( nSelPos );
else
{
if (bDataSelect)
pFilterBox->SetNoSelection();
}
pFilterBox->EndInit();
if (!bDataSelect)
{
// AutoFilter (aus MouseButtonDown):
// der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
nMouseStatus = SC_GM_FILTER;
CaptureMouse();
}
}
}
void ScGridWindow::FilterSelect( sal_uLong nSel )
{
String aString;
/*
SvLBoxEntry* pEntry = pFilterBox->GetEntry( nSel );
if (pEntry)
{
SvLBoxString* pStringEntry = (SvLBoxString*) pEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING );
if ( pStringEntry )
aString = pStringEntry->GetText();
}
*/
aString = pFilterBox->GetEntry( static_cast< sal_uInt16 >( nSel ) );
SCCOL nCol = pFilterBox->GetCol();
SCROW nRow = pFilterBox->GetRow();
switch ( pFilterBox->GetMode() )
{
case SC_FILTERBOX_DATASELECT:
ExecDataSelect( nCol, nRow, aString );
break;
case SC_FILTERBOX_FILTER:
ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
break;
case SC_FILTERBOX_SCENARIO:
pViewData->GetView()->UseScenario( aString );
break;
case SC_FILTERBOX_PAGEFIELD:
// first entry is "all"
ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
break;
}
if (pFilterFloat)
pFilterFloat->EndPopupMode();
GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht
}
void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
{
if ( rStr.Len() )
{
SCTAB nTab = pViewData->GetTabNo();
ScViewFunc* pView = pViewData->GetView();
pView->EnterData( nCol, nRow, nTab, rStr );
// #i52307# CellContentChanged is not in EnterData so it isn't called twice
// if the cursor is moved afterwards.
pView->CellContentChanged();
}
}
void ScGridWindow::ExecFilter( sal_uLong nSel,
SCCOL nCol, SCROW nRow,
const String& aValue, bool bCheckForDates )
{
SCTAB nTab = pViewData->GetTabNo();
ScDocument* pDoc = pViewData->GetDocument();
ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
if (pDBData)
{
ScQueryParam aParam;
pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
if (SC_AUTOFILTER_CUSTOM == nSel)
{
SCTAB nAreaTab;
SCCOL nStartCol;
SCROW nStartRow;
SCCOL nEndCol;
SCROW nEndRow;
pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow );
pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab));
pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??
pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
}
else
{
sal_Bool bDeleteOld = sal_False;
SCSIZE nQueryPos = 0;
sal_Bool bFound = sal_False;
if (!aParam.bInplace)
bDeleteOld = sal_True;
if (aParam.bRegExp)
bDeleteOld = sal_True;
for (SCSIZE i=0; i<MAXQUERY && !bDeleteOld; i++) // bisherige Filter-Einstellungen
if (aParam.GetEntry(i).bDoQuery)
{
//! Abfrage mit DrawButtons zusammenfassen!
ScQueryEntry& rEntry = aParam.GetEntry(i);
if (i>0)
if (rEntry.eConnect != SC_AND)
bDeleteOld = sal_True;
if (rEntry.nField == nCol)
{
if (bFound) // diese Spalte zweimal?
bDeleteOld = sal_True;
nQueryPos = i;
bFound = sal_True;
}
if (!bFound)
nQueryPos = i + 1;
}
if (bDeleteOld)
{
SCSIZE nEC = aParam.GetEntryCount();
for (SCSIZE i=0; i<nEC; i++)
aParam.GetEntry(i).Clear();
nQueryPos = 0;
aParam.bInplace = sal_True;
aParam.bRegExp = sal_False;
}
if ( nQueryPos < MAXQUERY || SC_AUTOFILTER_ALL == nSel ) // loeschen geht immer
{
if (nSel)
{
ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
rNewEntry.bDoQuery = sal_True;
rNewEntry.bQueryByString = sal_True;
rNewEntry.nField = nCol;
rNewEntry.bQueryByDate = bCheckForDates;
if ( nSel == SC_AUTOFILTER_TOP10 )
{
rNewEntry.eOp = SC_TOPVAL;
*rNewEntry.pStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("10"));
}
else
{
rNewEntry.eOp = SC_EQUAL;
*rNewEntry.pStr = aValue;
}
if (nQueryPos > 0)
rNewEntry.eConnect = SC_AND;
}
else
{
if (bFound)
aParam.DeleteQuery(nQueryPos);
}
// #100597# end edit mode - like in ScCellShell::ExecuteDB
if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
{
SC_MOD()->InputEnterHandler();
pViewData->GetViewShell()->UpdateInputHandler();
}
pViewData->GetView()->Query( aParam, NULL, sal_True );
pDBData->SetQueryParam( aParam ); // speichern
}
else // "Zuviele Bedingungen"
pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
}
}
else
{
DBG_ERROR("Wo ist der Datenbankbereich?");
}
}
void ScGridWindow::SetPointer( const Pointer& rPointer )
{
nCurrentPointer = 0;
Window::SetPointer( rPointer );
}
void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
{
if (nButtonDown)
{
rDestWin.nButtonDown = nButtonDown;
rDestWin.nMouseStatus = nMouseStatus;
}
if (bRFMouse)
{
rDestWin.bRFMouse = bRFMouse;
rDestWin.bRFSize = bRFSize;
rDestWin.nRFIndex = nRFIndex;
rDestWin.nRFAddX = nRFAddX;
rDestWin.nRFAddY = nRFAddY;
bRFMouse = sal_False;
}
if (nPagebreakMouse)
{
rDestWin.nPagebreakMouse = nPagebreakMouse;
rDestWin.nPagebreakBreak = nPagebreakBreak;
rDestWin.nPagebreakPrev = nPagebreakPrev;
rDestWin.aPagebreakSource = aPagebreakSource;
rDestWin.aPagebreakDrag = aPagebreakDrag;
nPagebreakMouse = SC_PD_NONE;
}
}
sal_Bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, sal_Bool bAction )
{
// MouseEvent buttons must only be checked if bAction==TRUE
// to allow changing the mouse pointer in MouseMove,
// but not start AutoFill with right button (#74229#).
// with bAction==sal_True, SetFillMode / SetDragMode is called
if ( bAction && !rMEvt.IsLeft() )
return sal_False;
sal_Bool bNewPointer = sal_False;
SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
if ( pViewData->IsActive() && !bOleActive )
{
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
// Auto-Fill
ScRange aMarkRange;
if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
{
if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
{
Point aMousePos = rMEvt.GetPosPixel();
if (mpAutoFillRect->IsInside(aMousePos))
{
SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
if (bAction)
{
SCCOL nX = aMarkRange.aEnd.Col();
SCROW nY = aMarkRange.aEnd.Row();
if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
pViewData->SetDragMode(
aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
else
pViewData->SetFillMode(
aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
// #108266# The simple selection must also be recognized when dragging,
// where the Marking flag is set and MarkToSimple won't work anymore.
pViewData->GetMarkData().MarkToSimple();
}
bNewPointer = sal_True;
}
}
}
// Embedded-Rechteck
if (pDoc->IsEmbedded())
{
ScRange aRange;
pDoc->GetEmbedded( aRange );
if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
{
Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
Point aMousePos = rMEvt.GetPosPixel();
if ( bLayoutRTL )
{
aStartPos.X() += 2;
aEndPos.X() += 2;
}
sal_Bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
sal_Bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
if ( bTop || bBottom )
{
SetPointer( Pointer( POINTER_CROSS ) );
if (bAction)
{
sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
pViewData->SetDragMode(
aRange.aStart.Col(), aRange.aStart.Row(),
aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
}
bNewPointer = sal_True;
}
}
}
}
if (!bNewPointer && bAction)
{
// SetPointer( POINTER_ARROW ); // in Fu...
pViewData->ResetFillMode();
}
return bNewPointer;
}
void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
{
nNestedButtonState = SC_NESTEDBUTTON_DOWN;
HandleMouseButtonDown( rMEvt );
if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
{
// #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
// so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
// simulate another MouseButtonUp call, so the selection state is consistent.
nButtonDown = rMEvt.GetButtons();
FakeButtonUp();
if ( IsTracking() )
EndTracking(); // normally done in VCL as part of MouseButtonUp handling
}
nNestedButtonState = SC_NESTEDBUTTON_NONE;
}
void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt )
{
// We have to check if a context menu is shown and we have an UI
// active inplace client. In that case we have to ignore the event.
// Otherwise we would crash (context menu has been
// opened by inplace client and we would deactivate the inplace client,
// the contex menu is closed by VCL asynchronously which in the end
// would work on deleted objects or the context menu has no parent anymore)
// See #126086# and #128122#
SfxViewShell* pViewSh = pViewData->GetViewShell();
SfxInPlaceClient* pClient = pViewSh->GetIPClient();
if ( pClient &&
pClient->IsObjectInPlaceActive() &&
PopupMenu::IsInExecute() )
return;
aCurMousePos = rMEvt.GetPosPixel();
// Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
// in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
#if 0
// merken, dass FilterBox geloescht wird, damit sichergestellt
// ist, dass in diesem Handler nicht an gleicher Stelle wieder
// eine neue geoeffnet wird.
sal_Bool bWasFilterBox = ( pFilterBox != NULL &&
((Window*)pFilterBox)->IsVisible() &&
!pFilterBox->IsDataSelect() );
SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0;
SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0;
#endif
ClickExtern(); // loescht FilterBox, wenn vorhanden
HideNoteMarker(); // Notiz-Anzeige
bEEMouse = sal_False;
ScModule* pScMod = SC_MOD();
if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
{
Sound::Beep();
return;
}
pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell();
sal_Bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen
sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
sal_Bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
sal_Bool bDouble = (rMEvt.GetClicks() == 2);
// DeactivateIP passiert nur noch bei MarkListHasChanged
// im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
// (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
if ( !nButtonDown || !bDouble ) // single (first) click is always valid
nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
// pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
GrabFocus();
// #i31846# need to cancel a double click if the first click has set the "ignore" state,
// but a single (first) click is always valid
if ( nMouseStatus == SC_GM_IGNORE && bDouble )
{
nButtonDown = 0;
nMouseStatus = SC_GM_NONE;
return;
}
if ( bDetective ) // Detektiv-Fuell-Modus
{
if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
{
Point aPos = rMEvt.GetPosPixel();
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
&aPosXItem, &aPosYItem, (void*)0L );
}
nButtonDown = 0;
nMouseStatus = SC_GM_NONE;
return;
}
if (!bDouble)
nMouseStatus = SC_GM_NONE;
if (!bFormulaMode)
{
if ( pViewData->GetActivePart() != eWhich )
pViewData->GetView()->ActivatePart( eWhich );
}
else
{
ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
pSelEng->SetWindow(this);
pSelEng->SetWhich(eWhich);
pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
}
if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
{
Point aPos = rMEvt.GetPosPixel();
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
EditView* pEditView;
SCCOL nEditCol;
SCROW nEditRow;
pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
SCCOL nEndCol = pViewData->GetEditEndCol();
SCROW nEndRow = pViewData->GetEditEndRow();
if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
{
// #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen
if (bFormulaMode) // sonst ist es oben schon passiert
GrabFocus();
pScMod->SetInputMode( SC_INPUT_TABLE );
bEEMouse = sal_True;
bEditMode = pEditView->MouseButtonDown( rMEvt );
return;
}
}
if (pScMod->GetIsWaterCan())
{
//! was is mit'm Mac ???
if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
{
nMouseStatus = SC_GM_WATERUNDO;
return;
}
}
// Reihenfolge passend zum angezeigten Cursor:
// RangeFinder, AutoFill, PageBreak, Drawing
if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) )
{
bRFMouse = sal_True; // die anderen Variablen sind oben initialisiert
if ( pViewData->GetActivePart() != eWhich )
pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ???
// CaptureMouse();
StartTracking();
return;
}
sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True );
if ( bCrossPointer )
{
if ( bDouble )
pViewData->GetView()->FillCrossDblClick();
else
pScMod->InputEnterHandler(); // Autofill etc.
}
if ( !bCrossPointer )
{
nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
&nPagebreakBreak, &nPagebreakPrev );
if (nPagebreakMouse)
{
bPagebreakDrawn = sal_False;
// CaptureMouse();
StartTracking();
PagebreakMove( rMEvt, sal_False );
return;
}
}
if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
{
if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
{
//if (DrawHasMarkedObj())
// pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert
return;
}
pViewData->GetViewShell()->SetDrawShell( sal_False ); // kein Draw-Objekt selektiert
// TestMouse schon oben passiert
}
Point aPos = rMEvt.GetPosPixel();
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
SCTAB nTab = pViewData->GetTabNo();
ScDocument* pDoc = pViewData->GetDocument();
//
// AutoFilter buttons
//
if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
{
SCsCOL nRealPosX;
SCsROW nRealPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nRealPosX, nRealPosY, false );//the real row/col
ScMergeFlagAttr* pRealPosAttr = (ScMergeFlagAttr*)
pDoc->GetAttr( nRealPosX, nRealPosY, nTab, ATTR_MERGE_FLAG );
ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
if( pRealPosAttr->HasAutoFilter() )
{
SC_MOD()->InputEnterHandler();
if (DoAutoFilterButton( nRealPosX, nRealPosY, rMEvt))
return;
}
if( pAttr->HasAutoFilter() )
{
SC_MOD()->InputEnterHandler(); //Add for i85305
if (DoAutoFilterButton( nPosX, nPosY, rMEvt))
return;
}
if (pAttr->HasButton())
{
DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse
return;
}
// List Validity drop-down button
if ( bListValButton )
{
Rectangle aButtonRect = GetListValButtonRect( aListValPos );
if ( aButtonRect.IsInside( aPos ) )
{
DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), sal_True );
nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
CaptureMouse();
return;
}
}
}
//
// scenario selection
//
ScRange aScenRange;
if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
{
DoScenarioMenue( aScenRange );
return;
}
//
// Doppelklick angefangen ?
//
// StopMarking kann aus DrawMouseButtonDown gerufen werden
if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
{
if ( bDouble && !bCrossPointer )
{
if (nMouseStatus == SC_GM_TABDOWN)
nMouseStatus = SC_GM_DBLDOWN;
}
else
nMouseStatus = SC_GM_TABDOWN;
}
//
// Links in Edit-Zellen
//
sal_Bool bAlt = rMEvt.IsMod2();
if ( !bAlt && rMEvt.IsLeft() &&
GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
{
SetPointer( Pointer( POINTER_REFHAND ) );
nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
return;
}
//
// Gridwin - SelectionEngine
//
if ( rMEvt.IsLeft() )
{
ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
pSelEng->SetWindow(this);
pSelEng->SetWhich(eWhich);
pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
// SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
{
if (IsMouseCaptured())
{
// Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
//! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
ReleaseMouse();
StartTracking();
}
pViewData->GetMarkData().SetMarking(sal_True);
return;
}
}
}
void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
{
aCurMousePos = rMEvt.GetPosPixel();
ScDocument* pDoc = pViewData->GetDocument();
ScMarkData& rMark = pViewData->GetMarkData();
// #i41690# detect a MouseButtonUp call from within MouseButtonDown
// (possible through Reschedule from storing an OLE object that is deselected)
if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
nNestedButtonState = SC_NESTEDBUTTON_UP;
if (nButtonDown != rMEvt.GetButtons())
nMouseStatus = SC_GM_IGNORE; // reset und return
nButtonDown = 0;
if (nMouseStatus == SC_GM_IGNORE)
{
nMouseStatus = SC_GM_NONE;
// Selection-Engine: Markieren abbrechen
pViewData->GetView()->GetSelEngine()->Reset();
rMark.SetMarking(sal_False);
if (pViewData->IsAnyFillMode())
{
pViewData->GetView()->StopRefMode();
pViewData->ResetFillMode();
}
StopMarking();
DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
ReleaseMouse();
return;
}
if (nMouseStatus == SC_GM_FILTER)
{
if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
{
if (mpFilterButton.get())
{
bool bFilterActive = IsAutoFilterActive(
pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() );
mpFilterButton->setHasHiddenMember(bFilterActive);
mpFilterButton->setPopupPressed(false);
HideCursor();
mpFilterButton->draw();
ShowCursor();
}
}
nMouseStatus = SC_GM_NONE;
ReleaseMouse();
return; // da muss nix mehr passieren
}
ScModule* pScMod = SC_MOD();
if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
return;
SfxBindings& rBindings = pViewData->GetBindings();
if (bEEMouse && pViewData->HasEditView( eWhich ))
{
EditView* pEditView;
SCCOL nEditCol;
SCROW nEditRow;
pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
pEditView->MouseButtonUp( rMEvt );
if ( rMEvt.IsMiddle() &&
GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
{
// EditView may have pasted from selection
pScMod->InputChanged( pEditView );
}
else
pScMod->InputSelection( pEditView ); // parentheses etc.
pViewData->GetView()->InvalidateAttribs();
rBindings.Invalidate( SID_HYPERLINK_GETLINK );
bEEMouse = sal_False;
return;
}
if (bDPMouse)
{
DPMouseButtonUp( rMEvt ); // resets bDPMouse
return;
}
if (bRFMouse)
{
RFMouseMove( rMEvt, sal_True ); // Range wieder richtigherum
bRFMouse = sal_False;
SetPointer( Pointer( POINTER_ARROW ) );
ReleaseMouse();
return;
}
if (nPagebreakMouse)
{
PagebreakMove( rMEvt, sal_True );
nPagebreakMouse = SC_PD_NONE;
SetPointer( Pointer( POINTER_ARROW ) );
ReleaseMouse();
return;
}
if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
{
::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
pMgr->Undo();
else
Sound::Beep();
return;
}
if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
{
ScTabViewShell* pViewShell = pViewData->GetViewShell();
SfxBindings& rBindings=pViewShell->GetViewFrame()->GetBindings();
rBindings.Invalidate(SID_ATTR_TRANSFORM_WIDTH);
rBindings.Invalidate(SID_ATTR_TRANSFORM_HEIGHT);
rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
rBindings.Invalidate(SID_ATTR_TRANSFORM_ANGLE);
rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_X);
rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_Y);
rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH);
rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT);
return;
}
rMark.SetMarking(sal_False);
SetPointer( Pointer( POINTER_ARROW ) );
if (pViewData->IsFillMode() ||
( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
{
nScFillModeMouseModifier = rMEvt.GetModifier();
SCCOL nStartCol;
SCROW nStartRow;
SCCOL nEndCol;
SCROW nEndRow;
pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
// DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(),
// "Block falsch fuer AutoFill" );
ScRange aDelRange;
sal_Bool bIsDel = pViewData->GetDelMark( aDelRange );
ScViewFunc* pView = pViewData->GetView();
pView->StopRefMode();
pViewData->ResetFillMode();
pView->GetFunctionSet()->SetAnchorFlag( sal_False ); // #i5819# don't use AutoFill anchor flag for selection
if ( bIsDel )
{
pView->MarkRange( aDelRange, sal_False );
pView->DeleteContents( IDF_CONTENTS );
SCTAB nTab = pViewData->GetTabNo();
ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
if ( aBlockRange != aDelRange )
{
if ( aDelRange.aStart.Row() == nStartRow )
aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
else
aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
pView->MarkRange( aBlockRange, sal_False );
}
}
else
pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
}
else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
{
SCTAB nTab = pViewData->GetTabNo();
SCCOL nStartCol;
SCROW nStartRow;
SCCOL nEndCol;
SCROW nEndRow;
pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
SCCOL nFillCol = pViewData->GetRefEndX();
SCROW nFillRow = pViewData->GetRefEndY();
ScAddress aEndPos( nFillCol, nFillRow, nTab );
ScTabView* pView = pViewData->GetView();
pView->StopRefMode();
pViewData->ResetFillMode();
pView->GetFunctionSet()->SetAnchorFlag( sal_False );
if ( aEndPos != aBlockRange.aEnd )
{
pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, sal_False );
pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
}
}
else if (pViewData->IsAnyFillMode())
{
// Embedded-Area has been changed
ScTabView* pView = pViewData->GetView();
pView->StopRefMode();
pViewData->ResetFillMode();
pView->GetFunctionSet()->SetAnchorFlag( sal_False );
pViewData->GetDocShell()->UpdateOle(pViewData);
}
sal_Bool bRefMode = pViewData->IsRefMode();
if (bRefMode)
pScMod->EndReference();
//
// Giesskannen-Modus (Gestalter)
//
if (pScMod->GetIsWaterCan())
{
// Abfrage auf Undo schon oben
ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
(pViewData->GetDocument()->
GetStyleSheetPool());
if ( pStylePool )
{
SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
pStylePool->GetActualStyleSheet();
if ( pStyleSheet )
{
SfxStyleFamily eFamily = pStyleSheet->GetFamily();
switch ( eFamily )
{
case SFX_STYLE_FAMILY_PARA:
pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
pViewData->GetView()->DoneBlockMode();
break;
case SFX_STYLE_FAMILY_PAGE:
pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
pStyleSheet->GetName() );
ScPrintFunc( pViewData->GetDocShell(),
pViewData->GetViewShell()->GetPrinter(sal_True),
pViewData->GetTabNo() ).UpdatePages();
rBindings.Invalidate( SID_STATUS_PAGESTYLE );
break;
default:
break;
}
}
}
}
ScDBFunc* pView = pViewData->GetView();
ScDocument* pBrushDoc = pView->GetBrushDocument();
if ( pBrushDoc )
{
pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
if ( !pView->IsPaintBrushLocked() )
pView->ResetBrushDocument(); // invalidates pBrushDoc pointer
}
//
// double click (only left button)
//
sal_Bool bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
{
// data pilot table
Point aPos = rMEvt.GetPosPixel();
SCsCOL nPosX;
SCsROW nPosY;
SCTAB nTab = pViewData->GetTabNo();
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
{
ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
// Check for header drill-down first.
sheet::DataPilotTableHeaderData aData;
pDPObj->GetHeaderPositionData(aCellPos, aData);
if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
{
sal_uInt16 nDummy;
if ( pView->HasSelectionForDrillDown( nDummy ) )
{
// execute slot to show dialog
pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
}
else
{
// toggle single entry
ScDPObject aNewObj( *pDPObj );
pDPObj->ToggleDetails( aData, &aNewObj );
ScDBDocFunc aFunc( *pViewData->GetDocShell() );
aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False );
pViewData->GetView()->CursorPosChanged(); // shells may be switched
}
}
else
{
// Check if the data area is double-clicked.
Sequence<sheet::DataPilotFieldFilter> aFilters;
if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
else
Sound::Beep(); // nothing to expand/collapse/show
}
return;
}
// Check for cell protection attribute.
ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
bool bEditAllowed = true;
if ( pProtect && pProtect->isProtected() )
{
bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
if ( bSkipProtected && bSkipUnprotected )
bEditAllowed = false;
else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
bEditAllowed = false;
}
if ( bEditAllowed )
{
// edit cell contents
pViewData->GetViewShell()->UpdateInputHandler();
pScMod->SetInputMode( SC_INPUT_TABLE );
if (pViewData->HasEditView(eWhich))
{
// Text-Cursor gleich an die geklickte Stelle setzen
EditView* pEditView = pViewData->GetEditView( eWhich );
MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
pEditView->MouseButtonDown( aEditEvt );
pEditView->MouseButtonUp( aEditEvt );
}
}
return;
}
//
// Links in edit cells
//
sal_Bool bAlt = rMEvt.IsMod2();
if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
{
// beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
String aName, aUrl, aTarget;
if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
{
nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
ScGlobal::OpenURL( aUrl, aTarget );
// fire worksheet_followhyperlink event
uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor();
if( xVbaEvents.is() ) try
{
Point aPos = rMEvt.GetPosPixel();
SCsCOL nPosX;
SCsROW nPosY;
SCTAB nTab = pViewData->GetTabNo();
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
ScBaseCell* pCell = NULL;
if( lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ) )
{
ScAddress aCellPos( nPosX, nPosY, nTab );
uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) );
uno::Sequence< uno::Any > aArgs(1);
aArgs[0] <<= xCell;
xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs );
}
}
catch( uno::Exception& )
{
}
return;
}
}
//
// Gridwin - SelectionEngine
//
// SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
// sal_True for any call, so IsLeft must be checked here, too.
if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
{
// rMark.MarkToSimple();
pViewData->GetView()->UpdateAutoFillMark();
SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
sal_Bool bFormulaMode = pScMod->IsFormulaMode();
DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
// #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
// multiple selection, so the argument string completely describes the selection,
// and executing the slot won't change the existing selection (executing the slot
// here and from a recorded macro is treated equally)
if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
{
String aAddr; // CurrentCell
if( rMark.IsMarked() )
{
// sal_Bool bKeep = rMark.IsMultiMarked(); //! wohin damit ???
ScRange aScRange;
rMark.GetMarkArea( aScRange );
aScRange.Format( aAddr, SCR_ABS );
if ( aScRange.aStart == aScRange.aEnd )
{
// make sure there is a range selection string even for a single cell
String aSingle = aAddr;
aAddr.Append( (sal_Char) ':' );
aAddr.Append( aSingle );
}
//! SID_MARKAREA gibts nicht mehr ???
//! was passiert beim Markieren mit dem Cursor ???
}
else // nur Cursor bewegen
{
ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
aScAddress.Format( aAddr, SCA_ABS );
}
SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
&aPosItem, (void*)0L );
pViewData->GetView()->InvalidateAttribs();
}
pViewData->GetViewShell()->SelectionChanged();
return;
}
}
void ScGridWindow::FakeButtonUp()
{
if ( nButtonDown )
{
MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
MouseButtonUp( aEvent );
}
}
void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
{
aCurMousePos = rMEvt.GetPosPixel();
if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
HideNoteMarker();
ScModule* pScMod = SC_MOD();
if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
return;
// Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
// nicht anders mit:
if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
{
bEEMouse = sal_False;
nButtonDown = 0;
nMouseStatus = SC_GM_NONE;
return;
}
if (nMouseStatus == SC_GM_IGNORE)
return;
if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
return;
if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus
{
SetPointer( Pointer( POINTER_FILL ) );
return;
}
if (nMouseStatus == SC_GM_FILTER && pFilterBox)
{
Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
{
nButtonDown = 0;
nMouseStatus = SC_GM_NONE;
if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
{
if (mpFilterButton.get())
{
mpFilterButton->setHasHiddenMember(false);
mpFilterButton->setPopupPressed(false);
HideCursor();
mpFilterButton->draw();
ShowCursor();
}
}
ReleaseMouse();
pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
return;
}
}
sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
if (bEEMouse && pViewData->HasEditView( eWhich ))
{
EditView* pEditView;
SCCOL nEditCol;
SCROW nEditRow;
pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
pEditView->MouseMove( rMEvt );
return;
}
if (bDPMouse)
{
DPMouseMove( rMEvt );
return;
}
if (bRFMouse)
{
RFMouseMove( rMEvt, sal_False );
return;
}
if (nPagebreakMouse)
{
PagebreakMove( rMEvt, sal_False );
return;
}
// anderen Mauszeiger anzeigen?
sal_Bool bEditMode = pViewData->HasEditView(eWhich);
//! Testen ob RefMode-Dragging !!!
if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
{
Point aPos = rMEvt.GetPosPixel();
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
EditView* pEditView;
SCCOL nEditCol;
SCROW nEditRow;
pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
SCCOL nEndCol = pViewData->GetEditEndCol();
SCROW nEndRow = pViewData->GetEditEndRow();
if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
{
// Field can only be URL field
sal_Bool bAlt = rMEvt.IsMod2();
if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
SetPointer( Pointer( POINTER_REFHAND ) );
else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
else
SetPointer( Pointer( POINTER_TEXT ) );
return;
}
}
sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
if (bWater)
SetPointer( Pointer(POINTER_FILL) );
if (!bWater)
{
sal_Bool bCross = sal_False;
// Range-Finder
sal_Bool bCorner;
if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
{
if (bCorner)
SetPointer( Pointer( POINTER_CROSS ) );
else
SetPointer( Pointer( POINTER_HAND ) );
bCross = sal_True;
}
// Page-Break-Modus
sal_uInt16 nBreakType;
if ( !nButtonDown && pViewData->IsPagebreakMode() &&
( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
{
PointerStyle eNew = POINTER_ARROW;
switch ( nBreakType )
{
case SC_PD_RANGE_L:
case SC_PD_RANGE_R:
case SC_PD_BREAK_H:
eNew = POINTER_ESIZE;
break;
case SC_PD_RANGE_T:
case SC_PD_RANGE_B:
case SC_PD_BREAK_V:
eNew = POINTER_SSIZE;
break;
case SC_PD_RANGE_TL:
case SC_PD_RANGE_BR:
eNew = POINTER_SESIZE;
break;
case SC_PD_RANGE_TR:
case SC_PD_RANGE_BL:
eNew = POINTER_NESIZE;
break;
}
SetPointer( Pointer( eNew ) );
bCross = sal_True;
}
// Fill-Cursor anzeigen ?
if ( !bFormulaMode && !nButtonDown )
if (TestMouse( rMEvt, sal_False ))
bCross = sal_True;
if ( nButtonDown && pViewData->IsAnyFillMode() )
{
SetPointer( Pointer( POINTER_CROSS ) );
bCross = sal_True;
nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
}
if (!bCross)
{
sal_Bool bAlt = rMEvt.IsMod2();
if (bEditMode) // Edit-Mode muss zuerst kommen!
SetPointer( Pointer( POINTER_ARROW ) );
else if ( !bAlt && !nButtonDown &&
GetEditUrl(rMEvt.GetPosPixel()) )
SetPointer( Pointer( POINTER_REFHAND ) );
else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
return;
}
}
if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
return;
}
void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
{
rEvent.Modifiers = 0;
if ( rEvt.IsShift() )
rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
if ( rEvt.IsMod1() )
rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
if ( rEvt.IsMod2() )
rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
if ( rEvt.IsMod3() )
rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
rEvent.Buttons = 0;
if ( rEvt.IsLeft() )
rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
if ( rEvt.IsRight() )
rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
if ( rEvt.IsMiddle() )
rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
rEvent.X = rEvt.GetPosPixel().X();
rEvent.Y = rEvt.GetPosPixel().Y();
rEvent.ClickCount = rEvt.GetClicks();
rEvent.PopupTrigger = sal_False;
}
long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
{
bool bDone = false;
sal_uInt16 nType = rNEvt.GetType();
if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
{
Window* pWindow = rNEvt.GetWindow();
if (pWindow == this && pViewData)
{
SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
if (pViewFrame)
{
com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController();
if (xController.is())
{
ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
if (pImp && pImp->IsMouseListening())
{
::com::sun::star::awt::MouseEvent aEvent;
lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
if ( rNEvt.GetWindow() )
aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
if ( nType == EVENT_MOUSEBUTTONDOWN)
bDone = pImp->MousePressed( aEvent );
else
bDone = pImp->MouseReleased( aEvent );
}
}
}
}
}
if (bDone) // event consumed by a listener
{
if ( nType == EVENT_MOUSEBUTTONDOWN )
{
const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent();
if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 )
{
// If a listener returned true for a right-click call, also prevent opening the context menu
// (this works only if the context menu is opened on mouse-down)
nMouseStatus = SC_GM_IGNORE;
}
}
return 1;
}
else
return Window::PreNotify( rNEvt );
}
void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
{
// Weil die SelectionEngine kein Tracking kennt, die Events nur auf
// die verschiedenen MouseHandler verteilen...
const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
{
if (!pViewData->GetView()->IsInActivatePart())
{
if (bDPMouse)
bDPMouse = sal_False; // gezeichnet wird per bDragRect
if (bDragRect)
{
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
bDragRect = sal_False;
UpdateDragRectOverlay();
}
if (bRFMouse)
{
RFMouseMove( rMEvt, sal_True ); // richtig abbrechen geht dabei nicht...
bRFMouse = sal_False;
}
if (nPagebreakMouse)
{
// if (bPagebreakDrawn)
// DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
// aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
bPagebreakDrawn = sal_False;
UpdateDragRectOverlay();
nPagebreakMouse = SC_PD_NONE;
}
SetPointer( Pointer( POINTER_ARROW ) );
StopMarking();
MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
sal_Bool bRefMode = pViewData->IsRefMode();
if (bRefMode)
SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen
}
}
else if ( rTEvt.IsTrackingEnded() )
{
// MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
// Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
// abgebrochen wurde.
MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
MouseButtonUp( aUpEvt );
}
else
MouseMove( rMEvt );
}
void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
{
if ( pFilterBox || nPagebreakMouse )
return;
HideNoteMarker();
CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
if (bEEMouse && pViewData->HasEditView( eWhich ))
{
EditView* pEditView;
SCCOL nEditCol;
SCROW nEditRow;
pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
// #63263# don't remove the edit view while switching views
ScModule* pScMod = SC_MOD();
pScMod->SetInEditCommand( sal_True );
pEditView->Command( aDragEvent );
ScInputHandler* pHdl = pScMod->GetInputHdl();
if (pHdl)
pHdl->DataChanged();
pScMod->SetInEditCommand( sal_False );
if (!pViewData->IsActive()) // dropped to different view?
{
ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
if ( pViewHdl && pViewData->HasEditView( eWhich ) )
{
pViewHdl->CancelHandler();
ShowCursor(); // missing from KillEditView
}
}
}
else
if ( !DrawCommand(aDragEvent) )
pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
}
void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
{
SCCOL nCol = pViewData->GetCurX();
SCROW nRow = pViewData->GetCurY();
Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True );
aEditArea.Right() = aEditArea.Left();
aEditArea = pWin->PixelToLogic( aEditArea );
pWin->SetCursorRect( &aEditArea );
}
void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt )
{
// The command event is send to the window after a possible context
// menu from an inplace client is closed. Now we have the chance to
// deactivate the inplace client without any problem regarding parent
// windows and code on the stack.
// For more information, see #126086# and #128122#
sal_uInt16 nCmd = rCEvt.GetCommand();
ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
if ( pClient &&
pClient->IsObjectInPlaceActive() &&
nCmd == COMMAND_CONTEXTMENU )
{
pTabViewSh->DeactivateOle();
return;
}
ScModule* pScMod = SC_MOD();
DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
nCmd == COMMAND_ENDEXTTEXTINPUT ||
nCmd == COMMAND_EXTTEXTINPUT ||
nCmd == COMMAND_CURSORPOS )
{
sal_Bool bEditView = pViewData->HasEditView( eWhich );
if (!bEditView)
{
// only if no cell editview is active, look at drawview
SdrView* pSdrView = pViewData->GetView()->GetSdrView();
if ( pSdrView )
{
OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
if ( pOlView && pOlView->GetWindow() == this )
{
pOlView->Command( rCEvt );
return; // done
}
}
}
if ( nCmd == COMMAND_CURSORPOS && !bEditView )
{
// #88458# CURSORPOS may be called without following text input,
// to set the input method window position
// -> input mode must not be started,
// manually calculate text insert position if not in input mode
lcl_SetTextCursorPos( pViewData, eWhich, this );
return;
}
ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
if ( pHdl )
{
pHdl->InputCommand( rCEvt, sal_True );
return; // done
}
Window::Command( rCEvt );
return;
}
if ( nCmd == COMMAND_VOICE )
{
// Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist,
// also muss es eine EditView oder ein editiertes Zeichenobjekt geben
ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
if ( pHdl && pViewData->HasEditView( eWhich ) )
{
EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
pHdl->DataChanging();
pEditView->Command( rCEvt );
pHdl->DataChanged();
return; // erledigt
}
SdrView* pSdrView = pViewData->GetView()->GetSdrView();
if ( pSdrView )
{
OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
if ( pOlView && pOlView->GetWindow() == this )
{
pOlView->Command( rCEvt );
return; // erledigt
}
}
Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
return;
}
if ( nCmd == COMMAND_PASTESELECTION )
{
if ( bEEMouse )
{
// EditEngine handles selection in MouseButtonUp - no action
// needed in command handler
}
else
{
PasteSelection( rCEvt.GetMousePosPixel() );
}
return;
}
if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
{
// #i55929# Font and font size state depends on input language if nothing is selected,
// so the slots have to be invalidated when the input language is changed.
SfxBindings& rBindings = pViewData->GetBindings();
rBindings.Invalidate( SID_ATTR_CHAR_FONT );
rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
return;
}
if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
{
sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
if (!bDone)
Window::Command(rCEvt);
return;
}
// #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
sal_Bool bDisable = pScMod->IsFormulaMode() ||
pScMod->IsModalMode(pViewData->GetSfxDocShell());
if (bDisable)
return;
if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
{
sal_Bool bMouse = rCEvt.IsMouseEvent();
if ( bMouse && nMouseStatus == SC_GM_IGNORE )
return;
if (pViewData->IsAnyFillMode())
{
pViewData->GetView()->StopRefMode();
pViewData->ResetFillMode();
}
ReleaseMouse();
StopMarking();
Point aPosPixel = rCEvt.GetMousePosPixel();
Point aMenuPos = aPosPixel;
if ( bMouse )
{
SCsCOL nCellX = -1;
SCsROW nCellY = -1;
pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
bool bSelectAllowed = true;
if ( pProtect && pProtect->isProtected() )
{
// This sheet is protected. Check if a context menu is allowed on this cell.
bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
if (bCellProtected)
bSelectAllowed = bSelProtected;
else
bSelectAllowed = bSelUnprotected;
}
if (!bSelectAllowed)
// Selecting this cell is not allowed, neither is context menu.
return;
// #i18735# First select the item under the mouse pointer.
// This can change the selection, and the view state (edit mode, etc).
SelectForContextMenu( aPosPixel, nCellX, nCellY );
}
sal_Bool bDone = sal_False;
sal_Bool bEdit = pViewData->HasEditView(eWhich);
if ( !bEdit )
{
// Edit-Zelle mit Spelling-Errors ?
if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) )
{
// GetEditUrlOrError hat den Cursor schon bewegt
pScMod->SetInputMode( SC_INPUT_TABLE );
bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" );
}
}
if ( bEdit )
{
EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
if ( !bMouse )
{
Cursor* pCur = pEditView->GetCursor();
if ( pCur )
{
Point aLogicPos = pCur->GetPos();
// use the position right of the cursor (spell popup is opened if
// the cursor is before the word, but not if behind it)
aLogicPos.X() += pCur->GetWidth();
aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
aMenuPos = LogicToPixel( aLogicPos );
}
}
// if edit mode was just started above, online spelling may be incomplete
pEditView->GetEditEngine()->CompleteOnlineSpelling();
// IsCursorAtWrongSpelledWord could be used for !bMouse
// if there was a corresponding ExecuteSpellPopup call
if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
{
// Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
// vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
// (Bug #40968#)
ScInputHandler* pHdl = pScMod->GetInputHdl();
if (pHdl)
pHdl->SetModified();
Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
bDone = sal_True;
}
}
else if ( !bMouse )
{
// non-edit menu by keyboard -> use lower right of cell cursor position
SCCOL nCurX = pViewData->GetCurX();
SCROW nCurY = pViewData->GetCurY();
aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True );
long nSizeXPix;
long nSizeYPix;
pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
aMenuPos.X() += nSizeXPix;
aMenuPos.Y() += nSizeYPix;
if (pViewData)
{
ScTabViewShell* pViewSh = pViewData->GetViewShell();
if (pViewSh)
{
// Is a draw object selected?
SdrView* pDrawView = pViewSh->GetSdrView();
if (pDrawView && pDrawView->AreObjectsMarked())
{
// #100442#; the conext menu should open in the middle of the selected objects
Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
aMenuPos = aSelectRect.Center();
}
}
}
}
if (!bDone)
{
SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
}
}
}
void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
{
// #i18735# if the click was outside of the current selection,
// the cursor is moved or an object at the click position selected.
// (see SwEditWin::SelectMenuPosition in Writer)
ScTabView* pView = pViewData->GetView();
ScDrawView* pDrawView = pView->GetScDrawView();
// check cell edit mode
if ( pViewData->HasEditView(eWhich) )
{
ScModule* pScMod = SC_MOD();
SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
SCROW nEditStartRow = pViewData->GetEditViewRow();
SCCOL nEditEndCol = pViewData->GetEditEndCol();
SCROW nEditEndRow = pViewData->GetEditEndRow();
if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
{
// handle selection within the EditView
EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
EditEngine* pEditEngine = pEditView->GetEditEngine();
Rectangle aOutputArea = pEditView->GetOutputArea();
Rectangle aVisArea = pEditView->GetVisArea();
Point aTextPos = PixelToLogic( rPosPixel );
if ( pEditEngine->IsVertical() ) // have to manually transform position
{
aTextPos -= aOutputArea.TopRight();
long nTemp = -aTextPos.X();
aTextPos.X() = aTextPos.Y();
aTextPos.Y() = nTemp;
}
else
aTextPos -= aOutputArea.TopLeft();
aTextPos += aVisArea.TopLeft(); // position in the edit document
EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
ESelection aSelection = pEditView->GetSelection();
aSelection.Adjust(); // needed for IsLess/IsGreater
if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
{
// clicked outside the selected text - deselect and move text cursor
MouseEvent aEvent( rPosPixel );
pEditView->MouseButtonDown( aEvent );
pEditView->MouseButtonUp( aEvent );
pScMod->InputSelection( pEditView );
}
return; // clicked within the edit view - keep edit mode
}
else
{
// outside of the edit view - end edit mode, regardless of cell selection, then continue
pScMod->InputEnterHandler();
}
}
// check draw text edit mode
Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
{
OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
Rectangle aOutputArea = pOlView->GetOutputArea();
if ( aOutputArea.IsInside( aLogicPos ) )
{
// handle selection within the OutlinerView
Outliner* pOutliner = pOlView->GetOutliner();
const EditEngine& rEditEngine = pOutliner->GetEditEngine();
Rectangle aVisArea = pOlView->GetVisArea();
Point aTextPos = aLogicPos;
if ( pOutliner->IsVertical() ) // have to manually transform position
{
aTextPos -= aOutputArea.TopRight();
long nTemp = -aTextPos.X();
aTextPos.X() = aTextPos.Y();
aTextPos.Y() = nTemp;
}
else
aTextPos -= aOutputArea.TopLeft();
aTextPos += aVisArea.TopLeft(); // position in the edit document
EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
ESelection aSelection = pOlView->GetSelection();
aSelection.Adjust(); // needed for IsLess/IsGreater
if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
{
// clicked outside the selected text - deselect and move text cursor
// use DrawView to allow extra handling there (none currently)
MouseEvent aEvent( rPosPixel );
pDrawView->MouseButtonDown( aEvent, this );
pDrawView->MouseButtonUp( aEvent, this );
}
return; // clicked within the edit area - keep edit mode
}
else
{
// Outside of the edit area - end text edit mode, then continue.
// DrawDeselectAll also ends text edit mode and updates the shells.
// If the click was on the edited object, it will be selected again below.
pView->DrawDeselectAll();
}
}
// look for existing selection
sal_Bool bHitSelected = sal_False;
if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
{
// clicked on selected object -> don't change anything
bHitSelected = sal_True;
}
else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
{
// clicked on selected cell -> don't change anything
bHitSelected = sal_True;
}
// select drawing object or move cell cursor
if ( !bHitSelected )
{
sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
sal_Bool bHitDraw = sal_False;
if ( pDrawView )
{
pDrawView->UnmarkAllObj();
// Unlock the Internal Layer in order to activate the context menu.
// re-lock in ScDrawView::MarkListHasChanged()
lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
bHitDraw = pDrawView->MarkObj( aLogicPos );
// draw shell is activated in MarkListHasChanged
}
if ( !bHitDraw )
{
pView->Unmark();
pView->SetCursor(nCellX, nCellY);
if ( bWasDraw )
pViewData->GetViewShell()->SetDrawShell( sal_False ); // switch shells
}
}
}
void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
{
// #96965# Cursor control for ref input dialog
if( SC_MOD()->IsRefDialogOpen() )
{
const KeyCode& rKeyCode = rKEvt.GetKeyCode();
if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
{
SC_MOD()->EndReference();
}
else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
{
ScRange aRef(
pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
}
pViewData->GetViewShell()->SelectionChanged();
return ;
}
// wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
else if( !pViewData->IsAnyFillMode() )
{
// query for existing note marker before calling ViewShell's keyboard handling
// which may remove the marker
sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
ScTabViewShell* pViewSh = pViewData->GetViewShell();
if (pViewData->GetDocShell()->GetProgress())
return;
if (DrawKeyInput(rKEvt))
{
const KeyCode& rKeyCode = rKEvt.GetKeyCode();
if (rKeyCode.GetCode() == KEY_DOWN
|| rKeyCode.GetCode() == KEY_UP
|| rKeyCode.GetCode() == KEY_LEFT
|| rKeyCode.GetCode() == KEY_RIGHT)
{
ScTabViewShell* pViewShell = pViewData->GetViewShell();
SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings();
rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
}
return;
}
if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
{ //! DrawShell abfragen !!!
if (pViewSh->TabKeyInput(rKEvt))
return;
}
else
if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
return;
KeyCode aCode = rKEvt.GetKeyCode();
if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
{
if ( bHadKeyMarker )
HideNoteMarker();
else
pViewSh->Escape();
return;
}
if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
{
// ctrl-F1 shows or hides the note or redlining info for the cursor position
// (hard-coded because F1 can't be configured)
if ( bHadKeyMarker )
HideNoteMarker(); // hide when previously visible
else
ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True );
return;
}
}
Window::KeyInput(rKEvt);
}
void ScGridWindow::StopMarking()
{
DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
if (nButtonDown)
{
pViewData->GetMarkData().SetMarking(sal_False);
nMouseStatus = SC_GM_IGNORE;
}
}
void ScGridWindow::UpdateInputContext()
{
sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly();
sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
// when font from InputContext is used,
// it must be taken from the cursor position's cell attributes
InputContext aContext;
aContext.SetOptions( nOptions );
SetInputContext( aContext );
}
//--------------------------------------------------------
// sensitiver Bereich (Pixel)
#define SCROLL_SENSITIVE 20
sal_Bool ScGridWindow::DropScroll( const Point& rMousePos )
{
/* doch auch auf nicht aktiven Views...
if ( !pViewData->IsActive() )
return sal_False;
*/
SCsCOL nDx = 0;
SCsROW nDy = 0;
Size aSize = GetOutputSizePixel();
if (aSize.Width() > SCROLL_SENSITIVE * 3)
{
if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
nDx = -1;
if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
&& pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
nDx = 1;
}
if (aSize.Height() > SCROLL_SENSITIVE * 3)
{
if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
nDy = -1;
if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
&& pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
nDy = 1;
}
if ( nDx != 0 || nDy != 0 )
{
// if (bDragRect)
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
if ( nDx != 0 )
pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
if ( nDy != 0 )
pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
// if (bDragRect)
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
}
return sal_False;
}
sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
{
// Testet, ob bei eingeschalteten RedLining,
// bei einem Drop ein Scenario betroffen ist.
sal_Bool bReturn = sal_False;
SCTAB nTab = aDragRange.aStart.Tab();
SCTAB nTabCount = pDoc->GetTableCount();
if(pDoc->GetChangeTrack()!=NULL)
{
if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
{
bReturn = sal_True;
}
else
{
for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
{
if(pDoc->HasScenarioRange(i, aDragRange))
{
bReturn = sal_True;
break;
}
}
}
}
return bReturn;
}
ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
{
SCCOL nCol1 = nPosX;
SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
if ( nCol2 > MAXCOL )
{
nCol1 -= nCol2 - MAXCOL;
nCol2 = MAXCOL;
}
SCROW nRow1 = nPosY;
SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
if ( nRow2 > MAXROW )
{
nRow1 -= nRow2 - MAXROW;
nRow2 = MAXROW;
}
return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
}
//--------------------------------------------------------
extern sal_Bool bPasteIsDrop; // viewfun4 -> move to header
extern sal_Bool bPasteIsMove; // viewfun7 -> move to header
//--------------------------------------------------------
sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
{
if ( rEvt.mbLeaving )
{
// if (bDragRect)
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
bDragRect = sal_False;
UpdateDragRectOverlay();
return rEvt.mnAction;
}
const ScDragData& rData = SC_MOD()->GetDragData();
if ( rData.pCellTransfer )
{
// Don't move source that would include filtered rows.
if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
{
if (bDragRect)
{
bDragRect = sal_False;
UpdateDragRectOverlay();
}
return DND_ACTION_NONE;
}
Point aPos = rEvt.maPosPixel;
ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
ScDocument* pThisDoc = pViewData->GetDocument();
if (pSourceDoc == pThisDoc)
{
if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) )
{
if (bDragRect) // Rechteck loeschen
{
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
bDragRect = sal_False;
UpdateDragRectOverlay();
}
//! highlight chart? (selection border?)
sal_Int8 nRet = rEvt.mnAction;
//! if ( rEvt.GetAction() == DROP_LINK )
//! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart
return nRet;
}
}
//! else
//! if ( rEvt.GetAction() == DROP_MOVE )
//! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY
if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
{
sal_Bool bOk = pThisDoc->IsDocEditable();
return bOk ? rEvt.mnAction : 0; // don't draw selection frame
}
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
ScRange aSourceRange = rData.pCellTransfer->GetRange();
SCCOL nSourceStartX = aSourceRange.aStart.Col();
SCROW nSourceStartY = aSourceRange.aStart.Row();
SCCOL nSourceEndX = aSourceRange.aEnd.Col();
SCROW nSourceEndY = aSourceRange.aEnd.Row();
SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
if ( rEvt.mnAction != DND_ACTION_MOVE )
nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
if (nNewDragX<0) nNewDragX=0;
if (nNewDragX+(nSizeX-1) > MAXCOL)
nNewDragX = MAXCOL-(nSizeX-1);
SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
if (nNewDragY<0) nNewDragY=0;
if (nNewDragY+(nSizeY-1) > MAXROW)
nNewDragY = MAXROW-(nSizeY-1);
// don't break scenario ranges, don't drop on filtered
SCTAB nTab = pViewData->GetTabNo();
ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
{
if (bDragRect)
{
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
bDragRect = sal_False;
UpdateDragRectOverlay();
}
return DND_ACTION_NONE;
}
InsCellCmd eDragInsertMode = INS_NONE;
Window::PointerState aState = GetPointerState();
// check for datapilot item sorting
ScDPObject* pDPObj = NULL;
if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
{
// drop on DataPilot table: sort or nothing
bool bDPSort = false;
if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
{
sheet::DataPilotTableHeaderData aDestData;
pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
// look through the source range
for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
{
sheet::DataPilotTableHeaderData aSourceData;
pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() )
bValid = false; // empty (subtotal) or different field
}
if ( bValid )
{
sal_Bool bIsDataLayout;
String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
if ( pDim )
{
ScRange aOutRange = pDPObj->GetOutRange();
sal_uInt16 nOrient = pDim->GetOrientation();
if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
{
eDragInsertMode = INS_CELLSRIGHT;
nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
bDPSort = true;
}
else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
{
eDragInsertMode = INS_CELLSDOWN;
nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
bDPSort = true;
}
}
}
}
if ( !bDPSort )
{
// no valid sorting in a DataPilot table -> disallow
if ( bDragRect )
{
bDragRect = sal_False;
UpdateDragRectOverlay();
}
return DND_ACTION_NONE;
}
}
else if ( aState.mnState & KEY_MOD2 )
{
if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
{
long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
if ( nDeltaX <= nDeltaY )
{
eDragInsertMode = INS_CELLSDOWN;
}
else
{
eDragInsertMode = INS_CELLSRIGHT;
}
if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
{
if ( bDragRect )
{
bDragRect = sal_False;
UpdateDragRectOverlay();
}
return DND_ACTION_NONE;
}
}
else
{
if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
{
eDragInsertMode = INS_CELLSDOWN;
}
else
{
eDragInsertMode = INS_CELLSRIGHT;
}
}
}
if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
!bDragRect || eDragInsertMode != meDragInsertMode )
{
// if (bDragRect)
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
nDragStartX = nNewDragX;
nDragStartY = nNewDragY;
nDragEndX = nDragStartX+nSizeX-1;
nDragEndY = nDragStartY+nSizeY-1;
bDragRect = sal_True;
meDragInsertMode = eDragInsertMode;
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
UpdateDragRectOverlay();
// show target position as tip help
#if 0
if (Help::IsQuickHelpEnabled())
{
ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab );
String aHelpStr;
aRange.Format( aHelpStr, SCA_VALID ); // non-3D
Point aPos = Pointer::GetPosPixel();
sal_uInt16 nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT;
Rectangle aRect( aPos, aPos );
Help::ShowQuickHelp(aRect, aHelpStr, nAlign);
}
#endif
}
}
return rEvt.mnAction;
}
sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
{
const ScDragData& rData = SC_MOD()->GetDragData();
if ( rEvt.mbLeaving )
{
DrawMarkDropObj( NULL );
if ( rData.pCellTransfer )
return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
else
return rEvt.mnAction;
}
if ( pViewData->GetDocShell()->IsReadOnly() )
return DND_ACTION_NONE;
sal_Int8 nRet = DND_ACTION_NONE;
if (rData.pCellTransfer)
{
ScRange aSource = rData.pCellTransfer->GetRange();
if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
DropScroll( rEvt.maPosPixel );
nRet = AcceptPrivateDrop( rEvt );
}
else
{
if ( rData.aLinkDoc.Len() )
{
String aThisName;
ScDocShell* pDocSh = pViewData->GetDocShell();
if (pDocSh && pDocSh->HasName())
aThisName = pDocSh->GetMedium()->GetName();
if ( rData.aLinkDoc != aThisName )
nRet = rEvt.mnAction;
}
else if (rData.aJumpTarget.Len())
{
// internal bookmarks (from Navigator)
// local jumps from an unnamed document are possible only within a document
if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
nRet = rEvt.mnAction;
}
else
{
sal_Int8 nMyAction = rEvt.mnAction;
// clear DND_ACTION_LINK when other actions are set. The usage below cannot handle
// multiple set values
if((nMyAction & DND_ACTION_LINK) && (nMyAction & (DND_ACTION_COPYMOVE)))
{
nMyAction &= ~DND_ACTION_LINK;
}
if ( !rData.pDrawTransfer ||
!IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
nMyAction = DND_ACTION_COPY;
ScDocument* pThisDoc = pViewData->GetDocument();
SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
if ( pHitObj && nMyAction == DND_ACTION_LINK ) // && !rData.pDrawTransfer )
{
if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
|| IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
|| IsDropFormatSupported(SOT_FORMATSTR_ID_PNG)
|| IsDropFormatSupported(SOT_FORMAT_BITMAP) )
{
// graphic dragged onto drawing object
DrawMarkDropObj( pHitObj );
nRet = nMyAction;
}
}
if (!nRet)
DrawMarkDropObj( NULL );
if (!nRet)
{
switch ( nMyAction )
{
case DND_ACTION_COPY:
case DND_ACTION_MOVE:
case DND_ACTION_COPYMOVE:
{
sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE );
if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
IsDropFormatSupported( SOT_FORMAT_STRING ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
IsDropFormatSupported( SOT_FORMAT_RTF ) ||
IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_PNG ) ||
IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
( !bMove && (
IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
IsDropFormatSupported( SOT_FORMAT_FILE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
{
nRet = nMyAction;
}
}
break;
case DND_ACTION_LINK:
if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
IsDropFormatSupported( SOT_FORMAT_FILE ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
{
nRet = nMyAction;
}
break;
}
if ( nRet )
{
// Simple check for protection: It's not known here if the drop will result
// in cells or drawing objects (some formats can be both) and how many cells
// the result will be. But if IsFormatEditable for the drop cell position
// is sal_False (ignores matrix formulas), nothing can be pasted, so the drop
// can already be rejected here.
Point aPos = rEvt.maPosPixel;
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
SCTAB nTab = pViewData->GetTabNo();
ScDocument* pDoc = pViewData->GetDocument();
ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
if ( !aTester.IsFormatEditable() )
nRet = DND_ACTION_NONE; // forbidden
}
}
}
// scroll only for accepted formats
if (nRet)
DropScroll( rEvt.maPosPixel );
}
return nRet;
}
sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
{
TransferableDataHelper aDataHelper( xTransfer );
if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
{
// use bookmark formats if no sba is present
if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
return SOT_FORMATSTR_ID_SOLK;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
}
sal_uLong nFormatId = 0;
if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
nFormatId = SOT_FORMATSTR_ID_DRAWING;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
nFormatId = SOT_FORMATSTR_ID_SVXB;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
{
// If it's a Writer object, insert RTF instead of OLE
sal_Bool bDoRtf = sal_False;
SotStorageStreamRef xStm;
TransferableObjectDescriptor aObjDesc;
if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
{
SotStorageRef xStore( new SotStorage( *xStm ) );
bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
&& aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
}
if ( bDoRtf )
nFormatId = FORMAT_RTF;
else
nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
}
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
nFormatId = SOT_FORMATSTR_ID_BIFF_8;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
nFormatId = SOT_FORMATSTR_ID_BIFF_5;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
nFormatId = SOT_FORMAT_RTF;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
nFormatId = SOT_FORMATSTR_ID_HTML;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
nFormatId = SOT_FORMATSTR_ID_SYLK;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
nFormatId = SOT_FORMATSTR_ID_LINK;
else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
nFormatId = SOT_FORMAT_STRING;
else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
nFormatId = SOT_FORMAT_FILE_LIST;
else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
nFormatId = SOT_FORMAT_FILE;
else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
nFormatId = SOT_FORMAT_STRING;
else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
nFormatId = SOT_FORMAT_GDIMETAFILE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_PNG ) )
nFormatId = SOT_FORMATSTR_ID_PNG;
else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
nFormatId = SOT_FORMAT_BITMAP;
return nFormatId;
}
sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
{
TransferableDataHelper aDataHelper( xTransfer );
sal_uLong nFormatId = 0;
if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
nFormatId = SOT_FORMATSTR_ID_LINK;
else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
nFormatId = SOT_FORMAT_FILE_LIST;
else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
nFormatId = SOT_FORMAT_FILE;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
nFormatId = SOT_FORMATSTR_ID_SOLK;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
return nFormatId;
}
sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
{
// hide drop marker
// if (bDragRect)
// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
bDragRect = sal_False;
UpdateDragRectOverlay();
ScModule* pScMod = SC_MOD();
const ScDragData& rData = pScMod->GetDragData();
return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
}
sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
const Point& rLogicPos, sal_Int8 nDndAction )
{
if ( !pTransObj )
return 0;
ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
ScDocShell* pDocSh = pViewData->GetDocShell();
ScDocument* pThisDoc = pViewData->GetDocument();
ScViewFunc* pView = pViewData->GetView();
SCTAB nThisTab = pViewData->GetTabNo();
sal_uInt16 nFlags = pTransObj->GetDragSourceFlags();
sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
// workaround for wrong nDndAction on Windows when pressing solely
// the Alt key during drag and drop;
// can be removed after #i79215# has been fixed
if ( meDragInsertMode != INS_NONE )
{
bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
}
sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK );
ScRange aSource = pTransObj->GetRange();
// only use visible tab from source range - when dragging within one table,
// all selected tables at the time of dropping are used (handled in MoveBlockTo)
SCTAB nSourceTab = pTransObj->GetVisibleTab();
aSource.aStart.SetTab( nSourceTab );
aSource.aEnd.SetTab( nSourceTab );
SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
ScRange aDest( nDestPosX, nDestPosY, nThisTab,
nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
/* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
* dragging and adapted drawing of the selection frame. We check here
* (again) because this may actually also be called from PasteSelection(),
* we would have to duplicate determination of flags and destination range
* and would lose the context of the "filtered destination is OK" cases
* below, which is already awkward enough as is. */
// Don't move filtered source.
bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
if (!bFiltered)
{
if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
(!bIsLink && meDragInsertMode == INS_NONE)))
{
// Nothing. Either entire sheet to be dropped, or the one case
// where PasteFromClip() is to be called that handles a filtered
// destination itself. Drag-copy from another document without
// inserting cells.
}
else
// Don't copy or move to filtered destination.
bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
}
sal_Bool bDone = sal_False;
if (!bFiltered && pSourceDoc == pThisDoc)
{
if ( nFlags & SC_DROP_TABLE ) // whole sheet?
{
if ( pThisDoc->IsDocEditable() )
{
SCTAB nSrcTab = aSource.aStart.Tab();
pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True ); // with Undo
pView->SetTabNo( nThisTab, sal_True );
bDone = sal_True;
}
}
else // move/copy block
{
String aChartName;
if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName ))
{
String aRangeName;
aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
&aRangeItem, &aNameItem, (void*) NULL );
bDone = sal_True;
}
else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
{
// drop on DataPilot table: try to sort, fail if that isn't possible
ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
if ( aDestPos != aSource.aStart )
bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
else
bDone = sal_True; // same position: nothing
}
else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
nSourceTab != nThisTab )
{
String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
bDone = sal_True;
if ( meDragInsertMode != INS_NONE )
{
// call with bApi = sal_True to avoid error messages in drop handler
bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
if ( bDone )
{
if ( nThisTab == nSourceTab )
{
if ( meDragInsertMode == INS_CELLSDOWN &&
nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
{
bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
}
else if ( meDragInsertMode == INS_CELLSRIGHT &&
nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
{
bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
}
}
pDocSh->UpdateOle( pViewData );
pView->CellContentChanged();
}
}
if ( bDone )
{
if ( bIsLink )
{
// call with bApi = sal_True to avoid error messages in drop handler
bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ );
}
else
{
// call with bApi = sal_True to avoid error messages in drop handler
bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ );
}
}
if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
{
DelCellCmd eCmd = DEL_NONE;
if ( meDragInsertMode == INS_CELLSDOWN )
{
eCmd = DEL_CELLSUP;
}
else if ( meDragInsertMode == INS_CELLSRIGHT )
{
eCmd = DEL_CELLSLEFT;
}
if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
{
// call with bApi = sal_True to avoid error messages in drop handler
bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ );
if ( bDone )
{
if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
{
bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
}
else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
{
bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
}
pDocSh->UpdateOle( pViewData );
pView->CellContentChanged();
}
}
}
if ( bDone )
{
pView->MarkRange( aDest, sal_False, sal_False );
pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
}
pDocSh->GetUndoManager()->LeaveListAction();
if (!bDone)
Sound::Beep(); // instead of error message in drop handler
}
else
bDone = sal_True; // nothing to do
}
if (bDone)
pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
}
else if ( !bFiltered && pSourceDoc ) // between documents
{
if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
{
if ( pThisDoc->IsDocEditable() )
{
ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
SCTAB nTabs[MAXTABCOUNT];
ScMarkData aMark = pTransObj->GetSourceMarkData();
SCTAB nTabCount = pSourceDoc->GetTableCount();
SCTAB nTabSelCount = 0;
for(SCTAB i=0; i<nTabCount; i++)
{
if(aMark.GetTableSelect(i))
{
nTabs[nTabSelCount++]=i;
for(SCTAB j=i+1;j<nTabCount;j++)
{
if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
{
nTabs[nTabSelCount++]=j;
i=j;
}
else break;
}
}
}
pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab );
bDone = sal_True;
}
}
else if ( bIsLink )
{
// as in PasteDDE
// (external references might be used instead?)
SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
DBG_ASSERT(pSourceSh, "drag document has no shell");
if (pSourceSh)
{
String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
bDone = sal_True;
if ( meDragInsertMode != INS_NONE )
{
// call with bApi = sal_True to avoid error messages in drop handler
bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
if ( bDone )
{
pDocSh->UpdateOle( pViewData );
pView->CellContentChanged();
}
}
if ( bDone )
{
String aApp = Application::GetAppName();
String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
String aItem;
aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
// TODO: we could define ocQuote for "
const String aQuote( '"' );
const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
String aFormula( '=' );
aFormula += ScCompiler::GetNativeSymbol( ocDde);
aFormula += ScCompiler::GetNativeSymbol( ocOpen);
aFormula += aQuote;
aFormula += aApp;
aFormula += aQuote;
aFormula += sSep;
aFormula += aQuote;
aFormula += aTopic;
aFormula += aQuote;
aFormula += sSep;
aFormula += aQuote;
aFormula += aItem;
aFormula += aQuote;
aFormula += ScCompiler::GetNativeSymbol( ocClose);
pView->DoneBlockMode();
pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
pView->MarkCursor( nDestPosX + nSizeX - 1,
nDestPosY + nSizeY - 1, nThisTab );
pView->EnterMatrix( aFormula );
pView->MarkRange( aDest, sal_False, sal_False );
pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
}
pDocSh->GetUndoManager()->LeaveListAction();
}
}
else
{
//! HasSelectedBlockMatrixFragment without selected sheet?
//! or don't start dragging on a part of a matrix
String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
bDone = sal_True;
if ( meDragInsertMode != INS_NONE )
{
// call with bApi = sal_True to avoid error messages in drop handler
bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
if ( bDone )
{
pDocSh->UpdateOle( pViewData );
pView->CellContentChanged();
}
}
if ( bDone )
{
pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
pView->SetCursor( nDestPosX, nDestPosY );
bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
if ( bDone )
{
pView->MarkRange( aDest, sal_False, sal_False );
pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
}
}
pDocSh->GetUndoManager()->LeaveListAction();
// no longer call ResetMark here - the inserted block has been selected
// and may have been copied to primary selection
}
}
sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
return nRet;
}
sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
DrawMarkDropObj( NULL ); // drawing layer
ScModule* pScMod = SC_MOD();
const ScDragData& rData = pScMod->GetDragData();
if (rData.pCellTransfer)
return ExecutePrivateDrop( rEvt );
Point aPos = rEvt.maPosPixel;
if ( rData.aLinkDoc.Len() )
{
// try to insert a link
sal_Bool bOk = sal_True;
String aThisName;
ScDocShell* pDocSh = pViewData->GetDocShell();
if (pDocSh && pDocSh->HasName())
aThisName = pDocSh->GetMedium()->GetName();
if ( rData.aLinkDoc == aThisName ) // error - no link within a document
bOk = sal_False;
else
{
ScViewFunc* pView = pViewData->GetView();
if ( rData.aLinkTable.Len() )
pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
rData.aLinkTable );
else if ( rData.aLinkArea.Len() )
{
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, sal_False, sal_False );
pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
rData.aLinkArea, 0 );
}
else
{
DBG_ERROR("drop with link: no sheet nor area");
bOk = sal_False;
}
}
return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
}
Point aLogicPos = PixelToLogic(aPos);
sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
if (!bIsLink && rData.pDrawTransfer)
{
sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags();
sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
bPasteIsMove = bIsMove;
pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
if (bPasteIsMove)
rData.pDrawTransfer->SetDragWasInternal();
bPasteIsMove = sal_False;
return rEvt.mnAction;
}
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
if (rData.aJumpTarget.Len())
{
// internal bookmark (from Navigator)
// bookmark clipboard formats are in PasteScDataObject
if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
{
pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
nPosX, nPosY );
return rEvt.mnAction;
}
}
ScDocument* pThisDoc = pViewData->GetDocument();
SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
if ( pHitObj && bIsLink )
{
// dropped on drawing object
// PasteOnDrawObjectLinked checks for valid formats
if ( pViewData->GetView()->PasteOnDrawObjectLinked( rEvt.maDropEvent.Transferable, *pHitObj ) )
return rEvt.mnAction;
}
sal_Bool bDone = sal_False;
sal_uLong nFormatId = bIsLink ?
lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
if ( nFormatId )
{
pScMod->SetInExecuteDrop( sal_True ); // #i28468# prevent error messages from PasteDataFormat
bPasteIsDrop = sal_True;
bDone = pViewData->GetView()->PasteDataFormat(
nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
bPasteIsDrop = sal_False;
pScMod->SetInExecuteDrop( sal_False );
}
sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
return nRet;
}
//--------------------------------------------------------
void ScGridWindow::PasteSelection( const Point& rPosPixel )
{
Point aLogicPos = PixelToLogic( rPosPixel );
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
if ( pOwnSelection )
{
// within Calc
ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
if ( pCellTransfer )
{
// keep a reference to the data in case the selection is changed during paste
uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
}
else
{
ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
if ( pDrawTransfer )
{
// keep a reference to the data in case the selection is changed during paste
uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
// #96821# bSameDocClipboard argument for PasteDraw is needed
// because only DragData is checked directly inside PasteDraw
pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), sal_False,
pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
}
}
}
else
{
// get selection from system
TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
if ( xTransferable.is() )
{
sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true );
if ( nFormatId )
{
bPasteIsDrop = sal_True;
pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
bPasteIsDrop = sal_False;
}
}
}
}
//--------------------------------------------------------
void ScGridWindow::UpdateEditViewPos()
{
if (pViewData->HasEditView(eWhich))
{
EditView* pView;
SCCOL nCol;
SCROW nRow;
pViewData->GetEditView( eWhich, pView, nCol, nRow );
SCCOL nEndCol = pViewData->GetEditEndCol();
SCROW nEndRow = pViewData->GetEditEndRow();
// hide EditView?
sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
if ( SC_MOD()->IsFormulaMode() )
if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
bHide = sal_True;
if (bHide)
{
Rectangle aRect = pView->GetOutputArea();
long nHeight = aRect.Bottom() - aRect.Top();
aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
Height() * 2;
aRect.Bottom() = aRect.Top() + nHeight;
pView->SetOutputArea( aRect );
pView->HideCursor();
}
else
{
// bForceToTop = sal_True for editing
Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True );
Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
Rectangle aRect = pView->GetOutputArea();
aRect.SetPos( aScrPos );
pView->SetOutputArea( aRect );
pView->ShowCursor();
}
}
}
void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
{
ClickExtern();
HideNoteMarker();
bIsInScroll = sal_True;
//sal_Bool bXor=DrawBeforeScroll();
SetMapMode(MAP_PIXEL);
Scroll( nDifX, nDifY, SCROLL_CHILDREN );
SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
UpdateEditViewPos();
DrawAfterScroll(); //bXor);
bIsInScroll = sal_False;
}
// Formeln neu zeichnen -------------------------------------------------
void ScGridWindow::UpdateFormulas()
{
if (pViewData->GetView()->IsMinimized())
return;
if ( nPaintCount )
{
// nicht anfangen, verschachtelt zu painten
// (dann wuerde zumindest der MapMode nicht mehr stimmen)
bNeedsRepaint = sal_True; // -> am Ende vom Paint nochmal Invalidate auf alles
aRepaintPixel = Rectangle(); // alles
return;
}
SCCOL nX1 = pViewData->GetPosX( eHWhich );
SCROW nY1 = pViewData->GetPosY( eVWhich );
SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
if (nX2 > MAXCOL) nX2 = MAXCOL;
if (nY2 > MAXROW) nY2 = MAXROW;
// Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
// don't draw directly - instead use OutputData to find changed area and invalidate
SCROW nPosY = nY1;
ScDocShell* pDocSh = pViewData->GetDocShell();
ScDocument* pDoc = pDocSh->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
long nMirrorWidth = GetSizePixel().Width();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
// unused variable long nLayoutSign = bLayoutRTL ? -1 : 1;
if ( bLayoutRTL )
{
long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
nMirrorWidth = aScrPos.X() - nEndPixel;
aScrPos.X() = nEndPixel + 1;
}
long nScrX = aScrPos.X();
long nScrY = aScrPos.Y();
double nPPTX = pViewData->GetPPTX();
double nPPTY = pViewData->GetPPTY();
ScTableInfo aTabInfo;
pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, sal_False, sal_False );
Fraction aZoomX = pViewData->GetZoomX();
Fraction aZoomY = pViewData->GetZoomY();
ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
&aZoomX, &aZoomY );
aOutputData.SetMirrorWidth( nMirrorWidth );
aOutputData.FindChanged();
// #122149# do not use old GetChangedArea() which used polygon-based Regions, but use
// the region-band based new version; anyways, only rectangles are added
Region aChangedRegion( aOutputData.GetChangedAreaRegion() ); // logic (PixelToLogic)
if(!aChangedRegion.IsEmpty())
{
Invalidate(aChangedRegion);
}
CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
}
void ScGridWindow::UpdateAutoFillMark(sal_Bool bMarked, const ScRange& rMarkRange)
{
if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
{
HideCursor();
bAutoMarkVisible = bMarked;
if ( bMarked )
aAutoMarkPos = rMarkRange.aEnd;
ShowCursor();
UpdateAutoFillOverlay();
}
}
void ScGridWindow::UpdateListValPos( sal_Bool bVisible, const ScAddress& rPos )
{
sal_Bool bOldButton = bListValButton;
ScAddress aOldPos = aListValPos;
bListValButton = bVisible;
aListValPos = rPos;
if ( bListValButton )
{
if ( !bOldButton || aListValPos != aOldPos )
{
// paint area of new button
Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
}
}
if ( bOldButton )
{
if ( !bListValButton || aListValPos != aOldPos )
{
// paint area of old button
Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
}
}
}
void ScGridWindow::HideCursor()
{
++nCursorHideCount;
if (nCursorHideCount==1)
{
DrawCursor();
DrawAutoFillMark();
}
}
void ScGridWindow::ShowCursor()
{
if (nCursorHideCount==0)
{
DBG_ERROR("zuviel ShowCursor");
return;
}
if (nCursorHideCount==1)
{
// #i57745# Draw the cursor before setting the variable, in case the
// GetSizePixel call from drawing causes a repaint (resize handler is called)
DrawAutoFillMark();
DrawCursor();
}
--nCursorHideCount;
}
void __EXPORT ScGridWindow::GetFocus()
{
ScTabViewShell* pViewShell = pViewData->GetViewShell();
pViewShell->GotFocus();
pViewShell->SetFormShellAtTop( sal_False ); // focus in GridWindow -> FormShell no longer on top
if (pViewShell->HasAccessibilityObjects())
pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
if ( !SC_MOD()->IsFormulaMode() )
{
pViewShell->UpdateInputHandler();
// StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
// MO: nur wenn nicht im RefInput-Modus
// -> GetFocus/MouseButtonDown-Reihenfolge
// auf dem Mac
}
Window::GetFocus();
}
void __EXPORT ScGridWindow::LoseFocus()
{
ScTabViewShell* pViewShell = pViewData->GetViewShell();
pViewShell->LostFocus();
if (pViewShell->HasAccessibilityObjects())
pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
Window::LoseFocus();
}
Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
//------------------------------------------------------------------------
sal_Bool ScGridWindow::HitRangeFinder( const Point& rMouse, sal_Bool& rCorner,
sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
{
sal_Bool bFound = sal_False;
ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
if (pHdl)
{
ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
if ( pRangeFinder && !pRangeFinder->IsHidden() &&
pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
{
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
long nLayoutSign = bLayoutRTL ? -1 : 1;
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
// zusammengefasste (einzeln/Bereich) ???
ScAddress aAddr( nPosX, nPosY, nTab );
// Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich );
Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, sal_True );
long nSizeXPix;
long nSizeYPix;
pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
aNext.X() += nSizeXPix * nLayoutSign;
aNext.Y() += nSizeYPix;
sal_Bool bCornerHor;
if ( bLayoutRTL )
bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
else
bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
sal_Bool bCellCorner = ( bCornerHor &&
rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
// corner is hit only if the mouse is within the cell
sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
for (sal_uInt16 i=nCount; i;)
{
// rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
--i;
ScRangeFindData* pData = pRangeFinder->GetObject(i);
if ( pData && pData->aRef.In(aAddr) )
{
if (pIndex) *pIndex = i;
if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col();
if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row();
bFound = sal_True;
rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
break;
}
}
}
}
return bFound;
}
#define SCE_TOP 1
#define SCE_BOTTOM 2
#define SCE_LEFT 4
#define SCE_RIGHT 8
#define SCE_ALL 15
void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges )
{
// der Range ist immer richtigherum
SCCOL nCol1 = rRange.aStart.Col();
SCROW nRow1 = rRange.aStart.Row();
SCTAB nTab1 = rRange.aStart.Tab();
SCCOL nCol2 = rRange.aEnd.Col();
SCROW nRow2 = rRange.aEnd.Row();
SCTAB nTab2 = rRange.aEnd.Tab();
sal_Bool bHiddenEdge = sal_False;
SCROW nTmp;
ScDocument* pDoc = pDocSh->GetDocument();
while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
{
--nCol1;
bHiddenEdge = sal_True;
}
while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
{
++nCol2;
bHiddenEdge = sal_True;
}
nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
if (!ValidRow(nTmp))
nTmp = 0;
if (nTmp < nRow1)
{
nRow1 = nTmp;
bHiddenEdge = sal_True;
}
nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
if (!ValidRow(nTmp))
nTmp = MAXROW;
if (nTmp > nRow2)
{
nRow2 = nTmp;
bHiddenEdge = sal_True;
}
if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
{
// nur an den Raendern entlang
// (die Ecken werden evtl. zweimal getroffen)
if ( nEdges & SCE_TOP )
pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
if ( nEdges & SCE_LEFT )
pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
if ( nEdges & SCE_RIGHT )
pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
if ( nEdges & SCE_BOTTOM )
pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
}
else // everything in one call
pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
}
void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
{
// Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
ScRange aOld = rOldUn;
ScRange aNew = rNewUn;
aOld.Justify();
aNew.Justify();
if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
pDocSh->GetDocument()->ExtendMerge(aOld);
if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
pDocSh->GetDocument()->ExtendMerge(aNew);
SCCOL nOldCol1 = aOld.aStart.Col();
SCROW nOldRow1 = aOld.aStart.Row();
SCCOL nOldCol2 = aOld.aEnd.Col();
SCROW nOldRow2 = aOld.aEnd.Row();
SCCOL nNewCol1 = aNew.aStart.Col();
SCROW nNewRow1 = aNew.aStart.Row();
SCCOL nNewCol2 = aNew.aEnd.Col();
SCROW nNewRow2 = aNew.aEnd.Row();
SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht
SCTAB nTab2 = aOld.aEnd.Tab();
if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
{
// komplett weggeschoben oder alle Seiten veraendert
// (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
}
else // alle vier Kanten einzeln testen
{
// oberer Teil
if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen
lcl_PaintOneRange( pDocSh, ScRange(
nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
lcl_PaintOneRange( pDocSh, ScRange(
nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
SCE_ALL &~ SCE_BOTTOM );
// unterer Teil
if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen
lcl_PaintOneRange( pDocSh, ScRange(
nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
lcl_PaintOneRange( pDocSh, ScRange(
nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
SCE_ALL &~ SCE_TOP );
// linker Teil
if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen
lcl_PaintOneRange( pDocSh, ScRange(
nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
lcl_PaintOneRange( pDocSh, ScRange(
nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
SCE_ALL &~ SCE_RIGHT );
// rechter Teil
if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen
lcl_PaintOneRange( pDocSh, ScRange(
nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
lcl_PaintOneRange( pDocSh, ScRange(
nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
SCE_ALL &~ SCE_LEFT );
}
}
void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp )
{
ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
if (!pHdl)
return;
ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
return;
ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
if (!pData)
return;
// Mauszeiger
if (bRFSize)
SetPointer( Pointer( POINTER_CROSS ) );
else
SetPointer( Pointer( POINTER_HAND ) );
// Scrolling
sal_Bool bTimer = sal_False;
Point aPos = rMEvt.GetPosPixel();
SCsCOL nDx = 0;
SCsROW nDy = 0;
if ( aPos.X() < 0 ) nDx = -1;
if ( aPos.Y() < 0 ) nDy = -1;
Size aSize = GetOutputSizePixel();
if ( aPos.X() >= aSize.Width() )
nDx = 1;
if ( aPos.Y() >= aSize.Height() )
nDy = 1;
if ( nDx != 0 || nDy != 0 )
{
if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
bTimer = sal_True;
}
// Umschalten bei Fixierung (damit Scrolling funktioniert)
if ( eWhich == pViewData->GetActivePart() ) //??
{
if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
if ( nDx > 0 )
{
if ( eWhich == SC_SPLIT_TOPLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
}
if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
if ( nDy > 0 )
{
if ( eWhich == SC_SPLIT_TOPLEFT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
else if ( eWhich == SC_SPLIT_TOPRIGHT )
pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
}
}
// Verschieben
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
ScRange aOld = pData->aRef;
ScRange aNew = aOld;
if ( bRFSize )
{
aNew.aEnd.SetCol((SCCOL)nPosX);
aNew.aEnd.SetRow((SCROW)nPosY);
}
else
{
long nStartX = nPosX - nRFAddX;
if ( nStartX < 0 ) nStartX = 0;
long nStartY = nPosY - nRFAddY;
if ( nStartY < 0 ) nStartY = 0;
long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
if ( nEndX > MAXCOL )
{
nStartX -= ( nEndX - MAXROW );
nEndX = MAXCOL;
}
long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
if ( nEndY > MAXROW )
{
nStartY -= ( nEndY - MAXROW );
nEndY = MAXROW;
}
aNew.aStart.SetCol((SCCOL)nStartX);
aNew.aStart.SetRow((SCROW)nStartY);
aNew.aEnd.SetCol((SCCOL)nEndX);
aNew.aEnd.SetRow((SCROW)nEndY);
}
if ( bUp )
aNew.Justify(); // beim ButtonUp wieder richtigherum
if ( aNew != aOld )
{
pHdl->UpdateRange( nRFIndex, aNew );
ScDocShell* pDocSh = pViewData->GetDocShell();
// nur das neuzeichnen, was sich veraendert hat...
lcl_PaintRefChanged( pDocSh, aOld, aNew );
// neuen Rahmen nur drueberzeichnen (synchron)
pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
Update(); // was man bewegt, will man auch sofort sehen
}
// Timer fuer Scrolling
if (bTimer)
pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
else
pViewData->GetView()->ResetTimer();
}
//------------------------------------------------------------------------
sal_Bool ScGridWindow::GetEditUrl( const Point& rPos,
String* pName, String* pUrl, String* pTarget )
{
return GetEditUrlOrError( sal_False, rPos, pName, pUrl, pTarget );
}
sal_Bool ScGridWindow::GetEditUrlOrError( sal_Bool bSpellErr, const Point& rPos,
String* pName, String* pUrl, String* pTarget )
{
//! nPosX/Y mit uebergeben?
SCsCOL nPosX;
SCsROW nPosY;
pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
SCTAB nTab = pViewData->GetTabNo();
ScDocShell* pDocSh = pViewData->GetDocShell();
ScDocument* pDoc = pDocSh->GetDocument();
ScBaseCell* pCell = NULL;
sal_Bool bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
if( !bFound )
return sal_False;
ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed)
const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
// bForceToTop = sal_False, use the cell's real position
Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False );
if (rPos.Y() < aEditRect.Top())
return sal_False;
// vertikal kann (noch) nicht angeklickt werden:
if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
return sal_False;
sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
GetItem(ATTR_HOR_JUSTIFY)).GetValue();
// EditEngine
ScFieldEditEngine aEngine( pDoc->GetEditPool() );
ScSizeDeviceProvider aProv(pDocSh);
aEngine.SetRefDevice( aProv.GetDevice() );
aEngine.SetRefMapMode( MAP_100TH_MM );
SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
pPattern->FillEditItemSet( &aDefault );
SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
switch (eHorJust)
{
case SVX_HOR_JUSTIFY_LEFT:
case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
eSvxAdjust = SVX_ADJUST_LEFT;
break;
case SVX_HOR_JUSTIFY_RIGHT:
eSvxAdjust = SVX_ADJUST_RIGHT;
break;
case SVX_HOR_JUSTIFY_CENTER:
eSvxAdjust = SVX_ADJUST_CENTER;
break;
case SVX_HOR_JUSTIFY_BLOCK:
eSvxAdjust = SVX_ADJUST_BLOCK;
break;
}
aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
aEngine.SetDefaults( aDefault );
if (bSpellErr)
aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
Size aPaperSize = Size( 1000000, 1000000 );
if(pCell->GetCellType() == CELLTYPE_FORMULA)
{
long nSizeX = 0;
long nSizeY = 0;
pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
aPaperSize = Size(nSizeX, nSizeY );
aPaperSize = PixelToLogic(aPaperSize);
}
if (bBreak)
aPaperSize.Width() = nThisColLogic;
aEngine.SetPaperSize( aPaperSize );
::std::auto_ptr< EditTextObject > pTextObj;
const EditTextObject* pData;
if(pCell->GetCellType() == CELLTYPE_EDIT)
{
((ScEditCell*)pCell)->GetData(pData);
if (pData)
aEngine.SetText(*pData);
}
else // HyperLink Formula cell
{
pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject());
if (pTextObj.get())
aEngine.SetText(*pTextObj);
}
long nStartX = aLogicEdit.Left();
long nTextWidth = aEngine.CalcTextWidth();
long nTextHeight = aEngine.GetTextHeight();
if ( nTextWidth < nThisColLogic )
{
if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
nStartX += nThisColLogic - nTextWidth;
else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
nStartX += (nThisColLogic - nTextWidth) / 2;
}
aLogicEdit.Left() = nStartX;
if (!bBreak)
aLogicEdit.Right() = nStartX + nTextWidth;
// There is one glitch when dealing with a hyperlink cell and
// the cell content is NUMERIC. This defaults to right aligned and
// we need to adjust accordingly.
if(pCell->GetCellType() == CELLTYPE_FORMULA &&
static_cast<ScFormulaCell*>(pCell)->IsValue() &&
eHorJust == SVX_HOR_JUSTIFY_STANDARD)
{
aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
}
aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
Point aLogicClick = PixelToLogic(rPos,aEditMode);
if ( aLogicEdit.IsInside(aLogicClick) )
{
// aEngine.SetUpdateMode(sal_False);
EditView aTempView( &aEngine, this );
aTempView.SetOutputArea( aLogicEdit );
sal_Bool bRet = sal_False;
MapMode aOld = GetMapMode();
SetMapMode(aEditMode); // kein return mehr
if (bSpellErr) // Spelling-Fehler suchen
{
bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
if ( bRet )
pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen
}
else // URL suchen
{
const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
if (pFieldItem)
{
const SvxFieldData* pField = pFieldItem->GetField();
if ( pField && pField->ISA(SvxURLField) )
{
if ( pName || pUrl || pTarget )
{
const SvxURLField* pURLField = (const SvxURLField*)pField;
if (pName)
*pName = pURLField->GetRepresentation();
if (pUrl)
*pUrl = pURLField->GetURL();
if (pTarget)
*pTarget = pURLField->GetTargetFrame();
}
bRet = sal_True;
}
}
}
SetMapMode(aOld);
// text cursor is restored in ScHideTextCursor dtor
return bRet;
}
return sal_False;
}
sal_Bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
{
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
SCTAB nTabCount = pDoc->GetTableCount();
if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
{
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
Size aButSize = pViewData->GetScenButSize();
long nBWidth = aButSize.Width();
if (!nBWidth)
return sal_False; // noch kein Button gezeichnet -> da ist auch keiner
long nBHeight = aButSize.Height();
long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
//! Ranges an der Table cachen!!!!
ScMarkData aMarks;
for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME );
ScRangeList aRanges;
aMarks.FillRangeListWithMarks( &aRanges, sal_False );
sal_uLong nRangeCount = aRanges.Count();
for (sal_uLong j=0; j<nRangeCount; j++)
{
ScRange aRange = *aRanges.GetObject(j);
// Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
// dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
pDoc->ExtendTotalMerge( aRange );
sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 );
Point aButtonPos;
if ( bTextBelow )
{
aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
eWhich, sal_True );
}
else
{
aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
eWhich, sal_True );
aButtonPos.Y() -= nBHeight;
}
if ( bLayoutRTL )
aButtonPos.X() -= nHSpace - 1;
else
aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
if ( aButRect.IsInside( rPosPixel ) )
{
rScenRange = aRange;
return sal_True;
}
}
}
return sal_False;
}
void ScGridWindow::UpdateVisibleRange()
{
// #163911# Update the visible range outside of paint (called when switching sheets).
// Use the same logic here as in ScGridWindow::Draw.
SCCOL nPosX = pViewData->GetPosX( eHWhich );
SCROW nPosY = pViewData->GetPosY( eVWhich );
SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
if (nXRight > MAXCOL) nXRight = MAXCOL;
SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
if (nYBottom > MAXROW) nYBottom = MAXROW;
// Store the current visible range.
maVisibleRange.mnCol1 = nPosX;
maVisibleRange.mnCol2 = nXRight;
maVisibleRange.mnRow1 = nPosY;
maVisibleRange.mnRow2 = nYBottom;
}
// #114409#
void ScGridWindow::DrawLayerCreated()
{
SetMapMode( GetDrawMapMode() );
// initially create overlay objects
ImpCreateOverlayObjects();
}
// #114409#
void ScGridWindow::CursorChanged()
{
// here the created OverlayObjects may be transformed in later versions. For
// now, just re-create them
UpdateCursorOverlay();
}
// #114409#
void ScGridWindow::ImpCreateOverlayObjects()
{
UpdateCursorOverlay();
UpdateSelectionOverlay();
UpdateAutoFillOverlay();
UpdateDragRectOverlay();
UpdateHeaderOverlay();
UpdateShrinkOverlay();
}
// #114409#
void ScGridWindow::ImpDestroyOverlayObjects()
{
DeleteCursorOverlay();
DeleteSelectionOverlay();
DeleteAutoFillOverlay();
DeleteDragRectOverlay();
DeleteHeaderOverlay();
DeleteShrinkOverlay();
}
void ScGridWindow::UpdateAllOverlays()
{
// delete and re-allocate all overlay objects
ImpDestroyOverlayObjects();
ImpCreateOverlayObjects();
}
void ScGridWindow::DeleteCursorOverlay()
{
DELETEZ( mpOOCursors );
}
void ScGridWindow::UpdateCursorOverlay()
{
MapMode aDrawMode = GetDrawMapMode();
MapMode aOldMode = GetMapMode();
if ( aOldMode != aDrawMode )
SetMapMode( aDrawMode );
// Existing OverlayObjects may be transformed in later versions.
// For now, just re-create them.
DeleteCursorOverlay();
std::vector<Rectangle> aPixelRects;
//
// determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
//
SCTAB nTab = pViewData->GetTabNo();
SCCOL nX = pViewData->GetCurX();
SCROW nY = pViewData->GetCurY();
if (!maVisibleRange.isInside(nX, nY))
return;
// don't show the cursor in overlapped cells
ScDocument* pDoc = pViewData->GetDocument();
const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
sal_Bool bOverlapped = rMergeFlag.IsOverlapped();
// left or above of the screen?
sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
if (!bVis)
{
SCCOL nEndX = nX;
SCROW nEndY = nY;
const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
if (rMerge.GetColMerge() > 1)
nEndX += rMerge.GetColMerge()-1;
if (rMerge.GetRowMerge() > 1)
nEndY += rMerge.GetRowMerge()-1;
bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
}
if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
{
Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
// completely right of/below the screen?
// (test with logical start position in aScrPos)
sal_Bool bMaybeVisible;
if ( bLayoutRTL )
bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
else
{
Size aOutSize = GetOutputSizePixel();
bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
}
if ( bMaybeVisible )
{
long nSizeXPix;
long nSizeYPix;
pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
if ( bLayoutRTL )
aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ||
pViewData->GetVSplitMode() == SC_SPLIT_FIX );
if ( pViewData->GetActivePart()==eWhich || bFix )
{
aScrPos.X() -= 2;
aScrPos.Y() -= 2;
Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
}
else
{
Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) );
aPixelRects.push_back( aRect );
}
}
}
if ( aPixelRects.size() )
{
// #i70788# get the OverlayManager safely
::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
if(pOverlayManager)
{
const Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
std::vector< basegfx::B2DRange > aRanges;
const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
{
const Rectangle aRA(aPixelRects[a]);
basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
aRB.transform(aTransform);
aRanges.push_back(aRB);
}
sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
sdr::overlay::OVERLAY_SOLID,
aCursorColor,
aRanges,
false);
pOverlayManager->add(*pOverlay);
mpOOCursors = new ::sdr::overlay::OverlayObjectList;
mpOOCursors->append(*pOverlay);
}
}
if ( aOldMode != aDrawMode )
SetMapMode( aOldMode );
}
void ScGridWindow::DeleteSelectionOverlay()
{
DELETEZ( mpOOSelection );
}
void ScGridWindow::UpdateSelectionOverlay()
{
MapMode aDrawMode = GetDrawMapMode();
MapMode aOldMode = GetMapMode();
if ( aOldMode != aDrawMode )
SetMapMode( aDrawMode );
DeleteSelectionOverlay();
std::vector<Rectangle> aPixelRects;
GetSelectionRects( aPixelRects );
if ( aPixelRects.size() && pViewData->IsActive() )
{
// #i70788# get the OverlayManager safely
::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
if(pOverlayManager)
{
std::vector< basegfx::B2DRange > aRanges;
const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
{
const Rectangle aRA(aPixelRects[a]);
basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
aRB.transform(aTransform);
aRanges.push_back(aRB);
}
// get the system's hilight color
const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor());
sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
sdr::overlay::OVERLAY_TRANSPARENT,
aHighlight,
aRanges,
true);
pOverlayManager->add(*pOverlay);
mpOOSelection = new ::sdr::overlay::OverlayObjectList;
mpOOSelection->append(*pOverlay);
}
}
if ( aOldMode != aDrawMode )
SetMapMode( aOldMode );
}
void ScGridWindow::DeleteAutoFillOverlay()
{
DELETEZ( mpOOAutoFill );
mpAutoFillRect.reset();
}
void ScGridWindow::UpdateAutoFillOverlay()
{
MapMode aDrawMode = GetDrawMapMode();
MapMode aOldMode = GetMapMode();
if ( aOldMode != aDrawMode )
SetMapMode( aDrawMode );
DeleteAutoFillOverlay();
//
// get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark)
//
if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
!pViewData->HasEditView(eWhich) && pViewData->IsActive() )
{
SCCOL nX = aAutoMarkPos.Col();
SCROW nY = aAutoMarkPos.Row();
if (!maVisibleRange.isInside(nX, nY))
// Autofill mark is not visible. Bail out.
return;
SCTAB nTab = pViewData->GetTabNo();
ScDocument* pDoc = pViewData->GetDocument();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
long nSizeXPix;
long nSizeYPix;
pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
if ( bLayoutRTL )
aFillPos.X() -= nSizeXPix + 3;
else
aFillPos.X() += nSizeXPix - 2;
aFillPos.Y() += nSizeYPix;
aFillPos.Y() -= 2;
mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
// #i70788# get the OverlayManager safely
::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
if(pOverlayManager)
{
const Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
std::vector< basegfx::B2DRange > aRanges;
const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
aRB.transform(aTransform);
aRanges.push_back(aRB);
sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
sdr::overlay::OVERLAY_SOLID,
aHandleColor,
aRanges,
false);
pOverlayManager->add(*pOverlay);
mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
mpOOAutoFill->append(*pOverlay);
}
if ( aOldMode != aDrawMode )
SetMapMode( aOldMode );
}
}
void ScGridWindow::DeleteDragRectOverlay()
{
DELETEZ( mpOODragRect );
}
void ScGridWindow::UpdateDragRectOverlay()
{
MapMode aDrawMode = GetDrawMapMode();
MapMode aOldMode = GetMapMode();
if ( aOldMode != aDrawMode )
SetMapMode( aDrawMode );
DeleteDragRectOverlay();
//
// get the rectangles in pixels (moved from DrawDragRect)
//
if ( bDragRect || bPagebreakDrawn )
{
std::vector<Rectangle> aPixelRects;
SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
SCTAB nTab = pViewData->GetTabNo();
SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
if (nX1 < nPosX) nX1 = nPosX;
if (nX2 < nPosX) nX2 = nPosX;
if (nY1 < nPosY) nY1 = nPosY;
if (nY2 < nPosY) nY2 = nPosY;
Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
long nSizeXPix=0;
long nSizeYPix=0;
ScDocument* pDoc = pViewData->GetDocument();
double nPPTX = pViewData->GetPPTX();
double nPPTY = pViewData->GetPPTY();
SCCOLROW i;
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
long nLayoutSign = bLayoutRTL ? -1 : 1;
if (ValidCol(nX2) && nX2>=nX1)
for (i=nX1; i<=nX2; i++)
nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
else
{
aScrPos.X() -= nLayoutSign;
nSizeXPix += 2;
}
if (ValidRow(nY2) && nY2>=nY1)
for (i=nY1; i<=nY2; i++)
nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
else
{
aScrPos.Y() -= 1;
nSizeYPix += 2;
}
aScrPos.X() -= 2 * nLayoutSign;
aScrPos.Y() -= 2;
// Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
Rectangle aRect( aScrPos.X(), aScrPos.Y(),
aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
if ( bLayoutRTL )
{
aRect.Left() = aRect.Right(); // end position is left
aRect.Right() = aScrPos.X();
}
if ( meDragInsertMode == INS_CELLSDOWN )
{
aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
}
else if ( meDragInsertMode == INS_CELLSRIGHT )
{
aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
}
else
{
aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
}
// #i70788# get the OverlayManager safely
::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
if(pOverlayManager)
{
// Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
std::vector< basegfx::B2DRange > aRanges;
const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
{
const Rectangle aRA(aPixelRects[a]);
basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
aRB.transform(aTransform);
aRanges.push_back(aRB);
}
sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
sdr::overlay::OVERLAY_INVERT,
Color(COL_BLACK),
aRanges,
false);
pOverlayManager->add(*pOverlay);
mpOODragRect = new ::sdr::overlay::OverlayObjectList;
mpOODragRect->append(*pOverlay);
}
}
if ( aOldMode != aDrawMode )
SetMapMode( aOldMode );
}
void ScGridWindow::DeleteHeaderOverlay()
{
DELETEZ( mpOOHeader );
}
void ScGridWindow::UpdateHeaderOverlay()
{
MapMode aDrawMode = GetDrawMapMode();
MapMode aOldMode = GetMapMode();
if ( aOldMode != aDrawMode )
SetMapMode( aDrawMode );
DeleteHeaderOverlay();
// Pixel rectangle is in aInvertRect
if ( !aInvertRect.IsEmpty() )
{
// #i70788# get the OverlayManager safely
::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
if(pOverlayManager)
{
// Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
std::vector< basegfx::B2DRange > aRanges;
const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
aRB.transform(aTransform);
aRanges.push_back(aRB);
sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
sdr::overlay::OVERLAY_INVERT,
Color(COL_BLACK),
aRanges,
false);
pOverlayManager->add(*pOverlay);
mpOOHeader = new ::sdr::overlay::OverlayObjectList;
mpOOHeader->append(*pOverlay);
}
}
if ( aOldMode != aDrawMode )
SetMapMode( aOldMode );
}
void ScGridWindow::DeleteShrinkOverlay()
{
DELETEZ( mpOOShrink );
}
void ScGridWindow::UpdateShrinkOverlay()
{
MapMode aDrawMode = GetDrawMapMode();
MapMode aOldMode = GetMapMode();
if ( aOldMode != aDrawMode )
SetMapMode( aDrawMode );
DeleteShrinkOverlay();
//
// get the rectangle in pixels
//
Rectangle aPixRect;
ScRange aRange;
SCTAB nTab = pViewData->GetTabNo();
if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
pViewData->GetDelMark( aRange ) )
{
//! limit to visible area
if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
aRange.aStart.Row() <= aRange.aEnd.Row() )
{
Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
aRange.aStart.Row(), eWhich );
Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
aRange.aEnd.Row()+1, eWhich );
aEnd.X() -= 1;
aEnd.Y() -= 1;
aPixRect = Rectangle( aStart,aEnd );
}
}
if ( !aPixRect.IsEmpty() )
{
// #i70788# get the OverlayManager safely
::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
if(pOverlayManager)
{
// Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
std::vector< basegfx::B2DRange > aRanges;
const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
aRB.transform(aTransform);
aRanges.push_back(aRB);
sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
sdr::overlay::OVERLAY_INVERT,
Color(COL_BLACK),
aRanges,
false);
pOverlayManager->add(*pOverlay);
mpOOShrink = new ::sdr::overlay::OverlayObjectList;
mpOOShrink->append(*pOverlay);
}
}
if ( aOldMode != aDrawMode )
SetMapMode( aOldMode );
}
// #i70788# central method to get the OverlayManager safely
::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager()
{
SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
if(pPV)
{
SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
if ( pPageWin )
{
return (pPageWin->GetOverlayManager());
}
}
return 0L;
}
void ScGridWindow::flushOverlayManager()
{
// #i70788# get the OverlayManager safely
::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
if(pOverlayManager)
{
pOverlayManager->flush();
}
}
// ---------------------------------------------------------------------------
// eof