blob: 8e064c45d8739fd529be069537c716945c7d253f [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 ---------------------------------------------------------------
#define _ZFORLIST_DECLARE_TABLE
#include "scitems.hxx"
#include <svl/smplhint.hxx>
#include <svl/zforlist.hxx>
#include <svx/numfmtsh.hxx>
#include <svx/numinf.hxx>
#include <svx/svxids.hrc>
#include <sfx2/dispatch.hxx>
#include <sfx2/objsh.hxx>
#include "tabvwsh.hxx"
#include "sc.hrc"
#include "global.hxx"
#include "docsh.hxx"
#include "document.hxx"
#include "cell.hxx"
#include "globstr.hrc"
#include "scmod.hxx"
#include "uiitems.hxx"
#include "editsh.hxx"
#include "hints.hxx"
//==================================================================
void __EXPORT ScTabViewShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
if (rHint.ISA(SfxSimpleHint)) // ohne Parameter
{
sal_uLong nSlot = ((SfxSimpleHint&)rHint).GetId();
switch ( nSlot )
{
case FID_DATACHANGED:
UpdateFormulas();
break;
case FID_REFMODECHANGED:
{
sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
if (!bRefMode)
StopRefMode();
else
{
GetSelEngine()->Reset();
GetFunctionSet()->SetAnchorFlag(sal_True);
// AnchorFlag, damit gleich mit Control angehaengt werden kann
}
}
break;
case FID_KILLEDITVIEW:
case FID_KILLEDITVIEW_NOPAINT:
StopEditShell();
KillEditView( nSlot == FID_KILLEDITVIEW_NOPAINT );
break;
case SFX_HINT_DOCCHANGED:
{
ScDocument* pDoc = GetViewData()->GetDocument();
if (!pDoc->HasTable( GetViewData()->GetTabNo() ))
{
SetTabNo(0);
}
}
break;
case SC_HINT_DRWLAYER_NEW:
MakeDrawView();
break;
case SC_HINT_DOC_SAVED:
{
// beim "Save as" kann ein vorher schreibgeschuetztes Dokument
// bearbeitbar werden, deshalb die Layer-Locks neu (#39884#)
// (Invalidate etc. passiert schon vom Sfx her)
// #42091# bei SID_EDITDOC kommt kein SFX_HINT_TITLECHANGED, darum
// der eigene Hint aus DoSaveCompleted
//! was ist mit SFX_HINT_SAVECOMPLETED ?
UpdateLayerLocks();
// #54891# Design-Modus bei jedem Speichern anzupassen, waere zuviel
// (beim Speichern unter gleichem Namen soll er unveraendert bleiben)
// Darum nur bei SFX_HINT_MODECHANGED (vom ViewFrame)
}
break;
case SFX_HINT_MODECHANGED:
// #54891#/#58510# Da man sich nicht mehr darauf verlassen kann, woher
// dieser Hint kommt, den Design-Modus immer dann umschalten, wenn der
// ReadOnly-Status sich wirklich geaendert hat:
if ( GetViewData()->GetSfxDocShell()->IsReadOnly() != bReadOnly )
{
bReadOnly = GetViewData()->GetSfxDocShell()->IsReadOnly();
SfxBoolItem aItem( SID_FM_DESIGN_MODE, !bReadOnly);
GetViewData()->GetDispatcher().Execute( SID_FM_DESIGN_MODE, SFX_CALLMODE_ASYNCHRON,
&aItem, 0L );
UpdateInputContext();
}
break;
case SC_HINT_SHOWRANGEFINDER:
PaintRangeFinder();
break;
case SC_HINT_FORCESETTAB:
SetTabNo( GetViewData()->GetTabNo(), sal_True );
break;
default:
break;
}
}
else if (rHint.ISA(ScPaintHint)) // neu zeichnen
{
ScPaintHint* pHint = (ScPaintHint*) &rHint;
sal_uInt16 nParts = pHint->GetParts();
SCTAB nTab = GetViewData()->GetTabNo();
if (pHint->GetStartTab() <= nTab && pHint->GetEndTab() >= nTab)
{
if (nParts & PAINT_EXTRAS) // zuerst, falls Tabelle weg ist !!!
if (PaintExtras())
nParts = PAINT_ALL;
// if the current sheet has pending row height updates (sheet links refreshed),
// execute them before invalidating the window
GetViewData()->GetDocShell()->UpdatePendingRowHeights( GetViewData()->GetTabNo() );
if (nParts & PAINT_SIZE)
RepeatResize(); //! InvalidateBorder ???
if (nParts & PAINT_GRID)
PaintArea( pHint->GetStartCol(), pHint->GetStartRow(),
pHint->GetEndCol(), pHint->GetEndRow() );
if (nParts & PAINT_MARKS)
PaintArea( pHint->GetStartCol(), pHint->GetStartRow(),
pHint->GetEndCol(), pHint->GetEndRow(), SC_UPDATE_MARKS );
if (nParts & PAINT_LEFT)
PaintLeftArea( pHint->GetStartRow(), pHint->GetEndRow() );
if (nParts & PAINT_TOP)
PaintTopArea( pHint->GetStartCol(), pHint->GetEndCol() );
if (nParts & PAINT_INVERT)
InvertBlockMark( pHint->GetStartCol(), pHint->GetStartRow(),
pHint->GetEndCol(), pHint->GetEndRow() );
// #i84689# call UpdateAllOverlays here instead of in ScTabView::PaintArea
if (nParts & ( PAINT_LEFT | PAINT_TOP )) // only if widths or heights changed
UpdateAllOverlays();
HideNoteMarker();
}
}
else if (rHint.ISA(ScEditViewHint)) // Edit-View anlegen
{
// ScEditViewHint kommt nur an aktiver View an
ScEditViewHint* pHint = (ScEditViewHint*) &rHint;
SCTAB nTab = GetViewData()->GetTabNo();
if ( pHint->GetTab() == nTab )
{
SCCOL nCol = pHint->GetCol();
SCROW nRow = pHint->GetRow();
{
HideNoteMarker();
MakeEditView( pHint->GetEngine(), nCol, nRow );
StopEditShell(); // sollte nicht gesetzt sein
ScSplitPos eActive = GetViewData()->GetActivePart();
if ( GetViewData()->HasEditView(eActive) )
{
// MakeEditView geht schief, wenn der Cursor ausserhalb des
// Bildschirms steht. GetEditView gibt dann eine nicht aktive
// View zurueck, darum die Abfrage HasEditView.
EditView* pView = GetViewData()->GetEditView(eActive); // ist nicht 0
SetEditShell(pView ,sal_True);
}
}
}
}
else if (rHint.ISA(ScTablesHint)) // Tabelle eingefuegt / geloescht
{
// aktuelle Tabelle zuerst holen (kann bei DeleteTab an ViewData geaendert werden)
SCTAB nActiveTab = GetViewData()->GetTabNo();
const ScTablesHint& rTabHint = (const ScTablesHint&)rHint;
SCTAB nTab1 = rTabHint.GetTab1();
SCTAB nTab2 = rTabHint.GetTab2();
sal_uInt16 nId = rTabHint.GetId();
switch (nId)
{
case SC_TAB_INSERTED:
GetViewData()->InsertTab( nTab1 );
break;
case SC_TAB_DELETED:
GetViewData()->DeleteTab( nTab1 );
break;
case SC_TAB_MOVED:
GetViewData()->MoveTab( nTab1, nTab2 );
break;
case SC_TAB_COPIED:
GetViewData()->CopyTab( nTab1, nTab2 );
break;
case SC_TAB_HIDDEN:
break;
default:
DBG_ERROR("unbekannter ScTablesHint");
}
// hier keine Abfrage auf IsActive() mehr, weil die Aktion von Basic ausgehen
// kann und dann auch die aktive View umgeschaltet werden muss.
SCTAB nNewTab = nActiveTab;
bool bStayOnActiveTab = true;
switch (nId)
{
case SC_TAB_INSERTED:
if ( nTab1 <= nNewTab ) // vorher eingefuegt
++nNewTab;
break;
case SC_TAB_DELETED:
if ( nTab1 < nNewTab ) // vorher geloescht
--nNewTab;
else if ( nTab1 == nNewTab ) // aktuelle geloescht
bStayOnActiveTab = false;
break;
case SC_TAB_MOVED:
if ( nNewTab == nTab1 ) // verschobene Tabelle
nNewTab = nTab2;
else if ( nTab1 < nTab2 ) // nach hinten verschoben
{
if ( nNewTab > nTab1 && nNewTab <= nTab2 ) // nachrueckender Bereich
--nNewTab;
}
else // nach vorne verschoben
{
if ( nNewTab >= nTab2 && nNewTab < nTab1 ) // nachrueckender Bereich
++nNewTab;
}
break;
case SC_TAB_COPIED:
if ( nNewTab >= nTab2 ) // vorher eingefuegt
++nNewTab;
break;
case SC_TAB_HIDDEN:
if ( nTab1 == nNewTab ) // aktuelle ausgeblendet
bStayOnActiveTab = false;
break;
}
ScDocument* pDoc = GetViewData()->GetDocument();
if ( nNewTab >= pDoc->GetTableCount() )
nNewTab = pDoc->GetTableCount() - 1;
sal_Bool bForce = !bStayOnActiveTab;
SetTabNo( nNewTab, bForce, sal_False, bStayOnActiveTab );
}
else if (rHint.ISA(ScIndexHint))
{
const ScIndexHint& rIndexHint = (const ScIndexHint&)rHint;
sal_uInt16 nId = rIndexHint.GetId();
sal_uInt16 nIndex = rIndexHint.GetIndex();
switch (nId)
{
case SC_HINT_SHOWRANGEFINDER:
PaintRangeFinder( nIndex );
break;
}
}
SfxViewShell::Notify( rBC, rHint );
}
//------------------------------------------------------------------
void ScTabViewShell::MakeNumberInfoItem( ScDocument* pDoc,
ScViewData* pViewData,
SvxNumberInfoItem** ppItem )
{
//------------------------------
// NumberInfo-Item konstruieren:
//------------------------------
ScBaseCell* pCell = NULL;
SvxNumberValueType eValType = SVX_VALUE_TYPE_UNDEFINED;
double nCellValue = 0;
String aCellString;
pDoc->GetCell( pViewData->GetCurX(),
pViewData->GetCurY(),
pViewData->GetTabNo(),
pCell );
if ( pCell )
{
switch ( pCell->GetCellType() )
{
case CELLTYPE_VALUE:
{
nCellValue = ((ScValueCell*)pCell)->GetValue();
eValType = SVX_VALUE_TYPE_NUMBER;
aCellString.Erase();
}
break;
case CELLTYPE_STRING:
{
((ScStringCell*)pCell)->GetString( aCellString );
eValType = SVX_VALUE_TYPE_STRING;
}
break;
case CELLTYPE_FORMULA:
{
if ( ((ScFormulaCell*)pCell)->IsValue() )
{
nCellValue = ((ScFormulaCell*)pCell)->GetValue();
eValType = SVX_VALUE_TYPE_NUMBER;
}
else
{
nCellValue = 0;
eValType = SVX_VALUE_TYPE_UNDEFINED;
}
aCellString.Erase();
}
break;
default:
nCellValue = 0;
eValType = SVX_VALUE_TYPE_UNDEFINED;
aCellString.Erase();
}
}
else // Zelle noch leer (== nicht erzeugt)
{
nCellValue = 0;
eValType = SVX_VALUE_TYPE_UNDEFINED;
aCellString.Erase();
}
switch ( eValType )
{
case SVX_VALUE_TYPE_STRING:
*ppItem = new SvxNumberInfoItem(
pDoc->GetFormatTable(),
aCellString,
SID_ATTR_NUMBERFORMAT_INFO );
break;
case SVX_VALUE_TYPE_NUMBER:
*ppItem = new SvxNumberInfoItem(
pDoc->GetFormatTable(),
nCellValue,
SID_ATTR_NUMBERFORMAT_INFO );
break;
case SVX_VALUE_TYPE_UNDEFINED:
default:
*ppItem = new SvxNumberInfoItem(
pDoc->GetFormatTable(),
(const sal_uInt16)
SID_ATTR_NUMBERFORMAT_INFO );
}
}
//------------------------------------------------------------------
void ScTabViewShell::UpdateNumberFormatter(
ScDocument* pDoc,
const SvxNumberInfoItem& rInfoItem )
{
const sal_uInt32 nDelCount = rInfoItem.GetDelCount();
if ( nDelCount > 0 )
{
const sal_uInt32* pDelArr = rInfoItem.GetDelArray();
for ( sal_uInt16 i=0; i<nDelCount; i++ )
rInfoItem.GetNumberFormatter()->DeleteEntry( pDelArr[i] );
}
// sollte besser UpdateNumberFormats() heissen ?
pDoc->DeleteNumberFormat( rInfoItem.GetDelArray(),
rInfoItem.GetDelCount() );
}