blob: 162a4a5299f73330b8442e4db44a733f41a77b26 [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_cui.hxx"
#include "hangulhanjadlg.hxx"
#include "hangulhanjadlg.hrc"
#include "commonlingui.hxx"
#include <dialmgr.hxx>
#include <cuires.hrc>
#include "helpid.hrc"
#include <algorithm>
#include <tools/urlobj.hxx>
#include <vcl/controllayout.hxx>
#include <vcl/msgbox.hxx>
#include <unotools/lingucfg.hxx>
#include <unotools/linguprops.hxx>
#include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
#include <com/sun/star/linguistic2/ConversionDirection.hdl>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/i18n/TextConversionOption.hdl>
#include <com/sun/star/util/XFlushable.hpp>
#include <comphelper/processfactory.hxx>
#define HHC editeng::HangulHanjaConversion
#define LINE_CNT static_cast< sal_uInt16 >(2)
//.............................................................................
namespace svx
{
//.............................................................................
/*
using HangulHanjaConversion::eSimpleConversion;
using HangulHanjaConversion::eHangulBracketed;
using HangulHanjaConversion::eHanjaBracketed;
using HangulHanjaConversion::eRubyHanjaAbove;
using HangulHanjaConversion::eRubyHanjaBelow;
using HangulHanjaConversion::eRubyHangulAbove;
using HangulHanjaConversion::eRubyHangulBelow;
*/
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::linguistic2;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;
using ::rtl::OUString;
//-------------------------------------------------------------------------
namespace
{
class FontSwitch
{
private:
OutputDevice& m_rDev;
public:
inline FontSwitch( OutputDevice& _rDev, const Font& _rTemporaryFont )
:m_rDev( _rDev )
{
m_rDev.Push( PUSH_FONT );
m_rDev.SetFont( _rTemporaryFont );
}
inline ~FontSwitch( )
{
m_rDev.Pop( );
}
};
}
//=========================================================================
//= PseudoRubyText
//=========================================================================
/** a class which allows to draw two texts in a pseudo-ruby way (which basically
means one text above or below the other, and a little bit smaller)
*/
class PseudoRubyText
{
public:
enum RubyPosition
{
eAbove, eBelow
};
protected:
const String m_sPrimaryText;
const String m_sSecondaryText;
const RubyPosition m_ePosition;
public:
PseudoRubyText( const String& _rPrimary, const String& _rSecondary, const RubyPosition _ePosition );
public:
void Paint( OutputDevice& _rDevice, const Rectangle& _rRect, sal_uInt16 _nTextStyle,
Rectangle* _pPrimaryLocation = NULL, Rectangle* _pSecondaryLocation = NULL,
::vcl::ControlLayoutData* _pLayoutData = NULL );
};
//-------------------------------------------------------------------------
PseudoRubyText::PseudoRubyText( const String& _rPrimary, const String& _rSecondary, const RubyPosition _ePosition )
:m_sPrimaryText( _rPrimary )
,m_sSecondaryText( _rSecondary )
,m_ePosition( _ePosition )
{
}
//-------------------------------------------------------------------------
void PseudoRubyText::Paint( OutputDevice& _rDevice, const Rectangle& _rRect, sal_uInt16 _nTextStyle,
Rectangle* _pPrimaryLocation, Rectangle* _pSecondaryLocation, ::vcl::ControlLayoutData* _pLayoutData )
{
bool bLayoutOnly = NULL != _pLayoutData;
MetricVector* pTextMetrics = bLayoutOnly ? &_pLayoutData->m_aUnicodeBoundRects : NULL;
String* pDisplayText = bLayoutOnly ? &_pLayoutData->m_aDisplayText : NULL;
Size aPlaygroundSize( _rRect.GetSize() );
// the font for the secondary text:
Font aSmallerFont( _rDevice.GetFont() );
// heuristic: 80% of the original size
aSmallerFont.SetHeight( (long)( 0.8 * aSmallerFont.GetHeight() ) );
// let's calculate the size of our two texts
Rectangle aPrimaryRect = _rDevice.GetTextRect( _rRect, m_sPrimaryText, _nTextStyle );
Rectangle aSecondaryRect;
{
FontSwitch aFontRestore( _rDevice, aSmallerFont );
aSecondaryRect = _rDevice.GetTextRect( _rRect, m_sSecondaryText, _nTextStyle );
}
// position these rectangles properly
// x-axis:
sal_Int32 nCombinedWidth = ::std::max( aSecondaryRect.GetWidth(), aPrimaryRect.GetWidth() );
// the rectangle where both texts will reside is as high as possible, and as wide as the
// widest of both text rects
aPrimaryRect.Left() = aSecondaryRect.Left() = _rRect.Left();
aPrimaryRect.Right() = aSecondaryRect.Right() = _rRect.Left() + nCombinedWidth;
if ( TEXT_DRAW_RIGHT & _nTextStyle )
{
// move the rectangles to the right
aPrimaryRect.Move( aPlaygroundSize.Width() - nCombinedWidth, 0 );
aSecondaryRect.Move( aPlaygroundSize.Width() - nCombinedWidth, 0 );
}
else if ( TEXT_DRAW_CENTER & _nTextStyle )
{
// center the rectangles
aPrimaryRect.Move( ( aPlaygroundSize.Width() - nCombinedWidth ) / 2, 0 );
aSecondaryRect.Move( ( aPlaygroundSize.Width() - nCombinedWidth ) / 2, 0 );
}
// y-axis:
sal_Int32 nCombinedHeight = aPrimaryRect.GetHeight() + aSecondaryRect.GetHeight();
// align to the top, for the moment
aPrimaryRect.Move( 0, _rRect.Top() - aPrimaryRect.Top() );
aSecondaryRect.Move( 0, aPrimaryRect.Top() + aPrimaryRect.GetHeight() - aSecondaryRect.Top() );
if ( TEXT_DRAW_BOTTOM & _nTextStyle )
{
// move the rects to the bottom
aPrimaryRect.Move( 0, aPlaygroundSize.Height() - nCombinedHeight );
aSecondaryRect.Move( 0, aPlaygroundSize.Height() - nCombinedHeight );
}
else if ( TEXT_DRAW_VCENTER & _nTextStyle )
{
// move the rects to the bottom
aPrimaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 );
aSecondaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 );
}
// 'til here, everything we did assumes that the secondary text is painted _below_ the primary
// text. If this isn't the case, we need to correct the rectangles
if ( eAbove == m_ePosition )
{
sal_Int32 nVertDistance = aSecondaryRect.Top() - aPrimaryRect.Top();
aSecondaryRect.Move( 0, -nVertDistance );
aPrimaryRect.Move( 0, nCombinedHeight - nVertDistance );
}
// now draw the texts
// as we already calculated the precise rectangles for the texts, we don't want to
// use the alignment flags given - within it's rect, every text is centered
sal_uInt16 nDrawTextStyle( _nTextStyle );
nDrawTextStyle &= ~( TEXT_DRAW_RIGHT | TEXT_DRAW_LEFT | TEXT_DRAW_BOTTOM | TEXT_DRAW_TOP );
nDrawTextStyle |= TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER;
_rDevice.DrawText( aPrimaryRect, m_sPrimaryText, nDrawTextStyle, pTextMetrics, pDisplayText );
{
FontSwitch aFontRestore( _rDevice, aSmallerFont );
_rDevice.DrawText( aSecondaryRect, m_sSecondaryText, nDrawTextStyle, pTextMetrics, pDisplayText );
}
// outta here
if ( _pPrimaryLocation )
*_pPrimaryLocation = aPrimaryRect;
if ( _pSecondaryLocation )
*_pSecondaryLocation = aSecondaryRect;
}
//=========================================================================
//= RubyRadioButton
//=========================================================================
class RubyRadioButton :public RadioButton
,protected PseudoRubyText
{
using svx::PseudoRubyText::Paint;
public:
RubyRadioButton(
Window* _pParent,
const ResId& _rId, // the text in the resource will be taken as primary text
const String& _rSecondary, // this will be the secondary text which will be printed somewhat smaller
const PseudoRubyText::RubyPosition _ePosition );
protected:
virtual void Paint( const Rectangle& _rRect );
};
//-------------------------------------------------------------------------
RubyRadioButton::RubyRadioButton( Window* _pParent, const ResId& _rId,
const String& _rSecondary, const PseudoRubyText::RubyPosition _ePosition )
:RadioButton( _pParent, _rId )
,PseudoRubyText( RadioButton::GetText(), _rSecondary, _ePosition )
{
}
//-------------------------------------------------------------------------
void RubyRadioButton::Paint( const Rectangle& )
{
HideFocus();
// calculate the size of the radio image - we're to paint our text _after_ this image
DBG_ASSERT( !GetModeRadioImage(), "RubyRadioButton::Paint: images not supported!" );
Size aImageSize = GetRadioImage( GetSettings(), 0 ).GetSizePixel();
aImageSize.Width() = CalcZoom( aImageSize.Width() );
aImageSize.Height() = CalcZoom( aImageSize.Height() );
Rectangle aOverallRect( Point( 0, 0 ), GetOutputSizePixel() );
aOverallRect.Left() += aImageSize.Width() + 4; // 4 is the separator between the image and the text
// inflate the rect a little bit (because the VCL radio button does the same)
Rectangle aTextRect( aOverallRect );
++aTextRect.Left(); --aTextRect.Right();
++aTextRect.Top(); --aTextRect.Bottom();
// calculate the text flags for the painting
sal_uInt16 nTextStyle = TEXT_DRAW_MNEMONIC;
WinBits nStyle = GetStyle( );
// the horizontal alignment
if ( nStyle & WB_RIGHT )
nTextStyle |= TEXT_DRAW_RIGHT;
else if ( nStyle & WB_CENTER )
nTextStyle |= TEXT_DRAW_CENTER;
else
nTextStyle |= TEXT_DRAW_LEFT;
// the vertical alignment
if ( nStyle & WB_BOTTOM )
nTextStyle |= TEXT_DRAW_BOTTOM;
else if ( nStyle & WB_VCENTER )
nTextStyle |= TEXT_DRAW_VCENTER;
else
nTextStyle |= TEXT_DRAW_TOP;
// mnemonics
if ( 0 == ( nStyle & WB_NOLABEL ) )
nTextStyle |= TEXT_DRAW_MNEMONIC;
// paint the ruby text
Rectangle aPrimaryTextLocation, aSecondaryTextLocation;
PseudoRubyText::Paint( *this, aTextRect, nTextStyle, &aPrimaryTextLocation, &aSecondaryTextLocation );
// the focus rectangle is to be painted around both texts
Rectangle aCombinedRect( aPrimaryTextLocation );
aCombinedRect.Union( aSecondaryTextLocation );
SetFocusRect( aCombinedRect );
// let the base class paint the radio button
// for this, give it the proper location to paint the image (vertically centered, relative to our text)
Rectangle aImageLocation( Point( 0, 0 ), aImageSize );
sal_Int32 nTextHeight = aSecondaryTextLocation.Bottom() - aPrimaryTextLocation.Top();
aImageLocation.Top() = aPrimaryTextLocation.Top() + ( nTextHeight - aImageSize.Height() ) / 2;
aImageLocation.Bottom() = aImageLocation.Top() + aImageSize.Height();
SetStateRect( aImageLocation );
DrawRadioButtonState( );
// mouse clicks should be recognized in a rect which is one pixel larger in each direction, plus
// includes the image
aCombinedRect.Left() = aImageLocation.Left(); ++aCombinedRect.Right();
--aCombinedRect.Top(); ++aCombinedRect.Bottom();
SetMouseRect( aCombinedRect );
// paint the focus rect, if necessary
if ( HasFocus() )
ShowFocus( aTextRect );
}
//=========================================================================
//= SuggestionSet
//=========================================================================
//-------------------------------------------------------------------------
SuggestionSet::SuggestionSet( Window* pParent )
: ValueSet( pParent, pParent->GetStyle() | WB_BORDER )
{
}
SuggestionSet::~SuggestionSet()
{
ClearSet();
}
void SuggestionSet::UserDraw( const UserDrawEvent& rUDEvt )
{
OutputDevice* pDev = rUDEvt.GetDevice();
Rectangle aRect = rUDEvt.GetRect();
sal_uInt16 nItemId = rUDEvt.GetItemId();
String sText = *static_cast< String* >( GetItemData( nItemId ) );
pDev->DrawText( aRect, sText, TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER );
}
void SuggestionSet::ClearSet()
{
sal_uInt16 i, nCount = GetItemCount();
for ( i = 0; i < nCount; ++i )
delete static_cast< String* >( GetItemData(i) );
Clear();
}
//=========================================================================
//= SuggestionDisplay
//=========================================================================
//-------------------------------------------------------------------------
SuggestionDisplay::SuggestionDisplay( Window* pParent, const ResId& rResId )
: Control( pParent, rResId )
, m_bDisplayListBox(true)
, m_aValueSet(this)
, m_aListBox(this,GetStyle() | WB_BORDER )
, m_bInSelectionUpdate(false)
{
m_aValueSet.SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionHdl ) );
m_aListBox.SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionHdl ) );
m_aValueSet.SetLineCount( LINE_CNT );
m_aValueSet.SetStyle( m_aValueSet.GetStyle() | WB_ITEMBORDER | WB_FLATVALUESET | WB_VSCROLL );
m_aValueSet.SetBorderStyle( WINDOW_BORDER_MONO );
String aOneCharacter(RTL_CONSTASCII_STRINGPARAM("AU"));
long nItemWidth = 2*GetTextWidth( aOneCharacter );
m_aValueSet.SetItemWidth( nItemWidth );
Point aPos(0,0);
Size aSize(GetSizePixel());
m_aValueSet.SetSizePixel(aSize);
m_aListBox.SetSizePixel(aSize);
implUpdateDisplay();
}
SuggestionDisplay::~SuggestionDisplay()
{
}
void SuggestionDisplay::implUpdateDisplay()
{
bool bShowBox = IsVisible() && m_bDisplayListBox;
bool bShowSet = IsVisible() && !m_bDisplayListBox;
m_aListBox.Show(bShowBox);
m_aValueSet.Show(bShowSet);
}
void SuggestionDisplay::StateChanged( StateChangedType nStateChange )
{
if( STATE_CHANGE_VISIBLE == nStateChange )
implUpdateDisplay();
}
Control& SuggestionDisplay::implGetCurrentControl()
{
if( m_bDisplayListBox )
return m_aListBox;
return m_aValueSet;
}
void SuggestionDisplay::KeyInput( const KeyEvent& rKEvt )
{
implGetCurrentControl().KeyInput( rKEvt );
}
void SuggestionDisplay::KeyUp( const KeyEvent& rKEvt )
{
implGetCurrentControl().KeyUp( rKEvt );
}
void SuggestionDisplay::Activate()
{
implGetCurrentControl().Activate();
}
void SuggestionDisplay::Deactivate()
{
implGetCurrentControl().Deactivate();
}
void SuggestionDisplay::GetFocus()
{
implGetCurrentControl().GetFocus();
}
void SuggestionDisplay::LoseFocus()
{
implGetCurrentControl().LoseFocus();
}
void SuggestionDisplay::Command( const CommandEvent& rCEvt )
{
implGetCurrentControl().Command( rCEvt );
}
void SuggestionDisplay::DisplayListBox( bool bDisplayListBox )
{
if( m_bDisplayListBox != bDisplayListBox )
{
Control& rOldControl = implGetCurrentControl();
sal_Bool bHasFocus = rOldControl.HasFocus();
m_bDisplayListBox = bDisplayListBox;
if( bHasFocus )
{
Control& rNewControl = implGetCurrentControl();
rNewControl.GrabFocus();
}
implUpdateDisplay();
}
}
IMPL_LINK( SuggestionDisplay, SelectSuggestionHdl, Control*, pControl )
{
if( m_bInSelectionUpdate )
return 0L;
m_bInSelectionUpdate = true;
if(pControl==&m_aListBox)
{
sal_uInt16 nPos = m_aListBox.GetSelectEntryPos();
m_aValueSet.SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
}
else
{
sal_uInt16 nPos = m_aValueSet.GetSelectItemId()-1; //itemid == pos+1 (id 0 has special meaning)
m_aListBox.SelectEntryPos( nPos );
}
m_bInSelectionUpdate = false;
m_aSelectLink.Call(this);
return 0L;
}
void SuggestionDisplay::SetSelectHdl( const Link& rLink )
{
m_aSelectLink = rLink;
}
void SuggestionDisplay::Clear()
{
m_aListBox.Clear();
m_aValueSet.Clear();
}
void SuggestionDisplay::InsertEntry( const XubString& rStr )
{
sal_uInt16 nItemId = m_aListBox.InsertEntry( rStr ) + 1; //itemid == pos+1 (id 0 has special meaning)
m_aValueSet.InsertItem( nItemId );
String* pItemData = new String(rStr);
m_aValueSet.SetItemData( nItemId, pItemData );
}
void SuggestionDisplay::SelectEntryPos( sal_uInt16 nPos )
{
m_aListBox.SelectEntryPos( nPos );
m_aValueSet.SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
}
sal_uInt16 SuggestionDisplay::GetEntryCount() const
{
return m_aListBox.GetEntryCount();
}
XubString SuggestionDisplay::GetEntry( sal_uInt16 nPos ) const
{
return m_aListBox.GetEntry( nPos );
}
XubString SuggestionDisplay::GetSelectEntry() const
{
return m_aListBox.GetSelectEntry();
}
void SuggestionDisplay::SetHelpIds()
{
this->SetHelpId( HID_HANGULDLG_SUGGESTIONS );
m_aValueSet.SetHelpId( HID_HANGULDLG_SUGGESTIONS_GRID );
m_aListBox.SetHelpId( HID_HANGULDLG_SUGGESTIONS_LIST );
}
//=========================================================================
//= HangulHanjaConversionDialog
//=========================================================================
//-------------------------------------------------------------------------
HangulHanjaConversionDialog::HangulHanjaConversionDialog( Window* _pParent, HHC::ConversionDirection _ePrimaryDirection )
:ModalDialog( _pParent, CUI_RES( RID_SVX_MDLG_HANGULHANJA ) )
,m_pPlayground( new SvxCommonLinguisticControl( this ) )
,m_aFind ( m_pPlayground.get(), CUI_RES( PB_FIND ) )
,m_aSuggestions ( m_pPlayground.get(), CUI_RES( CTL_SUGGESTIONS ) )
,m_aFormat ( m_pPlayground.get(), CUI_RES( FT_FORMAT ) )
,m_aSimpleConversion( m_pPlayground.get(), CUI_RES( RB_SIMPLE_CONVERSION ) )
,m_aHangulBracketed ( m_pPlayground.get(), CUI_RES( RB_HANJA_HANGUL_BRACKETED ) )
,m_aHanjaBracketed ( m_pPlayground.get(), CUI_RES( RB_HANGUL_HANJA_BRACKETED ) )
,m_aConversion ( m_pPlayground.get(), CUI_RES( FT_CONVERSION ) )
,m_aHangulOnly ( m_pPlayground.get(), CUI_RES( CB_HANGUL_ONLY ) )
,m_aHanjaOnly ( m_pPlayground.get(), CUI_RES( CB_HANJA_ONLY ) )
,m_aReplaceByChar ( m_pPlayground.get(), CUI_RES( CB_REPLACE_BY_CHARACTER ) )
,m_pIgnoreNonPrimary( NULL )
,m_bDocumentMode( true )
{
// special creation of the 4 pseudo-ruby radio buttons
String sSecondaryHangul( CUI_RES( STR_HANGUL ) );
String sSecondaryHanja( CUI_RES( STR_HANJA ) );
m_pHanjaAbove.reset( new RubyRadioButton( m_pPlayground.get(), CUI_RES( RB_HANGUL_HANJA_ABOVE ), sSecondaryHanja, PseudoRubyText::eAbove ) );
m_pHanjaBelow.reset( new RubyRadioButton( m_pPlayground.get(), CUI_RES( RB_HANGUL_HANJA_BELOW ), sSecondaryHanja, PseudoRubyText::eBelow ) );
m_pHangulAbove.reset( new RubyRadioButton( m_pPlayground.get(), CUI_RES( RB_HANJA_HANGUL_ABOVE ), sSecondaryHangul, PseudoRubyText::eAbove ) );
m_pHangulBelow.reset( new RubyRadioButton( m_pPlayground.get(), CUI_RES( RB_HANJA_HANGUL_BELOW ), sSecondaryHangul, PseudoRubyText::eBelow ) );
// since these 4 buttons are not created within the other members, they have a wrong initial Z-Order
// correct this
m_pHanjaAbove->SetZOrder( &m_aHanjaBracketed, WINDOW_ZORDER_BEHIND );
m_pHanjaBelow->SetZOrder( m_pHanjaAbove.get(), WINDOW_ZORDER_BEHIND );
m_pHangulAbove->SetZOrder( m_pHanjaBelow.get(), WINDOW_ZORDER_BEHIND );
m_pHangulBelow->SetZOrder( m_pHangulAbove.get(), WINDOW_ZORDER_BEHIND );
// VCL automatically sets the WB_GROUP bit, if the previous sibling (at the moment of creation)
// is no radion button
m_pHanjaAbove->SetStyle( m_pHanjaAbove->GetStyle() & ~WB_GROUP );
// the "Find" button and the word input control may not have the proper distance/extensions
// -> correct this
Point aDistance = LogicToPixel( Point( 3, 0 ), MAP_APPFONT );
sal_Int32 nTooLargeByPixels =
// right margin of the word input control
( m_pPlayground->GetWordInputControl().GetPosPixel().X()
+ m_pPlayground->GetWordInputControl().GetSizePixel().Width()
)
// minus left margin of the find button
- m_aFind.GetPosPixel().X()
// plus desired distance between the both
+ aDistance.X();
// make the word input control smaller
Size aSize = m_pPlayground->GetWordInputControl().GetSizePixel();
aSize.Width() -= nTooLargeByPixels;
m_pPlayground->GetWordInputControl().SetSizePixel( aSize );
// additionall, the playground is not wide enough (in it's default size)
sal_Int32 nEnlargeWidth = 0;
{
FixedText aBottomAnchor( m_pPlayground.get(), CUI_RES( FT_RESIZE_ANCHOR ) );
Point aAnchorPos = aBottomAnchor.GetPosPixel();
nEnlargeWidth = aAnchorPos.X() - m_pPlayground->GetActionButtonsLocation().X();
}
m_pPlayground->Enlarge( nEnlargeWidth, 0 );
// insert our controls into the z-order of the playground
m_pPlayground->InsertControlGroup( m_aFind, m_aFind, SvxCommonLinguisticControl::eLeftRightWords );
m_pPlayground->InsertControlGroup( m_aSuggestions, m_aHanjaOnly, SvxCommonLinguisticControl::eSuggestionLabel );
m_pPlayground->InsertControlGroup( m_aReplaceByChar, m_aReplaceByChar, SvxCommonLinguisticControl::eActionButtons );
m_pPlayground->SetButtonHandler( SvxCommonLinguisticControl::eClose, LINK( this, HangulHanjaConversionDialog, OnClose ) );
m_pPlayground->GetWordInputControl().SetModifyHdl( LINK( this, HangulHanjaConversionDialog, OnSuggestionModified ) );
m_aSuggestions.SetSelectHdl( LINK( this, HangulHanjaConversionDialog, OnSuggestionSelected ) );
m_aReplaceByChar.SetClickHdl( LINK( this, HangulHanjaConversionDialog, ClickByCharacterHdl ) );
m_aHangulOnly.SetClickHdl( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
m_aHanjaOnly.SetClickHdl( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
m_pPlayground->SetButtonHandler( SvxCommonLinguisticControl::eOptions,
LINK( this, HangulHanjaConversionDialog, OnOption ) );
m_pPlayground->GetButton( SvxCommonLinguisticControl::eOptions )->Show();
// m_pPlayground->EnableButton( SvxCommonLinguisticControl::eOptions, true );
if ( editeng::HangulHanjaConversion::eHangulToHanja == _ePrimaryDirection )
{
// m_aHanjaOnly.Enable( sal_False );
m_pIgnoreNonPrimary = &m_aHangulOnly;
}
else
{
// m_aHangulOnly.Enable( sal_False );
m_pIgnoreNonPrimary = &m_aHanjaOnly;
}
// m_pIgnoreNonPrimary->Check();
// initial focus
FocusSuggestion( );
// initial control values
m_aSimpleConversion.Check();
m_pPlayground->GetButton(SvxCommonLinguisticControl::eClose )->SetHelpId(HID_HANGULDLG_BUTTON_CLOSE );
m_pPlayground->GetButton(SvxCommonLinguisticControl::eIgnore )->SetHelpId(HID_HANGULDLG_BUTTON_IGNORE );
m_pPlayground->GetButton(SvxCommonLinguisticControl::eIgnoreAll )->SetHelpId(HID_HANGULDLG_BUTTON_IGNOREALL);
m_pPlayground->GetButton(SvxCommonLinguisticControl::eChange )->SetHelpId(HID_HANGULDLG_BUTTON_CHANGE );
m_pPlayground->GetButton(SvxCommonLinguisticControl::eChangeAll )->SetHelpId(HID_HANGULDLG_BUTTON_CHANGEALL);
m_pPlayground->GetButton(SvxCommonLinguisticControl::eOptions )->SetHelpId(HID_HANGULDLG_BUTTON_OPTIONS );
m_pPlayground->GetWordInputControl().SetHelpId(HID_HANGULDLG_EDIT_NEWWORD);
FreeResource();
m_aSuggestions.SetHelpIds();
}
//-------------------------------------------------------------------------
HangulHanjaConversionDialog::~HangulHanjaConversionDialog( )
{
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::FillSuggestions( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rSuggestions )
{
m_aSuggestions.Clear();
const ::rtl::OUString* pSuggestions = _rSuggestions.getConstArray();
const ::rtl::OUString* pSuggestionsEnd = _rSuggestions.getConstArray() + _rSuggestions.getLength();
while ( pSuggestions != pSuggestionsEnd )
m_aSuggestions.InsertEntry( *pSuggestions++ );
// select the first suggestion, and fill in the suggestion edit field
String sFirstSuggestion;
if ( m_aSuggestions.GetEntryCount() )
{
sFirstSuggestion = m_aSuggestions.GetEntry( 0 );
m_aSuggestions.SelectEntryPos( 0 );
}
m_pPlayground->GetWordInputControl().SetText( sFirstSuggestion );
m_pPlayground->GetWordInputControl().SaveValue();
OnSuggestionModified( &m_pPlayground->GetWordInputControl() );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetOptionsChangedHdl( const Link& _rHdl )
{
m_aOptionsChangedLink = _rHdl;
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetIgnoreHdl( const Link& _rHdl )
{
m_pPlayground->SetButtonHandler( SvxCommonLinguisticControl::eIgnore, _rHdl );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetIgnoreAllHdl( const Link& _rHdl )
{
m_pPlayground->SetButtonHandler( SvxCommonLinguisticControl::eIgnoreAll, _rHdl );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetChangeHdl( const Link& _rHdl )
{
m_pPlayground->SetButtonHandler( SvxCommonLinguisticControl::eChange, _rHdl );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetChangeAllHdl( const Link& _rHdl )
{
m_pPlayground->SetButtonHandler( SvxCommonLinguisticControl::eChangeAll, _rHdl );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetFindHdl( const Link& _rHdl )
{
m_aFind.SetClickHdl( _rHdl );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetConversionFormatChangedHdl( const Link& _rHdl )
{
m_aSimpleConversion.SetClickHdl( _rHdl );
m_aHangulBracketed.SetClickHdl( _rHdl );
m_aHanjaBracketed.SetClickHdl( _rHdl );
m_pHanjaAbove->SetClickHdl( _rHdl );
m_pHanjaBelow->SetClickHdl( _rHdl );
m_pHangulAbove->SetClickHdl( _rHdl );
m_pHangulBelow->SetClickHdl( _rHdl );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetClickByCharacterHdl( const Link& _rHdl )
{
m_aClickByCharacterLink = _rHdl;
}
//-------------------------------------------------------------------------
IMPL_LINK( HangulHanjaConversionDialog, OnSuggestionSelected, void*, EMPTYARG )
{
m_pPlayground->GetWordInputControl().SetText( m_aSuggestions.GetSelectEntry() );
OnSuggestionModified( NULL );
return 0L;
}
//-------------------------------------------------------------------------
IMPL_LINK( HangulHanjaConversionDialog, OnSuggestionModified, void*, EMPTYARG )
{
m_aFind.Enable( m_pPlayground->GetWordInputControl().GetSavedValue() != m_pPlayground->GetWordInputControl().GetText() );
bool bSameLen = m_pPlayground->GetWordInputControl().GetText().Len() == m_pPlayground->GetCurrentText().Len();
m_pPlayground->EnableButton( SvxCommonLinguisticControl::eChange, m_bDocumentMode && bSameLen );
m_pPlayground->EnableButton( SvxCommonLinguisticControl::eChangeAll, m_bDocumentMode && bSameLen );
return 0L;
}
//-------------------------------------------------------------------------
IMPL_LINK( HangulHanjaConversionDialog, ClickByCharacterHdl, CheckBox *, pBox )
{
m_aClickByCharacterLink.Call(pBox);
bool bByCharacter = pBox->IsChecked();
m_aSuggestions.DisplayListBox( !bByCharacter );
return 0L;
}
//-------------------------------------------------------------------------
IMPL_LINK( HangulHanjaConversionDialog, OnConversionDirectionClicked, CheckBox *, pBox )
{
CheckBox *pOtherBox = 0;
if (pBox == &m_aHangulOnly)
pOtherBox = &m_aHanjaOnly;
else if (pBox == &m_aHanjaOnly)
pOtherBox = &m_aHangulOnly;
if (pBox && pOtherBox)
{
sal_Bool bBoxChecked = pBox->IsChecked();
if (bBoxChecked)
pOtherBox->Check( sal_False );
pOtherBox->Enable( !bBoxChecked );
}
return 0L;
}
//-------------------------------------------------------------------------
IMPL_LINK( HangulHanjaConversionDialog, OnClose, void*, EMPTYARG )
{
Close();
return 0L;
}
IMPL_LINK( HangulHanjaConversionDialog, OnOption, void*, EMPTYARG )
{
HangulHanjaOptionsDialog aOptDlg( this );
aOptDlg.Execute();
m_aOptionsChangedLink.Call(this);
return 0L;
}
//-------------------------------------------------------------------------
String HangulHanjaConversionDialog::GetCurrentString( ) const
{
return m_pPlayground->GetCurrentText( );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::FocusSuggestion( )
{
m_pPlayground->GetWordInputControl().GrabFocus();
}
//-------------------------------------------------------------------------
namespace
{
void lcl_modifyWindowStyle( Window* _pWin, WinBits _nSet, WinBits _nReset )
{
DBG_ASSERT( 0 == ( _nSet & _nReset ), "lcl_modifyWindowStyle: set _and_ reset the same bit?" );
if ( _pWin )
_pWin->SetStyle( ( _pWin->GetStyle() | _nSet ) & ~_nReset );
}
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetCurrentString( const String& _rNewString,
const Sequence< ::rtl::OUString >& _rSuggestions, bool _bOriginatesFromDocument )
{
m_pPlayground->SetCurrentText( _rNewString );
bool bOldDocumentMode = m_bDocumentMode;
m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions!
FillSuggestions( _rSuggestions );
m_pPlayground->EnableButton( SvxCommonLinguisticControl::eIgnoreAll, m_bDocumentMode );
// all other buttons have been implicitly enabled or disabled during filling in the suggestions
// switch the def button depending if we're working for document text
if ( bOldDocumentMode != m_bDocumentMode )
{
Window* pOldDefButton = NULL;
Window* pNewDefButton = NULL;
if ( m_bDocumentMode )
{
pOldDefButton = &m_aFind;
pNewDefButton = m_pPlayground->GetButton( SvxCommonLinguisticControl::eChange );
}
else
{
pOldDefButton = m_pPlayground->GetButton( SvxCommonLinguisticControl::eChange );
pNewDefButton = &m_aFind;
}
DBG_ASSERT( WB_DEFBUTTON == ( pOldDefButton->GetStyle( ) & WB_DEFBUTTON ),
"HangulHanjaConversionDialog::SetCurrentString: wrong previous default button (1)!" );
DBG_ASSERT( 0 == ( pNewDefButton->GetStyle( ) & WB_DEFBUTTON ),
"HangulHanjaConversionDialog::SetCurrentString: wrong previous default button (2)!" );
lcl_modifyWindowStyle( pOldDefButton, 0, WB_DEFBUTTON );
lcl_modifyWindowStyle( pNewDefButton, WB_DEFBUTTON, 0 );
// give the focus to the new def button temporarily - VCL is somewhat peculiar
// in recognizing a new default button
sal_uInt32 nSaveFocusId = Window::SaveFocus();
pNewDefButton->GrabFocus();
Window::EndSaveFocus( nSaveFocusId );
}
}
//-------------------------------------------------------------------------
String HangulHanjaConversionDialog::GetCurrentSuggestion( ) const
{
return m_pPlayground->GetWordInputControl().GetText();
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetByCharacter( sal_Bool _bByCharacter )
{
m_aReplaceByChar.Check( _bByCharacter );
m_aSuggestions.DisplayListBox( !_bByCharacter );
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetConversionDirectionState(
sal_Bool _bTryBothDirections,
HHC::ConversionDirection _ePrimaryConversionDirection )
{
// default state: try both direction
m_aHangulOnly.Check( sal_False );
m_aHangulOnly.Enable( sal_True );
m_aHanjaOnly.Check( sal_False );
m_aHanjaOnly.Enable( sal_True );
if (!_bTryBothDirections)
{
CheckBox *pBox = _ePrimaryConversionDirection == HHC::eHangulToHanja?
&m_aHangulOnly : &m_aHanjaOnly;
pBox->Check( sal_True );
OnConversionDirectionClicked( pBox );
}
}
//-------------------------------------------------------------------------
sal_Bool HangulHanjaConversionDialog::GetUseBothDirections( ) const
{
// DBG_ASSERT( m_pIgnoreNonPrimary, "HangulHanjaConversionDialog::GetUseBothDirections: where's the check box pointer?" );
// return m_pIgnoreNonPrimary ? !m_pIgnoreNonPrimary->IsChecked( ) : sal_True;
return !m_aHangulOnly.IsChecked() && !m_aHanjaOnly.IsChecked();
}
//-------------------------------------------------------------------------
HHC::ConversionDirection HangulHanjaConversionDialog::GetDirection(
HHC::ConversionDirection eDefaultDirection ) const
{
HHC::ConversionDirection eDirection = eDefaultDirection;
if (m_aHangulOnly.IsChecked() && !m_aHanjaOnly.IsChecked())
eDirection = HHC::eHangulToHanja;
else if (!m_aHangulOnly.IsChecked() && m_aHanjaOnly.IsChecked())
eDirection = HHC::eHanjaToHangul;
return eDirection;
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::SetConversionFormat( HHC::ConversionFormat _eType )
{
switch ( _eType )
{
case HHC::eSimpleConversion: m_aSimpleConversion.Check(); break;
case HHC::eHangulBracketed: m_aHangulBracketed.Check(); break;
case HHC::eHanjaBracketed: m_aHanjaBracketed.Check(); break;
case HHC::eRubyHanjaAbove: m_pHanjaAbove->Check(); break;
case HHC::eRubyHanjaBelow: m_pHanjaBelow->Check(); break;
case HHC::eRubyHangulAbove: m_pHangulAbove->Check(); break;
case HHC::eRubyHangulBelow: m_pHangulBelow->Check(); break;
default:
DBG_ERROR( "HangulHanjaConversionDialog::SetConversionFormat: unknown type!" );
}
}
//-------------------------------------------------------------------------
HHC::ConversionFormat HangulHanjaConversionDialog::GetConversionFormat( ) const
{
if ( m_aSimpleConversion.IsChecked() )
return HHC::eSimpleConversion;
if ( m_aHangulBracketed.IsChecked() )
return HHC::eHangulBracketed;
if ( m_aHanjaBracketed.IsChecked() )
return HHC::eHanjaBracketed;
if ( m_pHanjaAbove->IsChecked() )
return HHC::eRubyHanjaAbove;
if ( m_pHanjaBelow->IsChecked() )
return HHC::eRubyHanjaBelow;
if ( m_pHangulAbove->IsChecked() )
return HHC::eRubyHangulAbove;
if ( m_pHangulBelow->IsChecked() )
return HHC::eRubyHangulBelow;
DBG_ERROR( "HangulHanjaConversionDialog::GetConversionFormat: no radio checked?" );
return HHC::eSimpleConversion;
}
//-------------------------------------------------------------------------
void HangulHanjaConversionDialog::EnableRubySupport( sal_Bool bVal )
{
m_pHanjaAbove->Enable( bVal );
m_pHanjaBelow->Enable( bVal );
m_pHangulAbove->Enable( bVal );
m_pHangulBelow->Enable( bVal );
}
//=========================================================================
//= HangulHanjaOptionsDialog
//=========================================================================
//-------------------------------------------------------------------------
void HangulHanjaOptionsDialog::Init( void )
{
if( !m_xConversionDictionaryList.is() )
{
Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
if( xMgr.is() )
{
m_xConversionDictionaryList = Reference< XConversionDictionaryList >( xMgr->createInstance(
OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.linguistic2.ConversionDictionaryList")) ),
UNO_QUERY );
}
}
m_aDictList.clear();
m_aDictsLB.Clear();
if( m_xConversionDictionaryList.is() )
{
Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
Reference< XNameAccess > xNameAccess = Reference< XNameAccess >( xNameCont, UNO_QUERY );
if( xNameAccess.is() )
{
Sequence< ::rtl::OUString > aDictNames( xNameAccess->getElementNames() );
const ::rtl::OUString* pDic = aDictNames.getConstArray();
sal_Int32 nCount = aDictNames.getLength();
sal_Int32 i;
for( i = 0 ; i < nCount ; ++i )
{
Any aAny( xNameAccess->getByName( pDic[ i ] ) );
Reference< XConversionDictionary > xDic;
if( ( aAny >>= xDic ) && xDic.is() )
{
if( LANGUAGE_KOREAN == SvxLocaleToLanguage( xDic->getLocale() ) )
{
m_aDictList.push_back( xDic );
AddDict( xDic->getName(), xDic->isActive() );
}
}
}
}
}
}
IMPL_LINK( HangulHanjaOptionsDialog, OkHdl, void*, EMPTYARG )
{
sal_uInt32 nCnt = m_aDictList.size();
sal_uInt32 n = 0;
sal_uInt32 nActiveDics = 0;
Sequence< OUString > aActiveDics;
aActiveDics.realloc( nCnt );
OUString* pActActiveDic = aActiveDics.getArray();
while( nCnt )
{
Reference< XConversionDictionary > xDict = m_aDictList[ n ];
SvLBoxEntry* pEntry = m_aDictsLB.SvTreeListBox::GetEntry( n );
DBG_ASSERT( xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..." );
DBG_ASSERT( pEntry, "-HangulHanjaOptionsDialog::OkHdl(): no one there in list?" );
bool bActive = m_aDictsLB.GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED;
xDict->setActive( bActive );
Reference< util::XFlushable > xFlush( xDict, uno::UNO_QUERY );
if( xFlush.is() )
xFlush->flush();
if( bActive )
{
pActActiveDic[ nActiveDics ] = xDict->getName();
++nActiveDics;
}
++n;
--nCnt;
}
// save configuration
aActiveDics.realloc( nActiveDics );
Any aTmp;
SvtLinguConfig aLngCfg;
aTmp <<= aActiveDics;
aLngCfg.SetProperty( UPH_ACTIVE_CONVERSION_DICTIONARIES, aTmp );
aTmp <<= bool( m_aIgnorepostCB.IsChecked() );
aLngCfg.SetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD, aTmp );
aTmp <<= bool( m_aShowrecentlyfirstCB.IsChecked() );
aLngCfg.SetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, aTmp );
aTmp <<= bool( m_aAutoreplaceuniqueCB.IsChecked() );
aLngCfg.SetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES, aTmp );
EndDialog( RET_OK );
return 0;
}
IMPL_LINK( HangulHanjaOptionsDialog, DictsLB_SelectHdl, void*, EMPTYARG )
{
bool bSel = m_aDictsLB.FirstSelected() != NULL;
m_aEditPB.Enable( bSel );
m_aDeletePB.Enable( bSel );
return 0;
}
IMPL_LINK( HangulHanjaOptionsDialog, NewDictHdl, void*, EMPTYARG )
{
String aName;
HangulHanjaNewDictDialog aNewDlg( this );
aNewDlg.Execute();
if( aNewDlg.GetName( aName ) )
{
if( m_xConversionDictionaryList.is() )
{
try
{
Reference< XConversionDictionary > xDic =
m_xConversionDictionaryList->addNewDictionary( aName, SvxCreateLocale( LANGUAGE_KOREAN ), ConversionDictionaryType::HANGUL_HANJA );
if( xDic.is() )
{
//adapt local caches:
m_aDictList.push_back( xDic );
AddDict( xDic->getName(), xDic->isActive() );
}
}
catch( const ElementExistException& )
{
}
catch( const NoSupportException& )
{
}
}
}
return 0L;
}
IMPL_LINK( HangulHanjaOptionsDialog, EditDictHdl, void*, EMPTYARG )
{
SvLBoxEntry* pEntry = m_aDictsLB.FirstSelected();
DBG_ASSERT( pEntry, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not be possible with no selection!" );
if( pEntry )
{
HangulHanjaEditDictDialog aEdDlg( this, m_aDictList, m_aDictsLB.GetSelectEntryPos() );
aEdDlg.Execute();
}
return 0L;
}
IMPL_LINK( HangulHanjaOptionsDialog, DeleteDictHdl, void*, EMPTYARG )
{
sal_uInt16 nSelPos = m_aDictsLB.GetSelectEntryPos();
if( nSelPos != LISTBOX_ENTRY_NOTFOUND )
{
Reference< XConversionDictionary > xDic( m_aDictList[ nSelPos ] );
if( m_xConversionDictionaryList.is() && xDic.is() )
{
Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
if( xNameCont.is() )
{
try
{
xNameCont->removeByName( xDic->getName() );
//adapt local caches:
HHDictList::iterator aIter(m_aDictList.begin());
m_aDictList.erase(aIter+nSelPos );
m_aDictsLB.RemoveEntry( nSelPos );
}
catch( const ElementExistException& )
{
}
catch( const NoSupportException& )
{
}
}
}
}
return 0L;
}
HangulHanjaOptionsDialog::HangulHanjaOptionsDialog( Window* _pParent )
:ModalDialog ( _pParent, CUI_RES( RID_SVX_MDLG_HANGULHANJA_OPT ) )
,m_aUserdefdictFT ( this, CUI_RES( FT_USERDEFDICT ) )
,m_aDictsLB ( this, CUI_RES( LB_DICTS ) )
,m_aOptionsFL ( this, CUI_RES( FL_OPTIONS ) )
,m_aIgnorepostCB ( this, CUI_RES( CB_IGNOREPOST ) )
,m_aShowrecentlyfirstCB ( this, CUI_RES( CB_SHOWRECENTLYFIRST ) )
,m_aAutoreplaceuniqueCB ( this, CUI_RES( CB_AUTOREPLACEUNIQUE ) )
,m_aNewPB ( this, CUI_RES( PB_HHO_NEW ) )
,m_aEditPB ( this, CUI_RES( PB_HHO_EDIT ) )
,m_aDeletePB ( this, CUI_RES( PB_HHO_DELETE ) )
,m_aOkPB ( this, CUI_RES( PB_HHO_OK ) )
,m_aCancelPB ( this, CUI_RES( PB_HHO_CANCEL ) )
,m_aHelpPB ( this, CUI_RES( PB_HHO_HELP ) )
,m_pCheckButtonData ( NULL )
,m_xConversionDictionaryList( NULL )
{
m_aDictsLB.SetStyle( m_aDictsLB.GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_FORCE_MAKEVISIBLE );
m_aDictsLB.SetSelectionMode( SINGLE_SELECTION );
m_aDictsLB.SetHighlightRange();
// m_aDictsLB.SetHelpId( xxx );
m_aDictsLB.SetSelectHdl( LINK( this, HangulHanjaOptionsDialog, DictsLB_SelectHdl ) );
m_aDictsLB.SetDeselectHdl( LINK( this, HangulHanjaOptionsDialog, DictsLB_SelectHdl ) );
m_aOkPB.SetClickHdl( LINK( this, HangulHanjaOptionsDialog, OkHdl ) );
m_aNewPB.SetClickHdl( LINK( this, HangulHanjaOptionsDialog, NewDictHdl ) );
m_aEditPB.SetClickHdl( LINK( this, HangulHanjaOptionsDialog, EditDictHdl ) );
m_aDeletePB.SetClickHdl( LINK( this, HangulHanjaOptionsDialog, DeleteDictHdl ) );
FreeResource();
SvtLinguConfig aLngCfg;
Any aTmp;
bool bVal = bool();
aTmp = aLngCfg.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD );
if( aTmp >>= bVal )
m_aIgnorepostCB.Check( bVal );
aTmp = aLngCfg.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST );
if( aTmp >>= bVal )
m_aShowrecentlyfirstCB.Check( bVal );
aTmp = aLngCfg.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES );
if( aTmp >>= bVal )
m_aAutoreplaceuniqueCB.Check( bVal );
Init();
}
HangulHanjaOptionsDialog::~HangulHanjaOptionsDialog()
{
SvLBoxEntry* pEntry = m_aDictsLB.First();
String* pDel;
while( pEntry )
{
pDel = ( String* ) pEntry->GetUserData();
if( pDel )
delete pDel;
pEntry = m_aDictsLB.Next( pEntry );
}
if( m_pCheckButtonData )
delete m_pCheckButtonData;
}
void HangulHanjaOptionsDialog::AddDict( const String& _rName, bool _bChecked )
{
SvLBoxEntry* pEntry = m_aDictsLB.SvTreeListBox::InsertEntry( _rName );
m_aDictsLB.SetCheckButtonState( pEntry, _bChecked? SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED );
pEntry->SetUserData( new String( _rName ) );
}
//=========================================================================
//= HangulHanjaNewDictDialog
//=========================================================================
//-------------------------------------------------------------------------
IMPL_LINK( HangulHanjaNewDictDialog, OKHdl, void*, EMPTYARG )
{
String aName( m_aDictNameED.GetText() );
aName.EraseTrailingChars();
m_bEntered = aName.Len() > 0;
if( m_bEntered )
m_aDictNameED.SetText( aName ); // do this in case of trailing chars have been deleted
EndDialog( RET_OK );
return 0;
}
IMPL_LINK( HangulHanjaNewDictDialog, ModifyHdl, void*, EMPTYARG )
{
String aName( m_aDictNameED.GetText() );
aName.EraseTrailingChars();
m_aOkBtn.Enable( aName.Len() > 0 );
return 0;
}
HangulHanjaNewDictDialog::HangulHanjaNewDictDialog( Window* _pParent )
:ModalDialog ( _pParent, CUI_RES( RID_SVX_MDLG_HANGULHANJA_NEWDICT ) )
,m_aNewDictFL ( this, CUI_RES( FL_NEWDICT ) )
,m_aDictNameFT ( this, CUI_RES( FT_DICTNAME ) )
,m_aDictNameED ( this, CUI_RES( ED_DICTNAME ) )
,m_aOkBtn ( this, CUI_RES( PB_NEWDICT_OK ) )
,m_aCancelBtn ( this, CUI_RES( PB_NEWDICT_ESC ) )
,m_aHelpBtn ( this, CUI_RES( PB_NEWDICT_HLP ) )
,m_bEntered ( false )
{
m_aOkBtn.SetClickHdl( LINK( this, HangulHanjaNewDictDialog, OKHdl ) );
m_aDictNameED.SetModifyHdl( LINK( this, HangulHanjaNewDictDialog, ModifyHdl ) );
FreeResource();
}
HangulHanjaNewDictDialog::~HangulHanjaNewDictDialog()
{
}
bool HangulHanjaNewDictDialog::GetName( String& _rRetName ) const
{
if( m_bEntered )
{
_rRetName = m_aDictNameED.GetText();
_rRetName.EraseTrailingChars();
}
return m_bEntered;
}
//=========================================================================
//= HangulHanjaEditDictDialog
//=========================================================================
//-------------------------------------------------------------------------
class SuggestionList
{
private:
protected:
sal_uInt16 m_nSize;
String** m_ppElements;
sal_uInt16 m_nNumOfEntries;
sal_uInt16 m_nAct;
const String* _Next( void );
public:
SuggestionList( sal_uInt16 _nNumOfElements );
virtual ~SuggestionList();
bool Set( const String& _rElement, sal_uInt16 _nNumOfElement );
bool Reset( sal_uInt16 _nNumOfElement );
const String* Get( sal_uInt16 _nNumOfElement ) const;
void Clear( void );
const String* First( void );
const String* Next( void );
inline sal_uInt16 GetCount( void ) const;
};
inline sal_uInt16 SuggestionList::GetCount( void ) const
{
return m_nNumOfEntries;
}
SuggestionList::SuggestionList( sal_uInt16 _nNumOfElements )
{
if( !_nNumOfElements )
_nNumOfElements = 1;
m_nSize = _nNumOfElements;
m_ppElements = new String*[ m_nSize ];
m_nAct = m_nNumOfEntries = 0;
String** ppNull = m_ppElements;
sal_uInt16 n = _nNumOfElements;
while( n )
{
*ppNull = NULL;
++ppNull;
--n;
}
}
SuggestionList::~SuggestionList()
{
Clear();
}
bool SuggestionList::Set( const String& _rElement, sal_uInt16 _nNumOfElement )
{
bool bRet = _nNumOfElement < m_nSize;
if( bRet )
{
String** ppElem = m_ppElements + _nNumOfElement;
if( *ppElem )
**ppElem = _rElement;
else
{
*ppElem = new String( _rElement );
++m_nNumOfEntries;
}
}
return bRet;
}
bool SuggestionList::Reset( sal_uInt16 _nNumOfElement )
{
bool bRet = _nNumOfElement < m_nSize;
if( bRet )
{
String** ppElem = m_ppElements + _nNumOfElement;
if( *ppElem )
{
delete *ppElem;
*ppElem = NULL;
--m_nNumOfEntries;
}
}
return bRet;
}
const String* SuggestionList::Get( sal_uInt16 _nNumOfElement ) const
{
const String* pRet;
if( _nNumOfElement < m_nSize )
pRet = m_ppElements[ _nNumOfElement ];
else
pRet = NULL;
return pRet;
}
void SuggestionList::Clear( void )
{
if( m_nNumOfEntries )
{
String** ppDel = m_ppElements;
sal_uInt16 nCnt = m_nSize;
while( nCnt )
{
if( *ppDel )
{
delete *ppDel;
*ppDel = NULL;
}
++ppDel;
--nCnt;
}
m_nNumOfEntries = m_nAct = 0;
}
}
const String* SuggestionList::_Next( void )
{
const String* pRet = NULL;
while( m_nAct < m_nSize && !pRet )
{
pRet = m_ppElements[ m_nAct ];
if( !pRet )
++m_nAct;
}
return pRet;
}
const String* SuggestionList::First( void )
{
m_nAct = 0;
return _Next();
}
const String* SuggestionList::Next( void )
{
const String* pRet;
if( m_nAct < m_nNumOfEntries )
{
++m_nAct;
pRet = _Next();
}
else
pRet = NULL;
return pRet;
}
bool SuggestionEdit::ShouldScroll( bool _bUp ) const
{
bool bRet = false;
if( _bUp )
{
if( !m_pPrev )
bRet = m_rScrollBar.GetThumbPos() > m_rScrollBar.GetRangeMin();
}
else
{
if( !m_pNext )
bRet = m_rScrollBar.GetThumbPos() < ( m_rScrollBar.GetRangeMax() - 4 );
}
return bRet;
}
void SuggestionEdit::DoJump( bool _bUp )
{
const Link& rLoseFocusHdl = GetLoseFocusHdl();
if( rLoseFocusHdl.IsSet() )
rLoseFocusHdl.Call( this );
m_rScrollBar.SetThumbPos( m_rScrollBar.GetThumbPos() + ( _bUp? -1 : 1 ) );
( static_cast< HangulHanjaEditDictDialog* >( GetParent() ) )->UpdateScrollbar();
}
SuggestionEdit::SuggestionEdit( Window* pParent, const ResId& rResId,
ScrollBar& _rScrollBar, SuggestionEdit* _pPrev, SuggestionEdit* _pNext )
:Edit( pParent, rResId )
,m_pPrev( _pPrev )
,m_pNext( _pNext )
,m_rScrollBar( _rScrollBar )
{
}
SuggestionEdit::~SuggestionEdit()
{
}
long SuggestionEdit::PreNotify( NotifyEvent& rNEvt )
{
long nHandled = 0;
if( rNEvt.GetType() == EVENT_KEYINPUT )
{
const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
const KeyCode& rKeyCode = pKEvt->GetKeyCode();
sal_uInt16 nMod = rKeyCode.GetModifier();
sal_uInt16 nCode = rKeyCode.GetCode();
if( nCode == KEY_TAB && ( !nMod || KEY_SHIFT == nMod ) )
{
bool bUp = KEY_SHIFT == nMod;
if( ShouldScroll( bUp ) )
{
DoJump( bUp );
SetSelection( Selection( 0, SELECTION_MAX ) );
// Tab-travel doesn't really happen, so emulate it by setting a selection manually
nHandled = 1;
}
}
else if( KEY_UP == nCode || KEY_DOWN == nCode )
{
bool bUp = KEY_UP == nCode;
if( ShouldScroll( bUp ) )
{
DoJump( bUp );
nHandled = 1;
}
else if( bUp )
{
if( m_pPrev )
{
m_pPrev->GrabFocus();
nHandled = 1;
}
}
else if( m_pNext )
{
m_pNext->GrabFocus();
nHandled = 1;
}
}
}
if( !nHandled )
nHandled = Edit::PreNotify( rNEvt );
return nHandled;
}
namespace
{
bool GetConversions( Reference< XConversionDictionary > _xDict,
const OUString& _rOrg,
Sequence< OUString >& _rEntries )
{
bool bRet = false;
if( _xDict.is() && _rOrg.getLength() )
{
try
{
_rEntries = _xDict->getConversions( _rOrg,
0,
_rOrg.getLength(),
ConversionDirection_FROM_LEFT,
::com::sun::star::i18n::TextConversionOption::NONE );
bRet = _rEntries.getLength() > 0;
}
catch( const IllegalArgumentException& )
{
}
}
return bRet;
}
}
IMPL_LINK( HangulHanjaEditDictDialog, ScrollHdl, void*, EMPTYARG )
{
UpdateScrollbar();
return 0;
}
IMPL_LINK( HangulHanjaEditDictDialog, OriginalModifyHdl, void*, EMPTYARG )
{
m_bModifiedOriginal = true;
m_aOriginal = m_aOriginalLB.GetText();
m_aOriginal.EraseTrailingChars();
UpdateSuggestions();
UpdateButtonStates();
return 0;
}
IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl1, Edit*, pEdit )
{
EditModify( pEdit, 0 );
return 0;
}
IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl2, Edit*, pEdit )
{
EditModify( pEdit, 1 );
return 0;
}
IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl3, Edit*, pEdit )
{
EditModify( pEdit, 2 );
return 0;
}
IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl4, Edit*, pEdit )
{
EditModify( pEdit, 3 );
return 0;
}
IMPL_LINK( HangulHanjaEditDictDialog, BookLBSelectHdl, void*, EMPTYARG )
{
InitEditDictDialog( m_aBookLB.GetSelectEntryPos() );
return 0;
}
IMPL_LINK( HangulHanjaEditDictDialog, NewPBPushHdl, void*, EMPTYARG )
{
DBG_ASSERT( m_pSuggestions, "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..." );
Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
if( xDict.is() && m_pSuggestions )
{
//delete old entry
bool bRemovedSomething = DeleteEntryFromDictionary( m_aOriginal, xDict );
OUString aLeft( m_aOriginal );
const String* pRight = m_pSuggestions->First();
bool bAddedSomething = false;
while( pRight )
{
try
{
//add new entry
xDict->addEntry( aLeft, *pRight );
bAddedSomething = true;
}
catch( const IllegalArgumentException& )
{
}
catch( const ElementExistException& )
{
}
pRight = m_pSuggestions->Next();
}
if(bAddedSomething||bRemovedSomething)
InitEditDictDialog( m_nCurrentDict );
}
else
{
DBG_WARNING( "+HangulHanjaEditDictDialog::NewPBPushHdl(): dictionary faded away..." );
}
return 0;
}
bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( const OUString&, const Reference< XConversionDictionary >& xDict )
{
bool bRemovedSomething = false;
if( xDict.is() )
{
OUString aOrg( m_aOriginal );
Sequence< OUString > aEntries;
GetConversions( xDict, m_aOriginal, aEntries );
sal_uInt32 n = aEntries.getLength();
OUString* pEntry = aEntries.getArray();
while( n )
{
try
{
xDict->removeEntry( aOrg, *pEntry );
bRemovedSomething = true;
}
catch( const NoSuchElementException& )
{ // can not be...
}
++pEntry;
--n;
}
}
return bRemovedSomething;
}
IMPL_LINK( HangulHanjaEditDictDialog, DeletePBPushHdl, void*, EMPTYARG )
{
if( DeleteEntryFromDictionary( m_aOriginal, m_rDictList[ m_nCurrentDict ] ) )
{
m_aOriginal.Erase();
m_bModifiedOriginal = true;
InitEditDictDialog( m_nCurrentDict );
}
return 0;
}
void HangulHanjaEditDictDialog::InitEditDictDialog( sal_uInt32 _nSelDict )
{
if( m_pSuggestions )
m_pSuggestions->Clear();
if( m_nCurrentDict != _nSelDict )
{
m_nCurrentDict = _nSelDict;
m_aOriginal.Erase();
m_bModifiedOriginal = true;
}
UpdateOriginalLB();
m_aOriginalLB.SetText( m_aOriginal.Len()? m_aOriginal : m_aEditHintText, Selection( 0, SELECTION_MAX ) );
m_aOriginalLB.GrabFocus();
UpdateSuggestions();
UpdateButtonStates();
}
void HangulHanjaEditDictDialog::UpdateOriginalLB( void )
{
m_aOriginalLB.Clear();
Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
if( xDict.is() )
{
Sequence< OUString > aEntries = xDict->getConversionEntries( ConversionDirection_FROM_LEFT );
sal_uInt32 n = aEntries.getLength();
OUString* pEntry = aEntries.getArray();
while( n )
{
m_aOriginalLB.InsertEntry( *pEntry );
++pEntry;
--n;
}
}
else
{
DBG_WARNING( "+HangulHanjaEditDictDialog::UpdateOriginalLB(): dictionary faded away..." );
}
}
void HangulHanjaEditDictDialog::UpdateButtonStates()
{
bool bHaveValidOriginalString = m_aOriginal.Len() && m_aOriginal != m_aEditHintText;
bool bNew = bHaveValidOriginalString && m_pSuggestions && m_pSuggestions->GetCount() > 0;
bNew = bNew && (m_bModifiedSuggestions || m_bModifiedOriginal);
m_aNewPB.Enable( bNew );
m_aDeletePB.Enable( !m_bModifiedOriginal && bHaveValidOriginalString );
}
void HangulHanjaEditDictDialog::UpdateSuggestions( void )
{
Sequence< OUString > aEntries;
bool bFound = GetConversions( m_rDictList[ m_nCurrentDict ], m_aOriginal, aEntries );
if( bFound )
{
m_bModifiedOriginal = false;
if( m_pSuggestions )
m_pSuggestions->Clear();
//fill found entries into boxes
sal_uInt32 nCnt = aEntries.getLength();
sal_uInt32 n = 0;
if( nCnt )
{
if( !m_pSuggestions )
m_pSuggestions = new SuggestionList( MAXNUM_SUGGESTIONS );
const OUString* pSugg = aEntries.getConstArray();
while( nCnt )
{
m_pSuggestions->Set( pSugg[ n ], sal_uInt16( n ) );
++n;
--nCnt;
}
}
m_bModifiedSuggestions=false;
}
m_aScrollSB.SetThumbPos( 0 );
UpdateScrollbar(); // will force edits to be filled new
}
void HangulHanjaEditDictDialog::SetEditText( Edit& _rEdit, sal_uInt16 _nEntryNum )
{
String aStr;
if( m_pSuggestions )
{
const String* p = m_pSuggestions->Get( _nEntryNum );
if( p )
aStr = *p;
}
_rEdit.SetText( aStr );
}
void HangulHanjaEditDictDialog::EditModify( Edit* _pEdit, sal_uInt8 _nEntryOffset )
{
m_bModifiedSuggestions = true;
String aTxt( _pEdit->GetText() );
sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset;
if( aTxt.Len() == 0 )
{
//reset suggestion
if( m_pSuggestions )
m_pSuggestions->Reset( nEntryNum );
}
else
{
//set suggestion
if( !m_pSuggestions )
m_pSuggestions = new SuggestionList( MAXNUM_SUGGESTIONS );
m_pSuggestions->Set( aTxt, nEntryNum );
}
UpdateButtonStates();
}
HangulHanjaEditDictDialog::HangulHanjaEditDictDialog( Window* _pParent, HHDictList& _rDictList, sal_uInt32 _nSelDict )
:ModalDialog ( _pParent, CUI_RES( RID_SVX_MDLG_HANGULHANJA_EDIT ) )
,m_aEditHintText ( CUI_RES( STR_EDITHINT ) )
,m_rDictList ( _rDictList )
,m_nCurrentDict ( 0xFFFFFFFF )
,m_pSuggestions ( NULL )
,m_aBookFT ( this, CUI_RES( FT_BOOK ) )
,m_aBookLB ( this, CUI_RES( LB_BOOK ) )
,m_aOriginalFT ( this, CUI_RES( FT_ORIGINAL ) )
,m_aOriginalLB ( this, CUI_RES( LB_ORIGINAL ) )
,m_aSuggestionsFT ( this, CUI_RES( FT_SUGGESTIONS ) )
,m_aEdit1 ( this, CUI_RES( ED_1 ), m_aScrollSB, NULL, &m_aEdit2 )
,m_aEdit2 ( this, CUI_RES( ED_2 ), m_aScrollSB, &m_aEdit1, &m_aEdit3 )
,m_aEdit3 ( this, CUI_RES( ED_3 ), m_aScrollSB, &m_aEdit2, &m_aEdit4 )
,m_aEdit4 ( this, CUI_RES( ED_4 ), m_aScrollSB, &m_aEdit3, NULL )
,m_aScrollSB ( this, CUI_RES( SB_SCROLL ) )
,m_aNewPB ( this, CUI_RES( PB_HHE_NEW ) )
,m_aDeletePB ( this, CUI_RES( PB_HHE_DELETE ) )
,m_aHelpPB ( this, CUI_RES( PB_HHE_HELP ) )
,m_aClosePB ( this, CUI_RES( PB_HHE_CLOSE ) )
,m_nTopPos ( 0 )
,m_bModifiedSuggestions ( false )
,m_bModifiedOriginal ( false )
{
m_aOriginalLB.SetModifyHdl( LINK( this, HangulHanjaEditDictDialog, OriginalModifyHdl ) );
m_aNewPB.SetClickHdl( LINK( this, HangulHanjaEditDictDialog, NewPBPushHdl ) );
m_aNewPB.Enable( false );
m_aDeletePB.SetClickHdl( LINK( this, HangulHanjaEditDictDialog, DeletePBPushHdl ) );
m_aDeletePB.Enable( false );
#if( MAXNUM_SUGGESTIONS <= 4 )
#error number of suggestions should not under-run the value of 5
#endif
Link aScrLk( LINK( this, HangulHanjaEditDictDialog, ScrollHdl ) );
m_aScrollSB.SetScrollHdl( aScrLk );
m_aScrollSB.SetEndScrollHdl( aScrLk );
m_aScrollSB.SetRangeMin( 0 );
m_aScrollSB.SetRangeMax( MAXNUM_SUGGESTIONS );
m_aScrollSB.SetPageSize( 4 ); // because we have 4 edits / page
m_aScrollSB.SetVisibleSize( 4 );
m_aEdit1.SetModifyHdl( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl1 ) );
m_aEdit2.SetModifyHdl( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl2 ) );
m_aEdit3.SetModifyHdl( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl3 ) );
m_aEdit4.SetModifyHdl( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl4 ) );
m_aBookLB.SetSelectHdl( LINK( this, HangulHanjaEditDictDialog, BookLBSelectHdl ) );
sal_uInt32 nDictCnt = m_rDictList.size();
for( sal_uInt32 n = 0 ; n < nDictCnt ; ++n )
{
Reference< XConversionDictionary > xDic( m_rDictList[n] );
String aName;
if(xDic.is())
aName = xDic->getName();
m_aBookLB.InsertEntry( aName );
}
m_aBookLB.SelectEntryPos( sal_uInt16( _nSelDict ) );
FreeResource();
InitEditDictDialog( _nSelDict );
}
HangulHanjaEditDictDialog::~HangulHanjaEditDictDialog()
{
if( m_pSuggestions )
delete m_pSuggestions;
}
void HangulHanjaEditDictDialog::UpdateScrollbar( void )
{
sal_uInt16 nPos = sal_uInt16( m_aScrollSB.GetThumbPos() );
m_nTopPos = nPos;
SetEditText( m_aEdit1, nPos++ );
SetEditText( m_aEdit2, nPos++ );
SetEditText( m_aEdit3, nPos++ );
SetEditText( m_aEdit4, nPos );
}
//.............................................................................
} // namespace svx
//.............................................................................