/**************************************************************
 * 
 * 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_svtools.hxx"

#include <svtools/fixedhyper.hxx>

//.........................................................................
namespace svt
{
//.........................................................................

// class FixedHyperlink --------------------------------------------------

FixedHyperlink::FixedHyperlink( Window* pParent, const ResId& rResId ) :
    ::toolkit::FixedHyperlinkBase( pParent, rResId ),
    m_nTextLen(0)
{
    Initialize();
}

FixedHyperlink::FixedHyperlink( Window* pParent, WinBits nWinStyle  ) :
    ::toolkit::FixedHyperlinkBase( pParent, nWinStyle ),
    m_nTextLen(0)
{
    Initialize();
}

FixedHyperlink::~FixedHyperlink()
{
}

void FixedHyperlink::Initialize()
{
    // saves the old pointer
    m_aOldPointer = GetPointer();
    // changes the font
    Font aFont = GetControlFont( );
    // to underline
    aFont.SetUnderline( UNDERLINE_SINGLE );
    SetControlFont( aFont );
    // changes the color to light blue
    SetTextColor( Color( COL_LIGHTBLUE ) );
    // calculates text len
    m_nTextLen = GetCtrlTextWidth( GetText() );
}

void FixedHyperlink::MouseMove( const MouseEvent& rMEvt )
{
    // changes the pointer if the control is enabled and the mouse is over the text.
    if ( !rMEvt.IsLeaveWindow() && IsEnabled() && GetPointerPosPixel().X() < m_nTextLen )
        SetPointer( POINTER_REFHAND );
    else
        SetPointer( m_aOldPointer );
}

void FixedHyperlink::MouseButtonUp( const MouseEvent& )
{
    // calls the link if the control is enabled and the mouse is over the text.
    if ( IsEnabled() && GetPointerPosPixel().X() < m_nTextLen )
        ImplCallEventListenersAndHandler( VCLEVENT_BUTTON_CLICK, m_aClickHdl, this );
}

void FixedHyperlink::RequestHelp( const HelpEvent& rHEvt )
{
    if ( IsEnabled() && GetPointerPosPixel().X() < m_nTextLen )
        FixedText::RequestHelp( rHEvt );
}

void FixedHyperlink::GetFocus()
{
    SetTextColor( Color( COL_LIGHTRED ) );
    Paint( Rectangle( Point(), GetSizePixel() ) );
    ShowFocus( Rectangle( Point( 1, 1 ), Size( m_nTextLen + 4, GetSizePixel().Height() - 2 ) ) );
}

void FixedHyperlink::LoseFocus()
{
    SetTextColor( Color( COL_LIGHTBLUE ) );
    Paint( Rectangle( Point(), GetSizePixel() ) );
    HideFocus();
}

void FixedHyperlink::KeyInput( const KeyEvent& rKEvt )
{
    switch ( rKEvt.GetKeyCode().GetCode() )
    {
        case KEY_SPACE:
        case KEY_RETURN:
            m_aClickHdl.Call( this );
            break;

        default:
            FixedText::KeyInput( rKEvt );
    }
}

void FixedHyperlink::SetURL( const String& rNewURL )
{
    m_sURL = rNewURL;
    SetQuickHelpText( m_sURL );
}

String  FixedHyperlink::GetURL() const
{
    return m_sURL;
}

void FixedHyperlink::SetDescription( const String& rNewDescription )
{
    SetText( rNewDescription );
    m_nTextLen = GetCtrlTextWidth( GetText() );
}

// class FixedHyperlinkImage ---------------------------------------------

FixedHyperlinkImage::FixedHyperlinkImage( Window* pParent, const ResId& rResId ) :
    FixedImage( pParent, rResId )
{
    Initialize();
}

FixedHyperlinkImage::FixedHyperlinkImage( Window* pParent, WinBits nWinStyle  ) :
    FixedImage( pParent, nWinStyle )
{
    Initialize();
}

FixedHyperlinkImage::~FixedHyperlinkImage()
{
}

void FixedHyperlinkImage::Initialize()
{
    // saves the old pointer
    m_aOldPointer = GetPointer();
}

void FixedHyperlinkImage::MouseMove( const MouseEvent& rMEvt )
{
    // changes the pointer if the control is enabled and the mouse is over the text.
    if ( !rMEvt.IsLeaveWindow() && IsEnabled() )
        SetPointer( POINTER_REFHAND );
    else
        SetPointer( m_aOldPointer );
}

void FixedHyperlinkImage::MouseButtonUp( const MouseEvent& )
{
    // calls the link if the control is enabled and the mouse is over the text.
    if ( IsEnabled() )
        ImplCallEventListenersAndHandler( VCLEVENT_BUTTON_CLICK, m_aClickHdl, this );

    Size aSize = GetSizePixel();
    Size aImgSz = GetImage().GetSizePixel();
    if ( aSize.Width() < aImgSz.Width() )
    {
        DBG_ERRORFILE("xxx");
    }
}

void FixedHyperlinkImage::RequestHelp( const HelpEvent& rHEvt )
{
    if ( IsEnabled() )
        FixedImage::RequestHelp( rHEvt );
}

void FixedHyperlinkImage::GetFocus()
{
    Paint( Rectangle( Point(), GetSizePixel() ) );
    ShowFocus( Rectangle( Point( 1, 1 ), Size( GetSizePixel().Width() - 2, GetSizePixel().Height() - 2 ) ) );
}

void FixedHyperlinkImage::LoseFocus()
{
    Paint( Rectangle( Point(), GetSizePixel() ) );
    HideFocus();
}

void FixedHyperlinkImage::KeyInput( const KeyEvent& rKEvt )
{
    switch ( rKEvt.GetKeyCode().GetCode() )
    {
        case KEY_SPACE:
        case KEY_RETURN:
            m_aClickHdl.Call( this );
            break;

        default:
            FixedImage::KeyInput( rKEvt );
    }
}

void FixedHyperlinkImage::SetURL( const String& rNewURL )
{
    m_sURL = rNewURL;
    SetQuickHelpText( m_sURL );
}

String  FixedHyperlinkImage::GetURL() const
{
    return m_sURL;
}

//.........................................................................
} // namespace svt
//.........................................................................

