Files
libreoffice/sc/source/ui/app/inputwin.cxx

1801 lines
57 KiB
C++
Raw Normal View History

2000-09-18 16:07:07 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 16:07:07 +00:00
*
* $RCSfile: inputwin.cxx,v $
2000-09-18 16:07:07 +00:00
*
* $Revision: 1.45 $
2000-09-18 16:07:07 +00:00
*
* last change: $Author: rt $ $Date: 2006-01-13 17:02:49 $
2000-09-18 16:07:07 +00:00
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
2000-09-18 16:07:07 +00:00
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
2000-09-18 16:07:07 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
2000-09-18 16:07:07 +00:00
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
2000-09-18 16:07:07 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
2000-09-18 16:07:07 +00:00
*
************************************************************************/
#ifdef PCH
#include "ui_pch.hxx"
#endif
#pragma hdrstop
//------------------------------------------------------------------
#include "scitems.hxx"
#include "eetext.hxx"
#include <svx/eeitem.hxx>
#define ITEMID_FIELD EE_FEATURE_FIELD
#include <svx/adjitem.hxx>
2000-09-18 16:07:07 +00:00
#include <svx/editview.hxx>
#include <svx/editstat.hxx>
#include <svx/frmdiritem.hxx>
#include <svx/lspcitem.hxx>
2000-09-18 16:07:07 +00:00
#include <sfx2/bindings.hxx>
#include <sfx2/viewfrm.hxx>
2000-09-18 16:07:07 +00:00
#include <sfx2/dispatch.hxx>
#include <sfx2/event.hxx>
#include <sfx2/imgmgr.hxx>
#include <stdlib.h> // qsort
#include <svx/scriptspaceitem.hxx>
#include <svx/scripttypeitem.hxx>
#include <vcl/cursor.hxx>
#include <vcl/help.hxx>
2000-09-18 16:07:07 +00:00
#ifndef _SFXSTRITEM_HXX //autogen
#include <svtools/stritem.hxx>
#endif
#include "inputwin.hxx"
#include "scmod.hxx"
#include "uiitems.hxx"
#include "global.hxx"
#include "scresid.hxx"
#include "sc.hrc"
#include "globstr.hrc"
#include "editutil.hxx"
#include "inputhdl.hxx"
#include "tabvwsh.hxx"
#include "document.hxx"
#include "docsh.hxx"
#include "appoptio.hxx"
#include "rangenam.hxx"
#include "compiler.hrc"
#include "dbcolect.hxx"
#include "rangeutl.hxx"
#include "docfunc.hxx"
2000-09-18 16:07:07 +00:00
#ifndef _SVX_FONTITEM_HXX //autogen
#include <svx/fontitem.hxx>
#endif
#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLE_HPP_
#include <com/sun/star/accessibility/XAccessible.hpp>
2002-06-10 13:56:35 +00:00
#endif
#ifndef _SC_ACCESSIBLEEDITOBJECT_HXX
#include "AccessibleEditObject.hxx"
#endif
#ifndef _SC_ACCESSIBLETEXT_HXX
#include "AccessibleText.hxx"
#endif
2000-09-18 16:07:07 +00:00
#define TEXT_STARTPOS 3
#define THESIZE 1000000 //!!! langt... :-)
#define TBX_WINDOW_HEIGHT 22 // in Pixeln - fuer alle Systeme gleich?
enum ScNameInputType
{
SC_NAME_INPUT_CELL,
SC_NAME_INPUT_RANGE,
SC_NAME_INPUT_NAMEDRANGE,
SC_NAME_INPUT_DATABASE,
SC_NAME_INPUT_ROW,
SC_NAME_INPUT_SHEET,
SC_NAME_INPUT_DEFINE,
SC_NAME_INPUT_BAD_NAME,
SC_NAME_INPUT_BAD_SELECTION
};
2000-09-18 16:07:07 +00:00
//==================================================================
// class ScInputWindowWrapper
//==================================================================
SFX_IMPL_CHILDWINDOW(ScInputWindowWrapper,FID_INPUTLINE_STATUS)
ScInputWindowWrapper::ScInputWindowWrapper( Window* pParent,
USHORT nId,
SfxBindings* pBindings,
SfxChildWinInfo* pInfo )
: SfxChildWindow( pParent, nId )
{
ScInputWindow* pWin=new ScInputWindow( pParent, pBindings );
2000-09-18 16:07:07 +00:00
pWindow = pWin;
pWin->Show();
pWin->SetSizePixel( pWin->CalcWindowSizePixel() );
eChildAlignment = SFX_ALIGN_LOWESTTOP;
pBindings->Invalidate( FID_TOGGLEINPUTLINE );
}
// GetInfo fliegt wieder raus, wenn es ein SFX_IMPL_TOOLBOX gibt !!!!
SfxChildWinInfo __EXPORT ScInputWindowWrapper::GetInfo() const
{
SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
return aInfo;
}
//==================================================================
#define IMAGE(id) pImgMgr->SeekImage(id, bDark)
2000-09-18 16:07:07 +00:00
//==================================================================
// class ScInputWindow
//==================================================================
ScInputWindow::ScInputWindow( Window* pParent, SfxBindings* pBind ) :
2000-09-18 16:07:07 +00:00
#ifdef OS2
// #37192# ohne WB_CLIPCHILDREN wg. os/2 Paintproblem
ToolBox ( pParent, WinBits(WB_BORDER|WB_3DLOOK) ),
#else
// mit WB_CLIPCHILDREN, sonst Flicker
ToolBox ( pParent, WinBits(WB_BORDER|WB_3DLOOK|WB_CLIPCHILDREN) ),
#endif
aWndPos ( this ),
aTextWindow ( this ),
aTextOk ( ScResId( SCSTR_QHELP_BTNOK ) ), // nicht immer neu aus Resource
aTextCancel ( ScResId( SCSTR_QHELP_BTNCANCEL ) ),
aTextSum ( ScResId( SCSTR_QHELP_BTNSUM ) ),
aTextEqual ( ScResId( SCSTR_QHELP_BTNEQUAL ) ),
pBindings ( pBind ),
2000-09-18 16:07:07 +00:00
bIsOkCancelMode ( FALSE ),
pInputHdl ( NULL )
{
ScModule* pScMod = SC_MOD();
SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
2000-09-18 16:07:07 +00:00
BOOL bDark = GetDisplayBackground().GetColor().IsDark();
2000-09-18 16:07:07 +00:00
// Positionsfenster, 3 Buttons, Eingabefenster
InsertWindow ( 1, &aWndPos, 0, 0 );
InsertSeparator ( 1 );
InsertItem ( SID_INPUT_FUNCTION, IMAGE( SID_INPUT_FUNCTION ), 0, 2 );
InsertItem ( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ), 0, 3 );
InsertItem ( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ), 0, 4 );
InsertSeparator ( 5 );
InsertWindow ( 7, &aTextWindow, 0, 6 );
aWndPos .SetQuickHelpText( ScResId( SCSTR_QHELP_POSWND ) );
aWndPos .SetHelpId ( HID_INSWIN_POS );
aTextWindow.SetQuickHelpText( ScResId( SCSTR_QHELP_INPUTWND ) );
aTextWindow.SetHelpId ( HID_INSWIN_INPUT );
// kein SetHelpText, die Hilfetexte kommen aus der Hilfe
SetItemText ( SID_INPUT_FUNCTION, ScResId( SCSTR_QHELP_BTNCALC ) );
SetHelpId ( SID_INPUT_FUNCTION, HID_INSWIN_CALC );
SetItemText ( SID_INPUT_SUM, aTextSum );
SetHelpId ( SID_INPUT_SUM, HID_INSWIN_SUMME );
SetItemText ( SID_INPUT_EQUAL, aTextEqual );
SetHelpId ( SID_INPUT_EQUAL, HID_INSWIN_FUNC );
SetHelpId( HID_SC_INPUTWIN ); // fuer die ganze Eingabezeile
aWndPos .Show();
aTextWindow .Show();
pInputHdl = SC_MOD()->GetInputHdl( NULL, FALSE ); // use own handler even if ref-handler is set
2000-09-18 16:07:07 +00:00
if (pInputHdl)
pInputHdl->SetInputWindow( this );
if ( pInputHdl && pInputHdl->GetFormString().Len() )
{
// Umschalten waehrend der Funktionsautopilot aktiv ist
// -> Inhalt des Funktionsautopiloten wieder anzeigen
//! auch Selektion (am InputHdl gemerkt) wieder anzeigen
aTextWindow.SetTextString( pInputHdl->GetFormString() );
}
else if ( pInputHdl && pInputHdl->IsInputMode() )
{
// wenn waehrend des Editierens die Eingabezeile weg war
// (Editieren einer Formel, dann umschalten zu fremdem Dokument/Hilfe),
// wieder den gerade editierten Text aus dem InputHandler anzeigen
aTextWindow.SetTextString( pInputHdl->GetEditString() ); // Text anzeigen
if ( pInputHdl->IsTopMode() )
pInputHdl->SetMode( SC_INPUT_TABLE ); // Focus kommt eh nach unten
}
else if ( pViewSh )
pViewSh->UpdateInputHandler( TRUE ); // unbedingtes Update
pImgMgr->RegisterToolBox( this );
2000-09-18 16:07:07 +00:00
}
__EXPORT ScInputWindow::~ScInputWindow()
{
2001-07-02 09:17:00 +00:00
BOOL bDown = ( ScGlobal::pSysLocale == NULL ); // after Clear?
2000-09-18 16:07:07 +00:00
// if any view's input handler has a pointer to this input window, reset it
// (may be several ones, #74522#)
// member pInputHdl is not used here
if ( !bDown )
{
TypeId aScType = TYPE(ScTabViewShell);
SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
while ( pSh )
{
ScInputHandler* pHdl = ((ScTabViewShell*)pSh)->GetInputHandler();
if ( pHdl && pHdl->GetInputWindow() == this )
{
2000-09-18 16:07:07 +00:00
pHdl->SetInputWindow( NULL );
pHdl->StopInputWinEngine( FALSE ); // #125841# reset pTopView pointer
}
2000-09-18 16:07:07 +00:00
pSh = SfxViewShell::GetNext( *pSh, &aScType );
}
}
SfxImageManager::GetImageManager( SC_MOD() )->ReleaseToolBox( this );
2000-09-18 16:07:07 +00:00
}
void ScInputWindow::SetInputHandler( ScInputHandler* pNew )
{
// wird im Activate der View gerufen...
if ( pNew != pInputHdl )
{
// Bei Reload (letzte Version) ist pInputHdl der Input-Handler der alten,
// geloeschten ViewShell, darum hier auf keinen Fall anfassen!
pInputHdl = pNew;
if (pInputHdl)
pInputHdl->SetInputWindow( this );
}
}
sal_Bool ScInputWindow::UseSubTotal(ScRangeList* pRangeList) const
{
sal_Bool bSubTotal(sal_False);
ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
if ( pViewSh )
{
ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
sal_Int32 nRangeCount (pRangeList->Count());
sal_Int32 nRangeIndex (0);
while (!bSubTotal && nRangeIndex < nRangeCount)
{
const ScRange* pRange = pRangeList->GetObject( nRangeIndex );
if( pRange )
{
SCTAB nTabEnd(pRange->aEnd.Tab());
SCTAB nTab(pRange->aStart.Tab());
while (!bSubTotal && nTab <= nTabEnd)
{
SCROW nRowEnd(pRange->aEnd.Row());
SCROW nRow(pRange->aStart.Row());
while (!bSubTotal && nRow <= nRowEnd)
{
if (pDoc->IsFiltered(nRow, nTab))
bSubTotal = sal_True;
else
++nRow;
}
++nTab;
}
}
++nRangeIndex;
}
ScDBCollection* pDBCollection = pDoc->GetDBCollection();
sal_uInt16 nDBCount (pDBCollection->GetCount());
sal_uInt16 nDBIndex (0);
while (!bSubTotal && nDBIndex < nDBCount)
{
ScDBData* pDB = (*pDBCollection)[nDBIndex];
if (pDB && pDB->HasAutoFilter())
{
nRangeIndex = 0;
while (!bSubTotal && nRangeIndex < nRangeCount)
{
const ScRange* pRange = pRangeList->GetObject( nRangeIndex );
if( pRange )
{
ScRange aDBArea;
pDB->GetArea(aDBArea);
if (aDBArea.Intersects(*pRange))
bSubTotal = sal_True;
}
++nRangeIndex;
}
}
++nDBIndex;
}
}
return bSubTotal;
}
2000-09-18 16:07:07 +00:00
void __EXPORT ScInputWindow::Select()
{
ScModule* pScMod = SC_MOD();
ToolBox::Select();
switch ( GetCurItemId() )
{
case SID_INPUT_FUNCTION:
{
//! new method at ScModule to query if function autopilot is open
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
{
2000-09-22 17:57:10 +00:00
pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
2000-09-18 16:07:07 +00:00
SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
// die Toolbox wird sowieso disabled, also braucht auch nicht umgeschaltet
// zu werden, egal ob's geklappt hat oder nicht
// SetOkCancelMode();
}
}
break;
case SID_INPUT_CANCEL:
pScMod->InputCancelHandler();
SetSumAssignMode();
break;
case SID_INPUT_OK:
pScMod->InputEnterHandler();
SetSumAssignMode();
aTextWindow.Invalidate(); // sonst bleibt Selektion stehen
break;
case SID_INPUT_SUM:
{
ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
if ( pViewSh )
{
ScMarkData& rMark = pViewSh->GetViewData()->GetMarkData();
ScRangeList* pRangeList = new ScRangeList;
BOOL bDataFound = pViewSh->GetAutoSumArea( *pRangeList );
sal_Bool bSubTotal(UseSubTotal(pRangeList));
2000-09-18 16:07:07 +00:00
if ((rMark.IsMarked() || rMark.IsMultiMarked()) && bDataFound)
{
pViewSh->EnterAutoSum( *pRangeList, bSubTotal ); // Block mit Summen fuellen
2000-09-18 16:07:07 +00:00
}
else // nur in Eingabezeile einfuegen
{
String aFormula = '=';
ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
const ScFuncDesc* pDesc = NULL;
if (!bSubTotal)
pDesc = pFuncMgr->Get( SC_OPCODE_SUM );
else
pDesc = pFuncMgr->Get( SC_OPCODE_SUB_TOTAL );
2000-09-18 16:07:07 +00:00
if ( pDesc && pDesc->pFuncName )
{
aFormula += *pDesc->pFuncName;
if (bSubTotal)
aFormula.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "(9;)" ));
else
aFormula.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
2000-09-18 16:07:07 +00:00
}
xub_StrLen nPos = aFormula.Len() - 1;
String aRef;
ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
2000-09-18 16:07:07 +00:00
pRangeList->Format( aRef, SCA_VALID, pDoc );
aFormula.Insert( aRef, nPos );
SetFuncString( aFormula );
if ( bDataFound && pScMod->IsEditMode() )
{
ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
if ( pHdl )
{
pHdl->InitRangeFinder( aFormula );
//! SetSelection am InputHandler ???
//! bSelIsRef setzen ???
xub_StrLen nOpen = aFormula.Search('(');
xub_StrLen nLen = aFormula.Len();
if ( nOpen != STRING_NOTFOUND && nLen > nOpen )
{
sal_uInt8 nAdd(1);
if (bSubTotal)
nAdd = 3;
ESelection aSel(0,nOpen+nAdd,0,nLen-1);
2000-09-18 16:07:07 +00:00
EditView* pTableView = pHdl->GetTableView();
if (pTableView)
pTableView->SetSelection(aSel);
EditView* pTopView = pHdl->GetTopView();
if (pTopView)
pTopView->SetSelection(aSel);
}
}
}
}
delete pRangeList;
}
}
break;
case SID_INPUT_EQUAL:
{
aTextWindow.StartEditEngine();
if ( pScMod->IsEditMode() ) // nicht, wenn z.B. geschuetzt
{
aTextWindow.GrabFocus();
aTextWindow.SetTextString( '=' );
EditView* pView = aTextWindow.GetEditView();
if (pView)
{
pView->SetSelection( ESelection(0,1, 0,1) );
pScMod->InputChanged(pView);
SetOkCancelMode();
pView->SetEditEngineUpdateMode(TRUE);
}
}
break;
}
}
}
void __EXPORT ScInputWindow::Resize()
{
ToolBox::Resize();
long nWidth = GetSizePixel().Width();
long nLeft = aTextWindow.GetPosPixel().X();
Size aSize = aTextWindow.GetSizePixel();
aSize.Width() = Max( ((long)(nWidth - nLeft - 5)), (long)0 );
aTextWindow.SetSizePixel( aSize );
aTextWindow.Invalidate();
}
void ScInputWindow::SetFuncString( const String& rString, BOOL bDoEdit )
{
//! new method at ScModule to query if function autopilot is open
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
aTextWindow.StartEditEngine();
ScModule* pScMod = SC_MOD();
if ( pScMod->IsEditMode() )
{
if ( bDoEdit )
aTextWindow.GrabFocus();
2000-09-18 16:07:07 +00:00
aTextWindow.SetTextString( rString );
EditView* pView = aTextWindow.GetEditView();
if (pView)
{
xub_StrLen nLen = rString.Len();
if ( nLen > 0 )
{
nLen--;
pView->SetSelection( ESelection( 0, nLen, 0, nLen ) );
}
pScMod->InputChanged(pView);
if ( bDoEdit )
SetOkCancelMode(); // nicht, wenn gleich hinterher Enter/Cancel
pView->SetEditEngineUpdateMode(TRUE);
}
}
}
void ScInputWindow::SetPosString( const String& rStr )
{
aWndPos.SetPos( rStr );
}
void ScInputWindow::SetTextString( const String& rString )
{
if (rString.Len() <= 32767)
aTextWindow.SetTextString(rString);
else
{
String aNew = rString;
aNew.Erase(32767);
aTextWindow.SetTextString(aNew);
}
}
const String& ScInputWindow::GetTextString()
{
return aTextWindow.GetTextString();
}
void ScInputWindow::SetOkCancelMode()
{
//! new method at ScModule to query if function autopilot is open
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
ScModule* pScMod = SC_MOD();
SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
2000-09-18 16:07:07 +00:00
if (!bIsOkCancelMode)
{
BOOL bDark = GetDisplayBackground().GetColor().IsDark();
2000-09-18 16:07:07 +00:00
RemoveItem( 3 ); // SID_INPUT_SUM und SID_INPUT_EQUAL entfernen
RemoveItem( 3 );
InsertItem( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ), 0, 3 );
InsertItem( SID_INPUT_OK, IMAGE( SID_INPUT_OK ), 0, 4 );
SetItemText ( SID_INPUT_CANCEL, aTextCancel );
SetHelpId ( SID_INPUT_CANCEL, HID_INSWIN_CANCEL );
SetItemText ( SID_INPUT_OK, aTextOk );
SetHelpId ( SID_INPUT_OK, HID_INSWIN_OK );
bIsOkCancelMode = TRUE;
}
}
void ScInputWindow::SetSumAssignMode()
{
//! new method at ScModule to query if function autopilot is open
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
ScModule* pScMod = SC_MOD();
SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
2000-09-18 16:07:07 +00:00
if (bIsOkCancelMode)
{
BOOL bDark = GetDisplayBackground().GetColor().IsDark();
2000-09-18 16:07:07 +00:00
// SID_INPUT_CANCEL, und SID_INPUT_OK entfernen
RemoveItem( 3 );
RemoveItem( 3 );
InsertItem( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ), 0, 3 );
InsertItem( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ), 0, 4 );
SetItemText ( SID_INPUT_SUM, aTextSum );
SetHelpId ( SID_INPUT_SUM, HID_INSWIN_SUMME );
SetItemText ( SID_INPUT_EQUAL, aTextEqual );
SetHelpId ( SID_INPUT_EQUAL, HID_INSWIN_FUNC );
bIsOkCancelMode = FALSE;
SetFormulaMode(FALSE); // kein editieren -> keine Formel
}
}
void ScInputWindow::SetFormulaMode( BOOL bSet )
{
aWndPos.SetFormulaMode(bSet);
aTextWindow.SetFormulaMode(bSet);
}
void __EXPORT ScInputWindow::SetText( const String& rString )
{
ToolBox::SetText(rString);
}
String __EXPORT ScInputWindow::GetText() const
{
return ToolBox::GetText();
}
EditView* ScInputWindow::ActivateEdit( const String& rText,
const ESelection& rSel )
{
if ( !aTextWindow.IsActive() )
{
aTextWindow.StartEditEngine();
aTextWindow.GrabFocus();
aTextWindow.SetTextString( rText );
aTextWindow.GetEditView()->SetSelection( rSel );
}
return aTextWindow.GetEditView();
}
BOOL ScInputWindow::IsActive()
{
return aTextWindow.IsActive();
}
EditView* ScInputWindow::GetEditView()
{
return aTextWindow.GetEditView();
}
void ScInputWindow::MakeDialogEditView()
{
aTextWindow.MakeDialogEditView();
}
void ScInputWindow::StopEditEngine( BOOL bAll )
2000-09-18 16:07:07 +00:00
{
aTextWindow.StopEditEngine( bAll );
2000-09-18 16:07:07 +00:00
}
void ScInputWindow::TextGrabFocus()
{
aTextWindow.GrabFocus();
}
void ScInputWindow::TextInvalidate()
{
aTextWindow.Invalidate();
}
void ScInputWindow::SwitchToTextWin()
{
// used for shift-ctrl-F2
aTextWindow.StartEditEngine();
if ( SC_MOD()->IsEditMode() )
{
aTextWindow.GrabFocus();
EditView* pView = aTextWindow.GetEditView();
if (pView)
{
xub_StrLen nLen = pView->GetEditEngine()->GetTextLen(0);
ESelection aSel( 0, nLen, 0, nLen );
pView->SetSelection( aSel ); // set cursor to end of text
}
}
}
2000-09-18 16:07:07 +00:00
void ScInputWindow::PosGrabFocus()
{
aWndPos.GrabFocus();
}
void ScInputWindow::EnableButtons( BOOL bEnable )
{
// when enabling buttons, always also enable the input window itself
if ( bEnable && !IsEnabled() )
Enable();
2000-09-18 16:07:07 +00:00
EnableItem( SID_INPUT_FUNCTION, bEnable );
EnableItem( bIsOkCancelMode ? SID_INPUT_CANCEL : SID_INPUT_SUM, bEnable );
EnableItem( bIsOkCancelMode ? SID_INPUT_OK : SID_INPUT_EQUAL, bEnable );
// Invalidate();
}
void ScInputWindow::StateChanged( StateChangedType nType )
{
ToolBox::StateChanged( nType );
if ( nType == STATE_CHANGE_INITSHOW ) Resize();
}
void ScInputWindow::DataChanged( const DataChangedEvent& rDCEvt )
{
if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
{
// update item images
ScModule* pScMod = SC_MOD();
SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
BOOL bDark = GetDisplayBackground().GetColor().IsDark();
// IMAGE macro uses pScMod, pImgMgr, bDark
SetItemImage( SID_INPUT_FUNCTION, IMAGE( SID_INPUT_FUNCTION ) );
if ( bIsOkCancelMode )
{
SetItemImage( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ) );
SetItemImage( SID_INPUT_OK, IMAGE( SID_INPUT_OK ) );
}
else
{
SetItemImage( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ) );
SetItemImage( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ) );
}
}
ToolBox::DataChanged( rDCEvt );
}
2000-09-18 16:07:07 +00:00
//========================================================================
// Eingabefenster
//========================================================================
ScTextWnd::ScTextWnd( Window* pParent )
: Window ( pParent, WinBits(WB_HIDE | WB_BORDER) ),
2001-04-03 16:44:46 +00:00
DragSourceHelper( this ),
2000-09-18 16:07:07 +00:00
pEditEngine ( NULL ),
pEditView ( NULL ),
pAccTextData ( NULL ),
2000-09-18 16:07:07 +00:00
bIsInsertMode( TRUE ),
bFormulaMode ( FALSE ),
bInputMode ( FALSE )
2000-09-18 16:07:07 +00:00
{
EnableRTL( FALSE ); // #106269# EditEngine can't be used with VCL EnableRTL
bIsRTL = GetSettings().GetLayoutRTL();
// #79096# always use application font, so a font with cjk chars can be installed
2000-09-18 16:07:07 +00:00
Font aAppFont = GetFont();
aTextFont = aAppFont;
aTextFont.SetSize( PixelToLogic( aAppFont.GetSize(), MAP_TWIP ) ); // AppFont ist in Pixeln
const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
Color aBgColor= rStyleSettings.GetWindowColor();
Color aTxtColor= rStyleSettings.GetWindowTextColor();
aTextFont.SetTransparent ( TRUE );
aTextFont.SetFillColor ( aBgColor );
//aTextFont.SetColor ( COL_FIELDTEXT );
aTextFont.SetColor (aTxtColor);
aTextFont.SetWeight ( WEIGHT_NORMAL );
SetSizePixel ( Size(1,TBX_WINDOW_HEIGHT) );
SetBackground ( aBgColor );
SetLineColor ( COL_BLACK );
SetMapMode ( MAP_TWIP );
SetPointer ( POINTER_TEXT );
}
__EXPORT ScTextWnd::~ScTextWnd()
{
delete pEditView;
delete pEditEngine;
if (pAccTextData)
pAccTextData->Dispose();
2000-09-18 16:07:07 +00:00
}
void __EXPORT ScTextWnd::Paint( const Rectangle& rRec )
{
if (pEditView)
pEditView->Paint( rRec );
else
{
SetFont( aTextFont );
long nDiff = GetOutputSizePixel().Height()
- LogicToPixel( Size( 0, GetTextHeight() ) ).Height();
// if (nDiff<2) nDiff=2; // mind. 1 Pixel
long nStartPos = TEXT_STARTPOS;
if ( bIsRTL )
{
// right-align
nStartPos += GetOutputSizePixel().Width() - 2*TEXT_STARTPOS -
LogicToPixel( Size( GetTextWidth( aString ), 0 ) ).Width();
// LayoutMode isn't changed as long as ModifyRTLDefaults doesn't include SvxFrameDirectionItem
}
DrawText( PixelToLogic( Point( nStartPos, nDiff/2 ) ), aString );
2000-09-18 16:07:07 +00:00
}
}
void __EXPORT ScTextWnd::Resize()
{
if (pEditView)
{
Size aSize = GetOutputSizePixel();
long nDiff = aSize.Height()
- LogicToPixel( Size( 0, GetTextHeight() ) ).Height();
#ifdef OS2_DOCH_NICHT
nDiff-=2; // wird durch 2 geteilt
// passt sonst nicht zur normalen Textausgabe
#endif
aSize.Width() -= 2 * TEXT_STARTPOS - 1;
2000-09-18 16:07:07 +00:00
pEditView->SetOutputArea(
PixelToLogic( Rectangle( Point( TEXT_STARTPOS, (nDiff > 0) ? nDiff/2 : 1 ),
aSize ) ) );
}
}
void __EXPORT ScTextWnd::MouseMove( const MouseEvent& rMEvt )
{
if (pEditView)
pEditView->MouseMove( rMEvt );
}
void __EXPORT ScTextWnd::MouseButtonDown( const MouseEvent& rMEvt )
{
if (!HasFocus())
{
StartEditEngine();
if ( SC_MOD()->IsEditMode() )
GrabFocus();
}
if (pEditView)
{
pEditView->SetEditEngineUpdateMode( TRUE );
pEditView->MouseButtonDown( rMEvt );
}
}
void __EXPORT ScTextWnd::MouseButtonUp( const MouseEvent& rMEvt )
{
if (pEditView)
if (pEditView->MouseButtonUp( rMEvt ))
2001-10-02 17:32:43 +00:00
{
if ( rMEvt.IsMiddle() &&
GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
{
// EditView may have pasted from selection
SC_MOD()->InputChanged( pEditView );
}
else
SC_MOD()->InputSelection( pEditView );
}
2000-09-18 16:07:07 +00:00
}
void __EXPORT ScTextWnd::Command( const CommandEvent& rCEvt )
{
bInputMode = TRUE;
2000-09-18 16:07:07 +00:00
USHORT nCommand = rCEvt.GetCommand();
if ( pEditView /* && ( nCommand == COMMAND_STARTDRAG || nCommand == COMMAND_VOICE ) */ )
{
ScModule* pScMod = SC_MOD();
ScTabViewShell* pStartViewSh = ScTabViewShell::GetActiveViewShell();
// #109441# don't modify the font defaults here - the right defaults are
// already set in StartEditEngine when the EditEngine is created
2000-09-18 16:07:07 +00:00
// #63263# verhindern, dass die EditView beim View-Umschalten wegkommt
pScMod->SetInEditCommand( TRUE );
pEditView->Command( rCEvt );
pScMod->SetInEditCommand( FALSE );
// #48929# COMMAND_STARTDRAG heiss noch lange nicht, dass der Inhalt geaendert wurde
// darum in dem Fall kein InputChanged
//! erkennen, ob mit Move gedraggt wurde, oder Drag&Move irgendwie verbieten
if ( nCommand == COMMAND_STARTDRAG )
{
// ist auf eine andere View gedraggt worden?
ScTabViewShell* pEndViewSh = ScTabViewShell::GetActiveViewShell();
if ( pEndViewSh != pStartViewSh && pStartViewSh != NULL )
{
ScViewData* pViewData = pStartViewSh->GetViewData();
ScInputHandler* pHdl = pScMod->GetInputHdl( pStartViewSh );
if ( pHdl && pViewData->HasEditView( pViewData->GetActivePart() ) )
{
pHdl->CancelHandler();
pViewData->GetView()->ShowCursor(); // fehlt bei KillEditView, weil nicht aktiv
}
}
}
else if ( nCommand == COMMAND_CURSORPOS )
{
// don't call InputChanged for COMMAND_CURSORPOS
}
else if ( nCommand == 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.
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if (pViewFrm)
{
SfxBindings& rBindings = pViewFrm->GetBindings();
rBindings.Invalidate( SID_ATTR_CHAR_FONT );
rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
}
}
2000-09-18 16:07:07 +00:00
else
SC_MOD()->InputChanged( pEditView );
}
else
Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
bInputMode = FALSE;
2000-09-18 16:07:07 +00:00
}
2001-04-03 16:44:46 +00:00
void ScTextWnd::StartDrag( sal_Int8 nAction, const Point& rPosPixel )
{
if ( pEditView )
{
CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, TRUE );
pEditView->Command( aDragEvent );
// handling of d&d to different view (CancelHandler) can't be done here,
// because the call returns before d&d is complete.
}
}
2000-09-18 16:07:07 +00:00
void __EXPORT ScTextWnd::KeyInput(const KeyEvent& rKEvt)
{
bInputMode = TRUE;
2000-09-18 16:07:07 +00:00
if (!SC_MOD()->InputKeyEvent( rKEvt ))
{
BOOL bUsed = FALSE;
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if ( pViewSh )
bUsed = pViewSh->SfxKeyInput(rKEvt); // nur Acceleratoren, keine Eingabe
if (!bUsed)
Window::KeyInput( rKEvt );
}
bInputMode = FALSE;
2000-09-18 16:07:07 +00:00
}
void __EXPORT ScTextWnd::GetFocus()
{
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if ( pViewSh )
pViewSh->SetFormShellAtTop( FALSE ); // focus in input line -> FormShell no longer on top
2000-09-18 16:07:07 +00:00
}
void __EXPORT ScTextWnd::LoseFocus()
{
}
String __EXPORT ScTextWnd::GetText() const
{
// ueberladen, um per Testtool an den Text heranzukommen
if ( pEditEngine )
return pEditEngine->GetText();
else
return GetTextString();
}
void ScTextWnd::SetFormulaMode( BOOL bSet )
{
if ( bSet != bFormulaMode )
{
bFormulaMode = bSet;
UpdateAutoCorrFlag();
}
}
void ScTextWnd::UpdateAutoCorrFlag()
{
if ( pEditEngine )
{
ULONG nControl = pEditEngine->GetControlWord();
ULONG nOld = nControl;
if ( bFormulaMode )
nControl &= ~EE_CNTRL_AUTOCORRECT; // keine Autokorrektur in Formeln
else
nControl |= EE_CNTRL_AUTOCORRECT; // sonst schon
if ( nControl != nOld )
pEditEngine->SetControlWord( nControl );
}
}
void lcl_ExtendEditFontAttribs( SfxItemSet& rSet )
{
const SfxPoolItem& rFontItem = rSet.Get( EE_CHAR_FONTINFO );
rSet.Put( rFontItem, EE_CHAR_FONTINFO_CJK );
rSet.Put( rFontItem, EE_CHAR_FONTINFO_CTL );
const SfxPoolItem& rHeightItem = rSet.Get( EE_CHAR_FONTHEIGHT );
rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CJK );
rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CTL );
const SfxPoolItem& rWeightItem = rSet.Get( EE_CHAR_WEIGHT );
rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CJK );
rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CTL );
const SfxPoolItem& rItalicItem = rSet.Get( EE_CHAR_ITALIC );
rSet.Put( rItalicItem, EE_CHAR_ITALIC_CJK );
rSet.Put( rItalicItem, EE_CHAR_ITALIC_CTL );
const SfxPoolItem& rLangItem = rSet.Get( EE_CHAR_LANGUAGE );
rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CJK );
rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CTL );
}
void lcl_ModifyRTLDefaults( SfxItemSet& rSet )
{
rSet.Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
// always using rtl writing direction would break formulas
//rSet.Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
// PaperSize width is limited to USHRT_MAX in RTL mode (because of EditEngine's
// USHORT values in EditLine), so the text may be wrapped and line spacing must be
// increased to not see the beginning of the next line.
SvxLineSpacingItem aItem( SVX_LINESPACE_TWO_LINES, EE_PARA_SBL );
aItem.SetPropLineSpace( 200 );
rSet.Put( aItem );
}
void lcl_ModifyRTLVisArea( EditView* pEditView )
{
Rectangle aVisArea = pEditView->GetVisArea();
Size aPaper = pEditView->GetEditEngine()->GetPaperSize();
long nDiff = aPaper.Width() - aVisArea.Right();
aVisArea.Left() += nDiff;
aVisArea.Right() += nDiff;
pEditView->SetVisArea(aVisArea);
}
2000-09-18 16:07:07 +00:00
void ScTextWnd::StartEditEngine()
{
// #31147# Bei "eigener Modalitaet" (Doc-modale Dialoge) nicht aktivieren
SfxObjectShell* pObjSh = SfxObjectShell::Current();
if ( pObjSh && pObjSh->IsInModalMode() )
return;
if ( !pEditView || !pEditEngine )
{
ScFieldEditEngine* pNew;
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if ( pViewSh )
{
const ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
pNew = new ScFieldEditEngine( pDoc->GetEnginePool(), pDoc->GetEditPool() );
}
else
pNew = new ScFieldEditEngine( EditEngine::CreatePool(), NULL, TRUE );
pNew->SetExecuteURL( FALSE );
pEditEngine = pNew;
pEditEngine->SetUpdateMode( FALSE );
pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
2000-09-18 16:07:07 +00:00
pEditEngine->SetWordDelimiters(
ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
UpdateAutoCorrFlag();
{
SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
pEditEngine->SetFontInfoInItemSet( *pSet, aTextFont );
lcl_ExtendEditFontAttribs( *pSet );
// turn off script spacing to match DrawText output
pSet->Put( SvxScriptSpaceItem( FALSE, EE_PARA_ASIANCJKSPACING ) );
if ( bIsRTL )
lcl_ModifyRTLDefaults( *pSet );
2000-09-18 16:07:07 +00:00
pEditEngine->SetDefaults( pSet );
}
// #57254# Wenn in der Zelle URL-Felder enthalten sind, muessen die auch in
// die Eingabezeile uebernommen werden, weil sonst die Positionen nicht stimmen.
BOOL bFilled = FALSE;
ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
if ( pHdl ) //! Testen, ob's der richtige InputHdl ist?
bFilled = pHdl->GetTextAndFields( *pEditEngine );
pEditEngine->SetUpdateMode( TRUE );
// aString ist die Wahrheit...
if ( bFilled && pEditEngine->GetText() == aString )
Invalidate(); // Repaint fuer (hinterlegte) Felder
else
pEditEngine->SetText(aString); // dann wenigstens den richtigen Text
pEditView = new EditView( pEditEngine, this );
pEditView->SetInsertMode(bIsInsertMode);
// Text aus Clipboard wird als ASCII einzeilig uebernommen
ULONG n = pEditView->GetControlWord();
pEditView->SetControlWord( n | EV_CNTRL_SINGLELINEPASTE );
pEditEngine->InsertView( pEditView, EE_APPEND );
Resize();
if ( bIsRTL )
lcl_ModifyRTLVisArea( pEditView );
pEditEngine->SetModifyHdl(LINK(this, ScTextWnd, NotifyHdl));
if (pAccTextData)
pAccTextData->StartEdit();
// as long as EditEngine and DrawText sometimes differ for CTL text,
// repaint now to have the EditEngine's version visible
SfxObjectShell* pObjSh = SfxObjectShell::Current();
if ( pObjSh && pObjSh->ISA(ScDocShell) )
{
ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument(); // any document
BYTE nScript = pDoc->GetStringScriptType( aString );
if ( nScript & SCRIPTTYPE_COMPLEX )
Invalidate();
}
2000-09-18 16:07:07 +00:00
}
SC_MOD()->SetInputMode( SC_INPUT_TOP );
2000-09-22 17:57:10 +00:00
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if (pViewFrm)
pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
2000-09-18 16:07:07 +00:00
}
IMPL_LINK(ScTextWnd, NotifyHdl, EENotify*, aNotify)
{
if (pEditView && !bInputMode)
{
ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
// #105354# Use the InputHandler's InOwnChange flag to prevent calling InputChanged
// while an InputHandler method is modifying the EditEngine content
if ( pHdl && !pHdl->IsInOwnChange() )
pHdl->InputChanged( pEditView, TRUE ); // #i20282# InputChanged must know if called from modify handler
}
return 0;
}
void ScTextWnd::StopEditEngine( BOOL bAll )
2000-09-18 16:07:07 +00:00
{
if (pEditView)
{
if (pAccTextData)
pAccTextData->EndEdit();
2000-09-18 16:07:07 +00:00
ScModule* pScMod = SC_MOD();
if (!bAll)
pScMod->InputSelection( pEditView );
2000-09-18 16:07:07 +00:00
aString = pEditEngine->GetText();
bIsInsertMode = pEditView->IsInsertMode();
BOOL bSelection = pEditView->HasSelection();
pEditEngine->SetModifyHdl(Link());
2000-09-18 16:07:07 +00:00
DELETEZ(pEditView);
DELETEZ(pEditEngine);
if ( pScMod->IsEditMode() && !bAll )
2000-09-18 16:07:07 +00:00
pScMod->SetInputMode(SC_INPUT_TABLE);
2000-09-22 17:57:10 +00:00
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if (pViewFrm)
pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
2000-09-18 16:07:07 +00:00
if (bSelection)
Invalidate(); // damit Selektion nicht stehenbleibt
}
}
void ScTextWnd::SetTextString( const String& rNewString )
{
if ( rNewString != aString )
{
bInputMode = TRUE;
2000-09-18 16:07:07 +00:00
// Position der Aenderung suchen, nur Rest painten
long nInvPos = 0;
long nStartPos = 0;
long nYPos = 0;
long nTextSize = 0;
if (!pEditEngine)
{
BOOL bPaintAll;
if ( bIsRTL )
bPaintAll = TRUE;
else
{
// test if CTL script type is involved
BYTE nOldScript = 0;
BYTE nNewScript = 0;
SfxObjectShell* pObjSh = SfxObjectShell::Current();
if ( pObjSh && pObjSh->ISA(ScDocShell) )
{
// any document can be used (used only for its break iterator)
ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument();
nOldScript = pDoc->GetStringScriptType( aString );
nNewScript = pDoc->GetStringScriptType( rNewString );
}
bPaintAll = ( nOldScript & SCRIPTTYPE_COMPLEX ) || ( nNewScript & SCRIPTTYPE_COMPLEX );
}
2000-09-18 16:07:07 +00:00
if ( bPaintAll )
{
// if CTL is involved, the whole text has to be redrawn
Invalidate();
}
2000-09-18 16:07:07 +00:00
else
{
xub_StrLen nDifPos;
if (rNewString.Len() > aString.Len())
nDifPos = rNewString.Match(aString);
else
nDifPos = aString.Match(rNewString);
long nSize1 = GetTextWidth(aString);
long nSize2 = GetTextWidth(rNewString);
if ( nSize1>0 && nSize2>0 )
nTextSize = Max( nSize1, nSize2 );
else
nTextSize = GetOutputSize().Width(); // Ueberlauf
if (nDifPos == STRING_MATCH)
nDifPos = 0;
// -1 wegen Rundung und "A"
Point aLogicStart = PixelToLogic(Point(TEXT_STARTPOS-1,0));
nStartPos = aLogicStart.X();
nInvPos = nStartPos;
if (nDifPos)
nInvPos += GetTextWidth(aString,0,nDifPos);
USHORT nFlags = 0;
if ( nDifPos == aString.Len() ) // only new characters appended
nFlags = INVALIDATE_NOERASE; // then background is already clear
Invalidate( Rectangle( nInvPos, 0,
nStartPos+nTextSize, GetOutputSize().Height()-1 ),
nFlags );
}
2000-09-18 16:07:07 +00:00
}
else
{
pEditEngine->SetText(rNewString);
}
aString = rNewString;
if (pAccTextData)
pAccTextData->TextChanged();
bInputMode = FALSE;
2000-09-18 16:07:07 +00:00
}
}
const String& ScTextWnd::GetTextString() const
{
return aString;
}
BOOL ScTextWnd::IsActive()
{
return HasFocus();
}
EditView* ScTextWnd::GetEditView()
{
return pEditView;
}
void ScTextWnd::MakeDialogEditView()
{
if ( pEditView ) return;
ScFieldEditEngine* pNew;
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if ( pViewSh )
{
const ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
pNew = new ScFieldEditEngine( pDoc->GetEnginePool(), pDoc->GetEditPool() );
}
else
pNew = new ScFieldEditEngine( EditEngine::CreatePool(), NULL, TRUE );
pNew->SetExecuteURL( FALSE );
pEditEngine = pNew;
pEditEngine->SetUpdateMode( FALSE );
pEditEngine->SetWordDelimiters( pEditEngine->GetWordDelimiters() += '=' );
pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
2000-09-18 16:07:07 +00:00
SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
pEditEngine->SetFontInfoInItemSet( *pSet, aTextFont );
lcl_ExtendEditFontAttribs( *pSet );
if ( bIsRTL )
lcl_ModifyRTLDefaults( *pSet );
2000-09-18 16:07:07 +00:00
pEditEngine->SetDefaults( pSet );
pEditEngine->SetUpdateMode( TRUE );
pEditView = new EditView( pEditEngine, this );
pEditEngine->InsertView( pEditView, EE_APPEND );
Resize();
if ( bIsRTL )
lcl_ModifyRTLVisArea( pEditView );
if (pAccTextData)
pAccTextData->StartEdit();
2000-09-18 16:07:07 +00:00
}
void ScTextWnd::ImplInitSettings()
{
bIsRTL = GetSettings().GetLayoutRTL();
2000-09-18 16:07:07 +00:00
const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
Color aBgColor= rStyleSettings.GetWindowColor();
Color aTxtColor= rStyleSettings.GetWindowTextColor();
aTextFont.SetFillColor ( aBgColor );
aTextFont.SetColor (aTxtColor);
SetBackground ( aBgColor );
Invalidate();
}
2002-06-10 13:56:35 +00:00
::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ScTextWnd::CreateAccessible()
2002-06-10 13:56:35 +00:00
{
return new ScAccessibleEditObject(GetAccessibleParentWindow()->GetAccessible(), NULL, this,
rtl::OUString(String(ScResId(STR_ACC_EDITLINE_NAME))),
rtl::OUString(String(ScResId(STR_ACC_EDITLINE_DESCR))), EditLine);
2002-06-10 13:56:35 +00:00
}
2000-09-18 16:07:07 +00:00
// -----------------------------------------------------------------------
void ScTextWnd::DataChanged( const DataChangedEvent& rDCEvt )
{
if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
(rDCEvt.GetFlags() & SETTINGS_STYLE) )
{
ImplInitSettings();
Invalidate();
}
else
Window::DataChanged( rDCEvt );
}
//========================================================================
// Positionsfenster
//========================================================================
ScPosWnd::ScPosWnd( Window* pParent ) :
ComboBox ( pParent, WinBits(WB_HIDE | WB_DROPDOWN) ),
pAccel ( NULL ),
nTipVisible ( 0 ),
2000-09-18 16:07:07 +00:00
bFormulaMode( FALSE )
{
Size aSize( GetTextWidth( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("GW99999:GW99999")) ),
GetTextHeight() );
aSize.Width() += 25; // ??
aSize.Height() = CalcWindowSizePixel(11); // Funktionen: 10 MRU + "andere..."
SetSizePixel( aSize );
FillRangeNames();
StartListening( *SFX_APP() ); // fuer Navigator-Bereichsnamen-Updates
}
__EXPORT ScPosWnd::~ScPosWnd()
{
EndListening( *SFX_APP() );
HideTip();
2000-09-18 16:07:07 +00:00
delete pAccel;
}
void ScPosWnd::SetFormulaMode( BOOL bSet )
{
if ( bSet != bFormulaMode )
{
bFormulaMode = bSet;
if ( bSet )
FillFunctions();
else
FillRangeNames();
HideTip();
2000-09-18 16:07:07 +00:00
}
}
void ScPosWnd::SetPos( const String& rPosStr )
{
if ( aPosStr != rPosStr )
{
aPosStr = rPosStr;
SetText(aPosStr);
}
}
void ScPosWnd::FillRangeNames()
{
Clear();
SfxObjectShell* pObjSh = SfxObjectShell::Current();
if ( pObjSh && pObjSh->ISA(ScDocShell) )
{
ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument();
// per Hand sortieren, weil Funktionen nicht sortiert werden:
ScRangeName* pRangeNames = pDoc->GetRangeName();
USHORT nCount = pRangeNames->GetCount();
if ( nCount > 0 )
{
USHORT nValidCount = 0;
ScRange aDummy;
USHORT i;
for ( i=0; i<nCount; i++ )
{
ScRangeData* pData = (*pRangeNames)[i];
if (pData->IsReference(aDummy))
nValidCount++;
}
if ( nValidCount )
{
ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ];
USHORT j;
for ( i=0, j=0; i<nCount; i++ )
{
ScRangeData* pData = (*pRangeNames)[i];
if (pData->IsReference(aDummy))
ppSortArray[j++] = pData;
}
#ifndef ICC
qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
&ScRangeData::QsortNameCompare );
#else
qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
ICCQsortNameCompare );
#endif
for ( j=0; j<nValidCount; j++ )
InsertEntry( ppSortArray[j]->GetName() );
delete [] ppSortArray;
}
}
}
SetText(aPosStr);
}
void ScPosWnd::FillFunctions()
{
Clear();
String aFirstName;
const ScAppOptions& rOpt = SC_MOD()->GetAppOptions();
USHORT nMRUCount = rOpt.GetLRUFuncListCount();
const USHORT* pMRUList = rOpt.GetLRUFuncList();
if (pMRUList)
{
const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
ULONG nListCount = pFuncList->GetCount();
ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
for (USHORT i=0; i<nMRUCount; i++)
{
USHORT nId = pMRUList[i];
for (ULONG j=0; j<nListCount; j++)
{
const ScFuncDesc* pDesc = pFuncList->GetFunction( j );
if ( pDesc->nFIndex == nId && pDesc->pFuncName )
{
InsertEntry( *pDesc->pFuncName );
if (!aFirstName.Len())
aFirstName = *pDesc->pFuncName;
break; // nicht weitersuchen
}
}
}
}
//! Eintrag "Andere..." fuer Funktions-Autopilot wieder aufnehmen,
//! wenn der Funktions-Autopilot mit dem bisher eingegebenen Text arbeiten kann!
// InsertEntry( ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) );
SetText(aFirstName);
}
void __EXPORT ScPosWnd::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
const SfxHint& rHint, const TypeId& rHintType )
{
if ( !bFormulaMode )
{
// muss die Liste der Bereichsnamen updgedated werden?
if ( rHint.ISA(SfxSimpleHint) )
{
ULONG nHintId = ((SfxSimpleHint&)rHint).GetId();
if ( nHintId == SC_HINT_AREAS_CHANGED || nHintId == SC_HINT_NAVIGATOR_UPDATEALL)
FillRangeNames();
}
else if ( rHint.ISA(SfxEventHint) )
{
ULONG nEventId = ((SfxEventHint&)rHint).GetEventId();
if ( nEventId == SFX_EVENT_ACTIVATEDOC )
FillRangeNames();
}
}
}
void ScPosWnd::HideTip()
{
if ( nTipVisible )
{
Help::HideTip( nTipVisible );
nTipVisible = 0;
}
}
ScNameInputType lcl_GetInputType( const String& rText )
{
ScNameInputType eRet = SC_NAME_INPUT_BAD_NAME; // the more general error
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if ( pViewSh )
{
ScViewData* pViewData = pViewSh->GetViewData();
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
// test in same order as in SID_CURRENTCELL execute
ScRange aRange;
ScAddress aAddress;
ScRangeUtil aRangeUtil;
SCTAB nNameTab;
sal_Int32 nNumeric;
if ( aRange.Parse( rText, pDoc ) & SCA_VALID )
eRet = SC_NAME_INPUT_NAMEDRANGE;
else if ( aAddress.Parse( rText, pDoc ) & SCA_VALID )
eRet = SC_NAME_INPUT_CELL;
else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_NAMES ) )
eRet = SC_NAME_INPUT_NAMEDRANGE;
else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_DBASE ) )
eRet = SC_NAME_INPUT_DATABASE;
else if ( ByteString( rText, RTL_TEXTENCODING_ASCII_US ).IsNumericAscii() &&
( nNumeric = rText.ToInt32() ) > 0 && nNumeric <= MAXROW+1 )
eRet = SC_NAME_INPUT_ROW;
else if ( pDoc->GetTable( rText, nNameTab ) )
eRet = SC_NAME_INPUT_SHEET;
else if ( ScRangeData::IsNameValid( rText, pDoc ) ) // nothing found, create new range?
{
if ( pViewData->GetSimpleArea( aRange ) )
eRet = SC_NAME_INPUT_DEFINE;
else
eRet = SC_NAME_INPUT_BAD_SELECTION;
}
else
eRet = SC_NAME_INPUT_BAD_NAME;
}
return eRet;
}
void ScPosWnd::Modify()
{
ComboBox::Modify();
HideTip();
if ( !IsTravelSelect() && !bFormulaMode )
{
// determine the action that would be taken for the current input
ScNameInputType eType = lcl_GetInputType( GetText() ); // uses current view
USHORT nStrId = 0;
switch ( eType )
{
case SC_NAME_INPUT_CELL:
nStrId = STR_NAME_INPUT_CELL;
break;
case SC_NAME_INPUT_RANGE:
case SC_NAME_INPUT_NAMEDRANGE:
nStrId = STR_NAME_INPUT_RANGE; // named range or range reference
break;
case SC_NAME_INPUT_DATABASE:
nStrId = STR_NAME_INPUT_DBRANGE;
break;
case SC_NAME_INPUT_ROW:
nStrId = STR_NAME_INPUT_ROW;
break;
case SC_NAME_INPUT_SHEET:
nStrId = STR_NAME_INPUT_SHEET;
break;
case SC_NAME_INPUT_DEFINE:
nStrId = STR_NAME_INPUT_DEFINE;
break;
default:
// other cases (error): no tip help
break;
}
if ( nStrId )
{
// show the help tip at the text cursor position
Window* pWin = GetSubEdit();
if (!pWin)
pWin = this;
Point aPos;
Cursor* pCur = pWin->GetCursor();
if (pCur)
aPos = pWin->LogicToPixel( pCur->GetPos() );
aPos = pWin->OutputToScreenPixel( aPos );
Rectangle aRect( aPos, aPos );
String aText = ScGlobal::GetRscString( nStrId );
USHORT nAlign = QUICKHELP_LEFT|QUICKHELP_BOTTOM;
nTipVisible = Help::ShowTip(pWin, aRect, aText, nAlign);
}
}
}
2000-09-18 16:07:07 +00:00
void __EXPORT ScPosWnd::Select()
{
ComboBox::Select(); // in VCL gibt GetText() erst danach den ausgewaehlten Eintrag
HideTip();
2000-09-18 16:07:07 +00:00
if (!IsTravelSelect())
DoEnter();
}
void ScPosWnd::DoEnter()
{
String aText = GetText();
if ( aText.Len() )
{
if ( bFormulaMode )
{
ScModule* pScMod = SC_MOD();
if ( aText == ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) )
{
// Funktions-Autopilot
//! mit dem bisher eingegebenen Text weiterarbeiten !!!
//! new method at ScModule to query if function autopilot is open
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
2000-09-22 17:57:10 +00:00
pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
2000-09-18 16:07:07 +00:00
SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
}
else
{
ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
if (pHdl)
pHdl->InsertFunction( aText );
}
}
else
{
// depending on the input, select something or create a new named range
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if ( pViewSh )
{
ScNameInputType eType = lcl_GetInputType( aText );
if ( eType == SC_NAME_INPUT_BAD_NAME || eType == SC_NAME_INPUT_BAD_SELECTION )
{
USHORT nId = ( eType == SC_NAME_INPUT_BAD_NAME ) ? STR_NAME_ERROR_NAME : STR_NAME_ERROR_SELECTION;
pViewSh->ErrorMessage( nId );
}
else if ( eType == SC_NAME_INPUT_DEFINE )
{
ScViewData* pViewData = pViewSh->GetViewData();
ScDocShell* pDocShell = pViewData->GetDocShell();
ScDocument* pDoc = pDocShell->GetDocument();
ScRangeName* pNames = pDoc->GetRangeName();
ScRange aSelection;
USHORT nIndex = 0;
if ( pNames && !pNames->SearchName( aText, nIndex ) && pViewData->GetSimpleArea( aSelection ) )
{
ScRangeName aNewRanges( *pNames );
ScAddress aCursor( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
String aContent;
aSelection.Format( aContent, SCR_ABS_3D, pDoc );
ScRangeData* pNew = new ScRangeData( pDoc, aText, aContent, aCursor );
if ( aNewRanges.Insert(pNew) )
{
ScDocFunc aFunc(*pDocShell);
aFunc.ModifyRangeNames( aNewRanges, FALSE );
pViewSh->UpdateInputHandler(TRUE);
}
else
delete pNew; // shouldn't happen
}
}
else
{
// for all selection types, excecute the SID_CURRENTCELL slot
SfxStringItem aPosItem( SID_CURRENTCELL, aText );
SfxBoolItem aUnmarkItem( FN_PARAM_1, TRUE ); // remove existing selection
pViewSh->GetViewData()->GetDispatcher().Execute( SID_CURRENTCELL,
SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD,
&aPosItem, &aUnmarkItem, 0L );
}
}
2000-09-18 16:07:07 +00:00
}
}
else
SetText( aPosStr );
ReleaseFocus_Impl();
}
long __EXPORT ScPosWnd::Notify( NotifyEvent& rNEvt )
{
long nHandled = 0;
if ( rNEvt.GetType() == EVENT_KEYINPUT )
2000-09-18 16:07:07 +00:00
{
const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
switch ( pKEvt->GetKeyCode().GetCode() )
{
case KEY_RETURN:
DoEnter();
nHandled = 1;
break;
case KEY_ESCAPE:
if (nTipVisible)
{
// escape when the tip help is shown: only hide the tip
HideTip();
}
else
{
if (!bFormulaMode)
SetText( aPosStr );
ReleaseFocus_Impl();
}
2000-09-18 16:07:07 +00:00
nHandled = 1;
break;
}
}
if ( !nHandled )
nHandled = ComboBox::Notify( rNEvt );
if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
HideTip();
2000-09-18 16:07:07 +00:00
return nHandled;
}
void ScPosWnd::ReleaseFocus_Impl()
{
HideTip();
2000-09-18 16:07:07 +00:00
SfxViewShell* pCurSh = SfxViewShell::Current();
ScInputHandler* pHdl = SC_MOD()->GetInputHdl( PTR_CAST( ScTabViewShell, pCurSh ) );
if ( pHdl && pHdl->IsTopMode() )
{
// Focus wieder in die Eingabezeile?
ScInputWindow* pInputWin = pHdl->GetInputWindow();
if (pInputWin)
{
pInputWin->TextGrabFocus();
return;
}
}
// Focus auf die aktive View
if ( pCurSh )
{
Window* pShellWnd = pCurSh->GetWindow();
if ( pShellWnd )
pShellWnd->GrabFocus();
}
}