/*
* Copyright (c) 2005-2005 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0""
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Implementation for insertion point
*
*/
#include "peninputlayoutcursor.h"
#include "peninputlayouteditareabase.h"
#include "peninputlayouttimer.h"
#include "peninputlayoutrootctrl.h"
#include "peninputcmd.h"
#include "peninputlayout.h"
const TInt KDefaultCursorHeight = 10;
// ============================ MEMBER FUNCTIONS =============================
// ---------------------------------------------------------------------------
// CFepUiCursor::CFepUiCursor
// C++ default constructor can NOT contain any code, that might leave
// ---------------------------------------------------------------------------
//
CFepUiCursor::CFepUiCursor(const TRect& aRect,CFepUiLayout* aUiLayout,TInt aId)
:CFepUiBaseCtrl(aRect,aUiLayout,aId),
iPosition(0, 0),
iHeight(KDefaultCursorHeight),
iIsOn(EFalse),
iIsVisible(EFalse),
//iEditor(aOwner),
//iBitmapDevice(aBitmapDevice),
//iGc(aGc),
iCursorTempDisabled(EFalse)
{
SetControlType(ECtrlCursor);
}
// ---------------------------------------------------------------------------
// CFepUiCursor::ConstructL
// Symbian 2nd phase constructor can leave.
// ---------------------------------------------------------------------------
//
void CFepUiCursor::ConstructL()
{
CFepUiBaseCtrl::BaseConstructL();
iCursorBlinkingTimer = CPeriodic::NewL(CActive::EPriorityStandard);
iRestoreCursorTimer = CLayoutTimer::NewL(this,CLayoutTimer::EOthers);
CreateCursorBmpL();
}
// ---------------------------------------------------------------------------
// CFepUiCursor::NewL
// Two-phased constructor.
// ---------------------------------------------------------------------------
//
CFepUiCursor* CFepUiCursor::NewL(const TRect& aRect,CFepUiLayout* aUiLayout,TInt aId)
{
CFepUiCursor* self = new(ELeave) CFepUiCursor(aRect, aUiLayout,aId);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self); // insertionPoint
return self;
}
// ---------------------------------------------------------------------------
// CFepUiCursor::~CFepUiCursor
// Destructor
// ---------------------------------------------------------------------------
//
CFepUiCursor::~CFepUiCursor()
{
if(iCursorBlinkingTimer)
{
iCursorBlinkingTimer->Cancel();
delete iCursorBlinkingTimer;
}
delete iRestoreCursorTimer;
delete iBitmap;
delete iBitmapDevice;
delete iGc;
}
// ---------------------------------------------------------------------------
// CFepUiCursor::SetPosition
// Sets the position of the sprite if it has been turned on
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
EXPORT_C void CFepUiCursor::SetPosition(const TPoint& aPosition)
{
if( iPosition != aPosition )
{
TBool isOn = iIsOn;
if (isOn)
{
SetOn(EFalse);
}
iPosition=aPosition;
TPoint correction(KCursorPosCorrectionX,KCursorPosCorrectionY );
TRect rect = TRect(iPosition + correction , TSize(KCursorWidth,iHeight));
if(rect != iCursorRect)
{
SetRect(rect);
iCursorRect = rect;
//must update clip region again.
for(TInt i = 0 ; i < RootControl()->PopCtrlList().Count(); ++i)
{
UpdateValidRegion(RootControl()->PopCtrlList()[i],EFalse);
}
}
if (isOn)
{
SetOn(ETrue);
}
}
}
// ---------------------------------------------------------------------------
// CFepUiCursor::Position
// get the cursor position
// ---------------------------------------------------------------------------
//
EXPORT_C TPoint CFepUiCursor::Position()
{
return iPosition;
}
// ---------------------------------------------------------------------------
// CFepUiCursor::SetLayoutOwner
// Sets the layout owner
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
/*void CFepUiCursor::SetLayoutOwner(MLayoutOwner* aOwner)
{
iLayoutOwner = aOwner;
}
*/
// ---------------------------------------------------------------------------
// CFepUiCursor::SetOn
// Turns the sprite on and off
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
EXPORT_C void CFepUiCursor::SetOn(TBool aOn, TBool aImmediately)
{
//aOn = EFalse;
iIsOn = aOn;
// If cursor will bee set off and timer is active, Cancel timer
if ( !iIsOn )
{
CancelDelayCursorShown();
if ( iCursorBlinkingTimer->IsActive())
{
iCursorBlinkingTimer->Cancel();
}
InvalidateInsertionPoint();
}
else
{
if(iCursorTempDisabled)
{
return;
}
// Activate blinking timer, if it is not already activated
if ( !iCursorBlinkingTimer->IsActive() )
{
iCursorBlinkingTimer->Start(aImmediately ? 0: KCursorBlinkPerioid,
KCursorBlinkPerioid,TCallBack(CursorBlinkCallBack , this));
}
}
// Invalidate InsertionPoint's rect, so it will be removed from editarea
//InvalidateInsertionPoint();
}
// ---------------------------------------------------------------------------
// CFepUiCursor::SetHeight
// Sets caret height
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
EXPORT_C void CFepUiCursor::SetHeight(TInt aHeight)
{
if(aHeight > 0 && aHeight != iHeight )
{
TBool isOn = iIsOn;
if (isOn)
{
SetOn(EFalse);
}
iHeight = aHeight;
//change the cursor rect
TPoint correction(KCursorPosCorrectionX,KCursorPosCorrectionY );
iCursorRect = TRect(iPosition + correction ,
TSize(KCursorWidth,iHeight));
if (isOn)
{
SetOn(ETrue);
}
}
}
EXPORT_C void CFepUiCursor::ReDraw(TBool aReset)
{
if(aReset)
iIsVisible = EFalse;
Draw();
//UpdateArea(iCursorRect,EFalse);
UpdateCursorArea(iCursorRect,EFalse);
}
void CFepUiCursor::DrawCursor(CFbsBitGc* aGc,CFbsBitmapDevice* aDevice)
{
aGc->Activate(aDevice);
// draw cursor by inverting colors in the selected text rectancle
//aGc->SetClippingRegion(ValidClipRegion());
aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
aGc->SetBrushColor(KRgbBlack);
//aGc->SetDrawMode(CGraphicsContext::EDrawModeNOTSCREEN);
aGc->Clear();
aGc->SetPenColor(KRgbBlack);
aGc->SetPenStyle(CGraphicsContext::ESolidPen);
aGc->SetPenSize( TSize(1,1));
// When the blink timer out and cursor is visible, do nothing
// else draw the cursor and set the visible flag
//aGc->DrawRect(iCursorRect);
//iIsVisible = !iIsVisible;
// restore normal draw mode
aGc->SetDrawMode(CGraphicsContext::EDrawModePEN);
aGc->SetBrushStyle(CGraphicsContext::ENullBrush);
}
// ---------------------------------------------------------------------------
// CFepUiCursor::Draw
// Draws insertion point's Rect and starts blinking timer
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
void CFepUiCursor::Draw()//CBitmapContext* aGc, TBool aReset)
{
if(!AbleToDraw())
{
return;
}
//#ifdef FIX_FOR_NGA
if(UiLayout()->NotDrawToLayoutDevice())
{
if(iIsOn)
{
iIsVisible = !iIsVisible;
}
else
{
if(iIsVisible) //only do when already shown
{
iIsVisible = EFalse;
}
}
return;
}
//#endif
/*if (aReset)
{
iIsVisible = EFalse;
}
*/
CFbsBitGc* gc = static_cast<CFbsBitGc*>(BitGc());
gc->Activate( BitmapDevice());
if(iIsOn)
{
// draw cursor by inverting colors in the selected text rectancle
gc->SetClippingRegion(ValidClipRegion());
const TRegion& tr = ValidClipRegion();
const TRect* rl = tr.RectangleList();
TRect rr;
for(TInt id = 0; id < tr.Count(); ++id)
{
rr = rl[id];
}
gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
gc->SetBrushColor(KRgbBlack);
gc->SetDrawMode(CGraphicsContext::EDrawModeNOTSCREEN);
gc->SetPenColor(KRgbBlack);
gc->SetPenStyle(CGraphicsContext::ESolidPen);
gc->SetPenSize( TSize(1,1));
// When the blink timer out and cursor is visible, do nothing
// else draw the cursor and set the visible flag
gc->DrawRect(iCursorRect);
iIsVisible = !iIsVisible;
// restore normal draw mode
gc->SetDrawMode(CGraphicsContext::EDrawModePEN);
gc->SetBrushStyle(CGraphicsContext::ENullBrush);
//if (iEditor)
{
// iEditor->UpdateArea(iCursorRect,EFalse);
}
// UpdateArea(iCursorRect,EFalse);
}
else
{
if(iIsVisible) //only do when already shown
{
//CFbsBitmapDevice* bitmapDevice = iEditor->BitmapDevice();
//static_cast<CFbsBitGc*>(gc)->Activate(iBitmapDevice);
gc->SetClippingRegion(ValidClipRegion());
gc->SetPenColor(KRgbBlack);
gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
gc->SetBrushColor(KRgbBlack);
gc->SetDrawMode(CGraphicsContext::EDrawModeNOTSCREEN);
gc->SetPenStyle(CGraphicsContext::ESolidPen);
gc->SetPenSize( TSize(1,1));
gc->DrawRect(iCursorRect);
// restore normal draw mode
gc->SetDrawMode(CGraphicsContext::EDrawModePEN);
gc->SetBrushStyle(CGraphicsContext::ENullBrush);
iIsVisible = EFalse;
/*if (iEditor)
{
iEditor->UpdateArea(iCursorRect,EFalse);
}*/
// UpdateArea(iCursorRect,EFalse);
}
}
gc->CancelClippingRegion();
}
// ---------------------------------------------------------------------------
// CFepUiCursor::CursorBlinkCallBack
// Invalidates cursor rect, when timer gets out.
// With periodic caused draw/undraw of cursor will cause cursor blinking
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TInt CFepUiCursor::CursorBlinkCallBack(TAny *aPtr)
{
CFepUiCursor* self = static_cast<CFepUiCursor*>(aPtr);
self->InvalidateInsertionPoint();
return(ETrue);
}
// ---------------------------------------------------------------------------
// CFepUiCursor::InvalidateCursor
// Invalidates InsertionPoint's rect
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
void CFepUiCursor::InvalidateInsertionPoint()
{
if(AbleToDraw())
{
Draw();
//UpdateArea(iCursorRect,EFalse);
UpdateCursorArea(iCursorRect,EFalse);
}
}
// ---------------------------------------------------------------------------
// CFepUiCursor::DelayCursorWhileDraging
// Disable the cursor while pen is draging
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
EXPORT_C void CFepUiCursor::DelayCursorWhileDraging()
{
DelayCursorShown();
}
// ---------------------------------------------------------------------------
// CFepUiCursor::DelayCursorShown
// Disable the cursor while pen is draging
// (other items were commented in a header).
// ---------------------------------------------------------------------------
EXPORT_C void CFepUiCursor::DelayCursorShown()
{
if(!iIsOn && !iCursorTempDisabled) // do nothing is cursor is off
return;
if(!iCursorTempDisabled)
{
SetOn(EFalse); // disable the cursor
iCursorTempDisabled = ETrue;
}
iRestoreCursorTimer->SetTimer(KCursorBlinkPerioid);
}
// ---------------------------------------------------------------------------
// cancel delay shown process
// ---------------------------------------------------------------------------
//
void CFepUiCursor::CancelDelayCursorShown()
{
iRestoreCursorTimer->Cancel();
iCursorTempDisabled = EFalse;
}
// ---------------------------------------------------------------------------
// CFepUiCursor::HandleTimerOut
// Set the cursor on
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
void CFepUiCursor::HandleTimerOut(TInt /*aTimeType*/)
{
iCursorTempDisabled = EFalse;
iIsOn = ETrue;
//To avoid the ugly first shown, we draw the cursor directly here.
//InvalidateInsertionPoint();
SetOn(ETrue, EFalse);
}
// ---------------------------------------------------------------------------
// CFepUiCursor::UpdateValidRegion
// Update control's valid region when other control show or hide.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
EXPORT_C void CFepUiCursor::UpdateValidRegion(CFepUiBaseCtrl* aCtrl,TBool aRemoveFlag)
{
if(!iUpdateFlagEnabled)
return;
if(aRemoveFlag)
{
}
else
{
if(aCtrl->Hiden())
return;
TRect rect = Rect();
rect.Intersection(aCtrl->Rect());
iValidRegion.SubRect(rect);
iClipRegion.SubRect(rect);
}
//iValidRegion.AddRect(iRect);
return;
}
TInt CFepUiCursor::OrderPos()
{
TInt ret = 0;
TRAP_IGNORE(ret = OrderPosL());
return ret;
}
TInt CFepUiCursor::OrderPosL()
{
__ASSERT_DEBUG(iEditor,User::Leave(EUiCursorNoOwner));
return iEditor->OrderPos();
}
void CFepUiCursor::ResetValidClipRegion()
{
iValidRegion.Clear();
iClipRegion.Clear();
iValidRegion.AddRect(iRect);
iClipRegion.AddRect(iRect);
}
void CFepUiCursor::UpdateCursorArea(const TRect& aRect, TBool aFlag)
{
if(UiLayout()->NotDrawToLayoutDevice())
{
//CopyToBmp();
//signal special update
struct SData
{
TBool onOff;
CFbsBitmap* bmp;
TRect rect;
} data;
data.onOff = iIsVisible;
data.bmp = iBitmap;
data.rect = iCursorRect;
TPtrC ptr;
ptr.Set(reinterpret_cast<const TUint16*>(&data),sizeof(data)/sizeof(TUint16));
UiLayout()->SignalOwner(ESignalUpdateCursor,ptr);
return;
}
CFepUiBaseCtrl* parent = iEditor->ParentCtrl();
if(parent)
{
if(parent->IsKindOfControl(ECtrlControlGroup))
static_cast<CControlGroup*>(parent)->UpdateAreaInGrp(iEditor,aRect,aFlag);
else
iEditor->ParentCtrl()->UpdateArea(aRect,aFlag);
}
else
UpdateArea(aRect,aFlag);
}
void CFepUiCursor::CreateCursorBmpL()
{
iBitmap = new ( ELeave ) CFbsBitmap;
TRect rect = TRect(TPoint(0,0) , TSize(KCursorWidth,iHeight));
User::LeaveIfError( iBitmap->Create( rect.Size(), BitmapDevice()->DisplayMode() ) );
iBitmapDevice = CFbsBitmapDevice::NewL(iBitmap);
iGc = CFbsBitGc::NewL();
iGc->Reset();
DrawCursor(iGc,iBitmapDevice);
}
void CFepUiCursor::ResizeCursorBmp()
{
TRect rect = TRect(TPoint(0,0) , TSize(KCursorWidth,iHeight));
iBitmap->Resize(rect.Size());
iBitmapDevice->Resize( rect.Size());
//gc must be adjusted
iGc->Activate(iBitmapDevice);
iGc->Resized();
DrawCursor(iGc,iBitmapDevice);
}
// End of File