Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  hangulhanjadlg.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */


#include <hangulhanjadlg.hxx>
#include <dialmgr.hxx>

#include <helpids.h>
#include <strings.hrc>

#include <algorithm>
#include <sal/log.hxx>
#include <osl/diagnose.h>
#include <tools/debug.hxx>
#include <i18nlangtag/languagetag.hxx>
#include <vcl/virdev.hxx>
#include <vcl/weldutils.hxx>
#include <unotools/lingucfg.hxx>
#include <unotools/linguprops.hxx>
#include <com/sun/star/lang/NoSupportException.hpp>
#include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
#include <com/sun/star/linguistic2/ConversionDirection.hpp>
#include <com/sun/star/linguistic2/ConversionDictionaryList.hpp>
#include <com/sun/star/i18n/TextConversionOption.hpp>
#include <com/sun/star/util/XFlushable.hpp>

#include <comphelper/processfactory.hxx>
#include <comphelper/string.hxx>

#define HHC editeng::HangulHanjaConversion
#define LINE_CNT        static_cast< sal_uInt16 >(2)
#define MAXNUM_SUGGESTIONS 50


namespace svx
{

    using namespace ::com::sun::star;
    using namespace css::uno;
    using namespace css::linguistic2;
    using namespace css::lang;
    using namespace css::container;


    namespace
    {
        class FontSwitch
        {
        private:
            OutputDevice& m_rDev;

        public:
            FontSwitch( OutputDevice& _rDev, const vcl::Font& _rTemporaryFont )
                :m_rDev( _rDev )
            {
                m_rDev.Push( vcl::PushFlags::FONT );
                m_rDev.SetFont( _rTemporaryFont );
            }
            ~FontSwitch() COVERITY_NOEXCEPT_FALSE
            {
                m_rDev.Pop();
            }
        };

    /** 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:
        OUString      m_sPrimaryText;
        OUString      m_sSecondaryText;
        RubyPosition  m_ePosition;

    public:
        PseudoRubyText();
        void init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition );
        const OUString& getPrimaryText() const { return m_sPrimaryText; }
        const OUString& getSecondaryText() const { return m_sSecondaryText; }

    public:
        void Paint( vcl::RenderContext& _rDevice, const ::tools::Rectangle& _rRect,
            ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation );
    };

    }

    PseudoRubyText::PseudoRubyText()
        : m_ePosition(eAbove)
    {
    }

    void PseudoRubyText::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition )
    {
        m_sPrimaryText = rPrimaryText;
        m_sSecondaryText = rSecondaryText;
        m_ePosition = rPosition;
    }


    void PseudoRubyText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& _rRect,
                               ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation )
    {
        // calculate the text flags for the painting
        constexpr DrawTextFlags nTextStyle = DrawTextFlags::Mnemonic |
                                   DrawTextFlags::Left |
                                   DrawTextFlags::VCenter;

        Size aPlaygroundSize(_rRect.GetSize());

        // the font for the secondary text:
        vcl::Font aSmallerFont(rRenderContext.GetFont());
        // heuristic: 80% of the original size
        aSmallerFont.SetFontHeight( static_cast<tools::Long>( 0.8 * aSmallerFont.GetFontHeight() ) );

        // let's calculate the size of our two texts
        ::tools::Rectangle aPrimaryRect = rRenderContext.GetTextRect( _rRect, m_sPrimaryText, nTextStyle );
        ::tools::Rectangle aSecondaryRect;
        {
            FontSwitch aFontRestore(rRenderContext, aSmallerFont);
            aSecondaryRect = rRenderContext.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.SetLeft( _rRect.Left() );
        aSecondaryRect.SetLeft( aPrimaryRect.Left() );
        aPrimaryRect.SetRight( _rRect.Left() + nCombinedWidth );
        aSecondaryRect.SetRight( aPrimaryRect.Right() );

        // 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() );
        // 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 its rect, every text is centered
        DrawTextFlags nDrawTextStyle( nTextStyle );
        nDrawTextStyle &= ~DrawTextFlags( DrawTextFlags::Right | DrawTextFlags::Left | DrawTextFlags::Bottom | DrawTextFlags::Top );
        nDrawTextStyle |= DrawTextFlags::Center | DrawTextFlags::VCenter;

        rRenderContext.DrawText( aPrimaryRect, m_sPrimaryText, nDrawTextStyle );
        {
            FontSwitch aFontRestore(rRenderContext, aSmallerFont);
            rRenderContext.DrawText( aSecondaryRect, m_sSecondaryText, nDrawTextStyle );
        }

        // outta here
        if (_pPrimaryLocation)
            *_pPrimaryLocation = aPrimaryRect;
        if (_pSecondaryLocation)
            *_pSecondaryLocation = aSecondaryRect;
    }

    class RubyRadioButton
    {
    public:
        RubyRadioButton(std::unique_ptr<weld::RadioButton> xControl, std::unique_ptr<weld::Image> xImage);
        void init(const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition);

        void set_sensitive(bool sensitive)
        {
            m_xControl->set_sensitive(sensitive);
            m_xImage->set_sensitive(sensitive);
        }
        void set_active(bool active) { m_xControl->set_active(active); }
        bool get_active() const { return m_xControl->get_active(); }

        void connect_toggled(const Link<weld::Toggleable&, void>& rLink) { m_xControl->connect_toggled(rLink); }

    private:
        Size GetOptimalSize() const;
        void Paint(vcl::RenderContext& rRenderContext);

        ScopedVclPtr<VirtualDevice> m_xVirDev;
        std::unique_ptr<weld::RadioButton> m_xControl;
        std::unique_ptr<weld::Image> m_xImage;
        PseudoRubyText m_aRubyText;
    };

    RubyRadioButton::RubyRadioButton(std::unique_ptr<weld::RadioButton> xControl, std::unique_ptr<weld::Image> xImage)
        : m_xVirDev(xControl->create_virtual_device())
        , m_xControl(std::move(xControl))
        , m_xImage(std::move(xImage))
    {
        // expand the point size of the desired font to the equivalent pixel size
        weld::SetPointFont(*m_xVirDev, m_xControl->get_font());
    }

    void RubyRadioButton::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition )
    {
        m_aRubyText.init(rPrimaryText, rSecondaryText, rPosition);

        m_xVirDev->SetOutputSizePixel(GetOptimalSize());

        Paint(*m_xVirDev);

        m_xImage->set_image(m_xVirDev.get());
    }

    void RubyRadioButton::Paint(vcl::RenderContext& rRenderContext)
    {
        ::tools::Rectangle aOverallRect(Point(0, 0), rRenderContext.GetOutputSizePixel());
        // inflate the rect a little bit (because the VCL radio button does the same)
        ::tools::Rectangle aTextRect( aOverallRect );
        aTextRect.AdjustLeft( 1 ); aTextRect.AdjustRight( -1 );
        aTextRect.AdjustTop( 1 ); aTextRect.AdjustBottom( -1 );

        // paint the ruby text
        ::tools::Rectangle aPrimaryTextLocation;
        ::tools::Rectangle aSecondaryTextLocation;

        m_aRubyText.Paint(rRenderContext, aTextRect, &aPrimaryTextLocation, &aSecondaryTextLocation);
    }

    Size RubyRadioButton::GetOptimalSize() const
    {
        vcl::Font aSmallerFont(m_xVirDev->GetFont());
        aSmallerFont.SetFontHeight( static_cast<tools::Long>( 0.8 * aSmallerFont.GetFontHeight() ) );
        ::tools::Rectangle rect( Point(), Size( SAL_MAX_INT32, SAL_MAX_INT32 ) );

        Size aPrimarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getPrimaryText() ).GetSize();
        Size aSecondarySize;
        {
            FontSwitch aFontRestore(*m_xVirDev, aSmallerFont);
            aSecondarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getSecondaryText() ).GetSize();
        }

        Size minimumSize;
        minimumSize.setHeight( aPrimarySize.Height() + aSecondarySize.Height() + 5 );
        minimumSize.setWidth(std::max(aPrimarySize.Width(), aSecondarySize.Width()) + 5 );
        return minimumSize;
    }

    SuggestionSet::SuggestionSet(std::unique_ptr<weld::ScrolledWindow> xScrolledWindow)
        : ValueSet(std::move(xScrolledWindow))

    {
    }

    void SuggestionSet::UserDraw( const UserDrawEvent& rUDEvt )
    {
        vcl::RenderContext* pDev = rUDEvt.GetRenderContext();
        ::tools::Rectangle aRect = rUDEvt.GetRect();
        sal_uInt16  nItemId = rUDEvt.GetItemId();

        OUString sText = *static_cast< OUString* >( GetItemData( nItemId ) );
        pDev->DrawText( aRect, sText, DrawTextFlags::Center | DrawTextFlags::VCenter );
    }

    SuggestionDisplay::SuggestionDisplay(weld::Builder& rBuilder)
        : m_bDisplayListBox( true )
        , m_bInSelectionUpdate( false )
        , m_xValueSet(new SuggestionSet(rBuilder.weld_scrolled_window(u"scrollwin"_ustr, true)))
        , m_xValueSetWin(new weld::CustomWeld(rBuilder, u"valueset"_ustr, *m_xValueSet))
        , m_xListBox(rBuilder.weld_tree_view(u"listbox"_ustr))
    {
        m_xValueSet->SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionValueSetHdl ) );
        m_xListBox->connect_selection_changed(
            LINK(this, SuggestionDisplay, SelectSuggestionListBoxHdl));

        m_xValueSet->SetLineCount( LINE_CNT );
        m_xValueSet->SetStyle( m_xValueSet->GetStyle() | WB_ITEMBORDER | WB_VSCROLL );

        auto nItemWidth = 2 * m_xListBox->get_pixel_size(u"AU"_ustr).Width();
        m_xValueSet->SetItemWidth( nItemWidth );

        Size aSize(m_xListBox->get_approximate_digit_width() * 42, m_xListBox->get_text_height() * 5);
        m_xValueSet->set_size_request(aSize.Width(), aSize.Height());
        m_xListBox->set_size_request(aSize.Width(), aSize.Height());

        implUpdateDisplay();
    }

    void SuggestionDisplay::implUpdateDisplay()
    {
        m_xListBox->set_visible(m_bDisplayListBox);
        if (!m_bDisplayListBox)
            m_xValueSetWin->show();
        else
            m_xValueSetWin->hide();
    }

    weld::Widget& SuggestionDisplay::implGetCurrentControl()
    {
        if (m_bDisplayListBox)
            return *m_xListBox;
        return *m_xValueSet->GetDrawingArea();
    }

    void SuggestionDisplay::DisplayListBox( bool bDisplayListBox )
    {
        if( m_bDisplayListBox == bDisplayListBox )
            return;

        weld::Widget& rOldControl = implGetCurrentControl();
        bool bHasFocus = rOldControl.has_focus();

        m_bDisplayListBox = bDisplayListBox;

        if( bHasFocus )
        {
            weld::Widget& rNewControl = implGetCurrentControl();
            rNewControl.grab_focus();
        }

        implUpdateDisplay();
    }

    IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionValueSetHdl, ValueSet*, void)
    {
        SelectSuggestionHdl(false);
    }

    IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionListBoxHdl, weld::TreeView&, void)
    {
        SelectSuggestionHdl(true);
    }

    void SuggestionDisplay::SelectSuggestionHdl(bool bListBox)
    {
        if( m_bInSelectionUpdate )
            return;

        m_bInSelectionUpdate = true;
        if (bListBox)
        {
            sal_uInt16 nPos = m_xListBox->get_selected_index();
            m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
        }
        else
        {
            sal_uInt16 nPos = m_xValueSet->GetSelectedItemId()-1; //itemid == pos+1 (id 0 has special meaning)
            m_xListBox->select(nPos);
        }
        m_bInSelectionUpdate = false;
        m_aSelectLink.Call( *this );
    }

    void SuggestionDisplay::SetSelectHdl( const Link<SuggestionDisplay&,void>& rLink )
    {
        m_aSelectLink = rLink;
    }

    void SuggestionDisplay::Clear()
    {
        m_xListBox->clear();
        m_xValueSet->Clear();
    }

    void SuggestionDisplay::InsertEntry( const OUString& rStr )
    {
        m_xListBox->append_text(rStr);
        sal_uInt16 nItemId = m_xListBox->n_children(); //itemid == pos+1 (id 0 has special meaning)
        m_xValueSet->InsertItem( nItemId );
        OUString* pItemData = new OUString( rStr );
        m_xValueSet->SetItemData( nItemId, pItemData );
    }

    void SuggestionDisplay::SelectEntryPos( sal_uInt16 nPos )
    {
        m_xListBox->select(nPos);
        m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
    }

    sal_uInt16 SuggestionDisplay::GetEntryCount() const
    {
        return m_xListBox->n_children();
    }

    OUString SuggestionDisplay::GetEntry( sal_uInt16 nPos ) const
    {
        return m_xListBox->get_text( nPos );
    }

    OUString SuggestionDisplay::GetSelectedEntry() const
    {
        return m_xListBox->get_selected_text();
    }

    void SuggestionDisplay::SetHelpIds()
    {
        m_xValueSet->SetHelpId(HID_HANGULDLG_SUGGESTIONS_GRID);
        m_xListBox->set_help_id(HID_HANGULDLG_SUGGESTIONS_LIST);
    }

    HangulHanjaConversionDialog::HangulHanjaConversionDialog(weld::Widget* pParent)
        : GenericDialogController(pParent, u"cui/ui/hangulhanjaconversiondialog.ui"_ustr, u"HangulHanjaConversionDialog"_ustr)
        , m_bDocumentMode( true )
        , m_xFind(m_xBuilder->weld_button(u"find"_ustr))
        , m_xIgnore(m_xBuilder->weld_button(u"ignore"_ustr))
        , m_xIgnoreAll(m_xBuilder->weld_button(u"ignoreall"_ustr))
        , m_xReplace(m_xBuilder->weld_button(u"replace"_ustr))
        , m_xReplaceAll(m_xBuilder->weld_button(u"replaceall"_ustr))
        , m_xOptions(m_xBuilder->weld_button(u"options"_ustr))
        , m_xSuggestions(new SuggestionDisplay(*m_xBuilder))
        , m_xSimpleConversion(m_xBuilder->weld_radio_button(u"simpleconversion"_ustr))
        , m_xHangulBracketed(m_xBuilder->weld_radio_button(u"hangulbracket"_ustr))
        , m_xHanjaBracketed(m_xBuilder->weld_radio_button(u"hanjabracket"_ustr))
        , m_xWordInput(m_xBuilder->weld_entry(u"wordinput"_ustr))
        , m_xOriginalWord(m_xBuilder->weld_label(u"originalword"_ustr))
        , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hanja_above"_ustr),
                                            m_xBuilder->weld_image(u"hanja_above_img"_ustr)))
        , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hanja_below"_ustr),
                                            m_xBuilder->weld_image(u"hanja_below_img"_ustr)))
        , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hangul_above"_ustr),
                                             m_xBuilder->weld_image(u"hangul_above_img"_ustr)))
        , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hangul_below"_ustr),
                                             m_xBuilder->weld_image(u"hangul_below_img"_ustr)))
        , m_xHangulOnly(m_xBuilder->weld_check_button(u"hangulonly"_ustr))
        , m_xHanjaOnly(m_xBuilder->weld_check_button(u"hanjaonly"_ustr))
        , m_xReplaceByChar(m_xBuilder->weld_check_button(u"replacebychar"_ustr))
    {
        m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42,
                                         m_xOriginalWord->get_text_height() * 5);

        const OUString sHangul(CuiResId(RID_CUISTR_HANGUL));
        const OUString sHanja(CuiResId(RID_CUISTR_HANJA));
        m_xHanjaAbove->init( sHangul, sHanja, PseudoRubyText::eAbove );
        m_xHanjaBelow->init( sHangul, sHanja, PseudoRubyText::eBelow );
        m_xHangulAbove->init( sHanja, sHangul, PseudoRubyText::eAbove );
        m_xHangulBelow->init( sHanja, sHangul, PseudoRubyText::eBelow );

        m_xWordInput->connect_changed( LINK( this,  HangulHanjaConversionDialog, OnSuggestionModified ) );
        m_xSuggestions->SetSelectHdl( LINK( this,  HangulHanjaConversionDialog, OnSuggestionSelected ) );
        m_xReplaceByChar->connect_toggled( LINK( this, HangulHanjaConversionDialog, ClickByCharacterHdl ) );
        m_xHangulOnly->connect_toggled( LINK( this,  HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
        m_xHanjaOnly->connect_toggled(  LINK( this,  HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
        m_xOptions->connect_clicked(LINK(this, HangulHanjaConversionDialog, OnOption));

        // initial focus
        FocusSuggestion( );

        // initial control values
        m_xSimpleConversion->set_active(true);

        m_xSuggestions->SetHelpIds();
    }

    HangulHanjaConversionDialog::~HangulHanjaConversionDialog()
    {
    }

    void HangulHanjaConversionDialog::FillSuggestions( const css::uno::Sequence< OUString >&&nbsp;_rSuggestions )
    {
        m_xSuggestions->Clear();
        for ( auto const & suggestion : _rSuggestions )
            m_xSuggestions->InsertEntry( suggestion );

        // select the first suggestion, and fill in the suggestion edit field
        OUString sFirstSuggestion;
        if ( m_xSuggestions->GetEntryCount() )
        {
            sFirstSuggestion = m_xSuggestions->GetEntry( 0 );
            m_xSuggestions->SelectEntryPos( 0 );
        }
        m_xWordInput->set_text( sFirstSuggestion );
        m_xWordInput->save_value();
        OnSuggestionModified( *m_xWordInput );
    }

    void HangulHanjaConversionDialog::SetOptionsChangedHdl(const Link<LinkParamNone*,void>& rHdl)
    {
        m_aOptionsChangedLink = rHdl;
    }

    void HangulHanjaConversionDialog::SetIgnoreHdl(const Link<weld::Button&,void>& rHdl)
    {
        m_xIgnore->connect_clicked(rHdl);
    }

    void HangulHanjaConversionDialog::SetIgnoreAllHdl(const Link<weld::Button&,='color:red'>void>& rHdl)
    {
        m_xIgnoreAll->connect_clicked(rHdl);
    }

    void HangulHanjaConversionDialog::SetChangeHdl(const Link<weld::Button&,void>& rHdl )
    {
        m_xReplace->connect_clicked(rHdl);
    }

    void HangulHanjaConversionDialog::SetChangeAllHdl(const Link<weld::Button&,='color:red'>void>& rHdl)
    {
        m_xReplaceAll->connect_clicked(rHdl);
    }

    void HangulHanjaConversionDialog::SetFindHdl(const Link<weld::Button&,void>& rHdl)
    {
        m_xFind->connect_clicked(rHdl);
    }

    void HangulHanjaConversionDialog::SetConversionFormatChangedHdl( const Link<weld::Toggleable&,void>& rHdl )
    {
        m_xSimpleConversion->connect_toggled( rHdl );
        m_xHangulBracketed->connect_toggled( rHdl );
        m_xHanjaBracketed->connect_toggled( rHdl );
        m_xHanjaAbove->connect_toggled( rHdl );
        m_xHanjaBelow->connect_toggled( rHdl );
        m_xHangulAbove->connect_toggled( rHdl );
        m_xHangulBelow->connect_toggled( rHdl );
    }

    void HangulHanjaConversionDialog::SetClickByCharacterHdl( const Link<weld::Toggleable&,void>& _rHdl )
    {
        m_aClickByCharacterLink = _rHdl;
    }

    IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionSelected, SuggestionDisplay&, void )
    {
        m_xWordInput->set_text(m_xSuggestions->GetSelectedEntry());
        OnSuggestionModified( *m_xWordInput );
    }

    IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionModified, weld::Entry&, ;void )
    {
        m_xFind->set_sensitive(m_xWordInput->get_value_changed_from_saved());

        bool bSameLen = m_xWordInput->get_text().getLength() == m_xOriginalWord->get_label().getLength();
        m_xReplace->set_sensitive( m_bDocumentMode && bSameLen );
        m_xReplaceAll->set_sensitive( m_bDocumentMode && bSameLen );
    }

    IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::Toggleable&, rBox, void)
    {
        m_aClickByCharacterLink.Call(rBox);
        bool bByCharacter = rBox.get_active();
        m_xSuggestions->DisplayListBox( !bByCharacter );
    }

    IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::Toggleable&, rBox, void)
    {
        weld::CheckButton* pOtherBox = nullptr;
        if (&rBox == m_xHangulOnly.get())
            pOtherBox = m_xHanjaOnly.get();
        else
            pOtherBox = m_xHangulOnly.get();
        bool bBoxChecked = rBox.get_active();
        if (bBoxChecked)
            pOtherBox->set_active(false);
        pOtherBox->set_sensitive(!bBoxChecked);
    }

    IMPL_LINK_NOARG(HangulHanjaConversionDialog, OnOption, weld::Button&, void)
    {
        HangulHanjaOptionsDialog aOptDlg(m_xDialog.get());
        aOptDlg.run();
        m_aOptionsChangedLink.Call( nullptr );
    }

    OUString HangulHanjaConversionDialog::GetCurrentString( ) const
    {
        return m_xOriginalWord->get_label();
    }

    void HangulHanjaConversionDialog::FocusSuggestion( )
    {
        m_xWordInput->grab_focus();
    }

    void HangulHanjaConversionDialog::SetCurrentString( const OUString& _rNewString,
        const Sequence< OUString >& _rSuggestions, bool _bOriginatesFromDocument )
    {
        m_xOriginalWord->set_label(_rNewString);

        bool bOldDocumentMode = m_bDocumentMode;
        m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions!
        FillSuggestions( _rSuggestions );

        m_xIgnoreAll->set_sensitive( m_bDocumentMode );

        // switch the def button depending if we're working for document text
        if (bOldDocumentMode == m_bDocumentMode)
            return;

        weld::Widget* pOldDefButton = nullptr;
        weld::Widget* pNewDefButton = nullptr;
        if (m_bDocumentMode)
        {
            pOldDefButton = m_xFind.get();
            pNewDefButton = m_xReplace.get();
        }
        else
        {
            pOldDefButton = m_xReplace.get();
            pNewDefButton = m_xFind.get();
        }

        m_xDialog->change_default_widget(pOldDefButton, pNewDefButton);
    }

    OUString HangulHanjaConversionDialog::GetCurrentSuggestion( ) const
    {
        return m_xWordInput->get_text();
    }

    void HangulHanjaConversionDialog::SetByCharacter( bool _bByCharacter )
    {
        m_xReplaceByChar->set_active( _bByCharacter );
        m_xSuggestions->DisplayListBox( !_bByCharacter );
    }

    void HangulHanjaConversionDialog::SetConversionDirectionState(
            bool _bTryBothDirections,
            HHC::ConversionDirection ePrimaryConversionDirection )
    {
        // default state: try both direction
        m_xHangulOnly->set_active( false );
        m_xHangulOnly->set_sensitive(true);
        m_xHanjaOnly->set_active( false );
        m_xHanjaOnly->set_sensitive(true);

        if (!_bTryBothDirections)
        {
            weld::CheckButton* pBox = ePrimaryConversionDirection == HHC::eHangulToHanja ?
                                    m_xHangulOnly.get() : m_xHanjaOnly.get();
            pBox->set_active(true);
            OnConversionDirectionClicked(*pBox);
        }
    }

    bool HangulHanjaConversionDialog::GetUseBothDirections( ) const
    {
        return !m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active();
    }

    HHC::ConversionDirection HangulHanjaConversionDialog::GetDirection(
            HHC::ConversionDirection eDefaultDirection ) const
    {
        HHC::ConversionDirection eDirection = eDefaultDirection;
        if (m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active())
            eDirection = HHC::eHangulToHanja;
        else if (!m_xHangulOnly->get_active() && m_xHanjaOnly->get_active())
            eDirection = HHC::eHanjaToHangul;
        return eDirection;
    }

    void HangulHanjaConversionDialog::SetConversionFormat( HHC::ConversionFormat _eType )
    {
        switch ( _eType )
        {
            case HHC::eSimpleConversion: m_xSimpleConversion->set_active(true); break;
            case HHC::eHangulBracketed: m_xHangulBracketed->set_active(true); break;
            case HHC::eHanjaBracketed:  m_xHanjaBracketed->set_active(true); break;
            case HHC::eRubyHanjaAbove:  m_xHanjaAbove->set_active(true); break;
            case HHC::eRubyHanjaBelow:  m_xHanjaBelow->set_active(true); break;
            case HHC::eRubyHangulAbove: m_xHangulAbove->set_active(true); break;
            case HHC::eRubyHangulBelow: m_xHangulBelow->set_active(true); break;
        default:
            OSL_FAIL( "HangulHanjaConversionDialog::SetConversionFormat: unknown type!" );
        }
    }

    HHC::ConversionFormat HangulHanjaConversionDialog::GetConversionFormat( ) const
    {
        if ( m_xSimpleConversion->get_active() )
            return HHC::eSimpleConversion;
        if ( m_xHangulBracketed->get_active() )
            return HHC::eHangulBracketed;
        if ( m_xHanjaBracketed->get_active() )
            return HHC::eHanjaBracketed;
        if ( m_xHanjaAbove->get_active() )
            return HHC::eRubyHanjaAbove;
        if ( m_xHanjaBelow->get_active() )
            return HHC::eRubyHanjaBelow;
        if ( m_xHangulAbove->get_active() )
            return HHC::eRubyHangulAbove;
        if ( m_xHangulBelow->get_active() )
            return HHC::eRubyHangulBelow;

        OSL_FAIL( "HangulHanjaConversionDialog::GetConversionFormat: no radio checked?" );
        return HHC::eSimpleConversion;
    }

    void HangulHanjaConversionDialog::EnableRubySupport( bool bVal )
    {
        m_xHanjaAbove->set_sensitive( bVal );
        m_xHanjaBelow->set_sensitive( bVal );
        m_xHangulAbove->set_sensitive( bVal );
        m_xHangulBelow->set_sensitive( bVal );
    }

    void HangulHanjaOptionsDialog::Init()
    {
        if( !m_xConversionDictionaryList.is() )
        {
            m_xConversionDictionaryList = ConversionDictionaryList::create( ::comphelper::getProcessComponentContext() );
        }

        m_aDictList.clear();
        m_xDictsLB->clear();

        Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
        if( xNameCont.is() )
        {
            for (auto& name : xNameCont->getElementNames())
            {
                Any aAny(xNameCont->getByName(name));
                Reference< XConversionDictionary >  xDic;
                if( ( aAny >>= xDic ) && xDic.is() )
                {
                    if( LANGUAGE_KOREAN == LanguageTag( xDic->getLocale() ).getLanguageType() )
                    {
                        m_aDictList.push_back( xDic );
                        AddDict( xDic->getName(), xDic->isActive() );
                    }
                }
            }
        }
        if (m_xDictsLB->n_children())
            m_xDictsLB->select(0);
    }

    IMPL_LINK_NOARG(HangulHanjaOptionsDialog, OkHdl, weld::Button&, void)
    {
        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 ];

            DBG_ASSERT( xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..." );

            bool bActive = m_xDictsLB->get_toggle(n) == TRISTATE_TRUE;
            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 <<= m_xIgnorepostCB->get_active();
        aLngCfg.SetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD, aTmp );

        aTmp <<= m_xShowrecentlyfirstCB->get_active();
        aLngCfg.SetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, aTmp );

        aTmp <<= m_xAutoreplaceuniqueCB->get_active();
        aLngCfg.SetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES, aTmp );

        m_xDialog->response(RET_OK);
    }

    IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DictsLB_SelectHdl, weld::TreeView&, void)
    {
        bool bSel = m_xDictsLB->get_selected_index() != -1;

        m_xEditPB->set_sensitive(bSel);
        m_xDeletePB->set_sensitive(bSel);
    }

    IMPL_LINK_NOARG(HangulHanjaOptionsDialog, NewDictHdl, weld::Button&, void)
    {
        OUString                    aName;
        HangulHanjaNewDictDialog aNewDlg(m_xDialog.get());
        aNewDlg.run();
        if (!aNewDlg.GetName(aName))
            return;

        if( !m_xConversionDictionaryList.is() )
            return;

        try
        {
            Reference< XConversionDictionary >  xDic =
                m_xConversionDictionaryList->addNewDictionary( aName, LanguageTag::convertToLocale( LANGUAGE_KOREAN ), ConversionDictionaryType::HANGUL_HANJA );

            if( xDic.is() )
            {
                //adapt local caches:
                m_aDictList.push_back( xDic );
                AddDict( xDic->getName(), xDic->isActive() );
            }
        }
        catchconst ElementExistException& )
        {
        }
        catchconst NoSupportException& )
        {
        }
    }

    IMPL_LINK_NOARG(HangulHanjaOptionsDialog, EditDictHdl, weld::Button&, void)
    {
        int nEntry = m_xDictsLB->get_selected_index();
        DBG_ASSERT(nEntry != -1, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not be possible with no selection!");
        if (nEntry != -1)
        {
            HangulHanjaEditDictDialog aEdDlg(m_xDialog.get(), m_aDictList, nEntry);
            aEdDlg.run();
        }
    }

    IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DeleteDictHdl, weld::Button&, void)
    {
        int nSelPos = m_xDictsLB->get_selected_index();
        if (nSelPos == -1)
            return;

        Reference< XConversionDictionary >  xDic( m_aDictList[ nSelPos ] );
        if( !(m_xConversionDictionaryList.is() && xDic.is()) )
            return;

        Reference< XNameContainer >     xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
        if( !xNameCont.is() )
            return;

        try
        {
            xNameCont->removeByName( xDic->getName() );

            //adapt local caches:
            m_aDictList.erase(m_aDictList.begin()+nSelPos );
            m_xDictsLB->remove(nSelPos);
        }
        catchconst ElementExistException& )
        {
        }
        catchconst NoSupportException& )
        {
        }
    }

    HangulHanjaOptionsDialog::HangulHanjaOptionsDialog(weld::Window* pParent)
        : GenericDialogController(pParent, u"cui/ui/hangulhanjaoptdialog.ui"_ustr, u"HangulHanjaOptDialog"_ustr)
        , m_xDictsLB(m_xBuilder->weld_tree_view(u"dicts"_ustr))
        , m_xIgnorepostCB(m_xBuilder->weld_check_button(u"ignorepost"_ustr))
        , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button(u"showrecentfirst"_ustr))
        , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button(u"autoreplaceunique"_ustr))
        , m_xNewPB(m_xBuilder->weld_button(u"new"_ustr))
        , m_xEditPB(m_xBuilder->weld_button(u"edit"_ustr))
        , m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr))
        , m_xOkPB(m_xBuilder->weld_button(u"ok"_ustr))
    {
        m_xDictsLB->set_size_request(m_xDictsLB->get_approximate_digit_width() * 32,
                                     m_xDictsLB->get_height_rows(5));

        m_xDictsLB->enable_toggle_buttons(weld::ColumnToggleType::Check);

        m_xDictsLB->connect_selection_changed(
            LINK(this, HangulHanjaOptionsDialog, DictsLB_SelectHdl));

        m_xOkPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, OkHdl ) );
        m_xNewPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, NewDictHdl ) );
        m_xEditPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, EditDictHdl ) );
        m_xDeletePB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, DeleteDictHdl ) );

        SvtLinguConfig  aLngCfg;
        Any             aTmp;
        bool            bVal = bool();
        aTmp = aLngCfg.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD );
        if( aTmp >>= bVal )
            m_xIgnorepostCB->set_active( bVal );

        aTmp = aLngCfg.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST );
        if( aTmp >>= bVal )
            m_xShowrecentlyfirstCB->set_active( bVal );

        aTmp = aLngCfg.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES );
        if( aTmp >>= bVal )
            m_xAutoreplaceuniqueCB->set_active( bVal );

        Init();
    }

    HangulHanjaOptionsDialog::~HangulHanjaOptionsDialog()
    {
    }

    void HangulHanjaOptionsDialog::AddDict(const OUString& rName, bool bChecked)
    {
        m_xDictsLB->append();
        int nRow = m_xDictsLB->n_children() - 1;
        m_xDictsLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
        m_xDictsLB->set_text(nRow, rName, 0);
        m_xDictsLB->set_id(nRow, rName);
    }

    IMPL_LINK_NOARG(HangulHanjaNewDictDialog, OKHdl, weld::Button&, void)
    {
        OUString  aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));

        m_bEntered = !aName.isEmpty();
        if (m_bEntered)
            m_xDictNameED->set_text(aName);     // do this in case of trailing chars have been deleted

        m_xDialog->response(RET_OK);
    }

    IMPL_LINK_NOARG(HangulHanjaNewDictDialog, ModifyHdl, weld::Entry&, void)
    {
        OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));

        m_xOkBtn->set_sensitive(!aName.isEmpty());
    }

    HangulHanjaNewDictDialog::HangulHanjaNewDictDialog(weld::Window* pParent)
        : GenericDialogController(pParent, u"cui/ui/hangulhanjaadddialog.ui"_ustr, u"HangulHanjaAddDialog"_ustr)
        , m_bEntered(false)
        , m_xOkBtn(m_xBuilder->weld_button(u"ok"_ustr))
        , m_xDictNameED(m_xBuilder->weld_entry(u"entry"_ustr))
    {
        m_xOkBtn->connect_clicked( LINK( this, HangulHanjaNewDictDialog, OKHdl ) );
        m_xDictNameED->connect_changed( LINK( this, HangulHanjaNewDictDialog, ModifyHdl ) );
    }

    HangulHanjaNewDictDialog::~HangulHanjaNewDictDialog()
    {
    }

    bool HangulHanjaNewDictDialog::GetName( OUString& _rRetName ) const
    {
        if( m_bEntered )
            _rRetName = comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ');

        return m_bEntered;
    }

    class SuggestionList
    {
    private:
    protected:
        std::vector<OUString> m_vElements;
        sal_uInt16          m_nNumOfEntries;
        // index of the internal iterator, used for First() and Next() methods
        sal_uInt16          m_nAct;

        const OUString*       Next_();
    public:
                            SuggestionList();
                            ~SuggestionList();

        void                Set( const OUString& _rElement, sal_uInt16 _nNumOfElement );
        void                Reset( sal_uInt16 _nNumOfElement );
        const OUString &    Get( sal_uInt16 _nNumOfElement ) const;
        void                Clear();

        const OUString*     First();
        const OUString*     Next();

        sal_uInt16   GetCount() const { return m_nNumOfEntries; }
    };

    SuggestionList::SuggestionList() :
        m_vElements(MAXNUM_SUGGESTIONS)
    {
        m_nAct = m_nNumOfEntries = 0;
    }

    SuggestionList::~SuggestionList()
    {
        Clear();
    }

    void SuggestionList::Set( const OUString& _rElement, sal_uInt16 _nNumOfElement )
    {
        m_vElements[_nNumOfElement] = _rElement;
        ++m_nNumOfEntries;
    }

    void SuggestionList::Reset( sal_uInt16 _nNumOfElement )
    {
        m_vElements[_nNumOfElement].clear();
        --m_nNumOfEntries;
    }

    const OUString& SuggestionList::Get( sal_uInt16 _nNumOfElement ) const
    {
        return m_vElements[_nNumOfElement];
    }

    void SuggestionList::Clear()
    {
        if( m_nNumOfEntries )
        {
            for (auto & vElement : m_vElements)
                vElement.clear();
            m_nNumOfEntries = m_nAct = 0;
        }
    }

    const OUString* SuggestionList::Next_()
    {
        while( m_nAct < m_vElements.size() )
        {
            auto & s = m_vElements[ m_nAct ];
            if (!s.isEmpty())
                return &s;
            ++m_nAct;
        }

        return nullptr;
    }

    const OUString* SuggestionList::First()
    {
        m_nAct = 0;
        return Next_();
    }

    const OUString* SuggestionList::Next()
    {
        const OUString*   pRet;

        if( m_nAct < m_nNumOfEntries )
        {
            ++m_nAct;
            pRet = Next_();
        }
        else
            pRet = nullptr;

        return pRet;
    }


    bool SuggestionEdit::ShouldScroll( bool _bUp ) const
    {
        bool    bRet = false;

        if( _bUp )
        {
            if( !m_pPrev )
                bRet = m_pScrollBar->vadjustment_get_value() > m_pScrollBar->vadjustment_get_lower();
        }
        else
        {
            if( !m_pNext )
                bRet = m_pScrollBar->vadjustment_get_value() < ( m_pScrollBar->vadjustment_get_upper() - 4 );
        }

        return bRet;
    }

    void SuggestionEdit::DoJump( bool _bUp )
    {
        m_pScrollBar->vadjustment_set_value( m_pScrollBar->vadjustment_get_value() + ( _bUp? -1 : 1 ) );
        m_pParent->UpdateScrollbar();
    }

    SuggestionEdit::SuggestionEdit(std::unique_ptr<weld::Entry> xEntry, HangulHanjaEditDictDialog* pParent)
        : m_pParent(pParent)
        , m_pPrev(nullptr)
        , m_pNext(nullptr)
        , m_pScrollBar(nullptr)
        , m_xEntry(std::move(xEntry))
    {
        m_xEntry->connect_key_press(LINK(this, SuggestionEdit, KeyInputHdl));
    }

    IMPL_LINK(SuggestionEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
    {
        bool bHandled = false;

        const vcl::KeyCode& rKeyCode = rKEvt.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 );
                m_xEntry->select_region(0, -1);
                    // Tab-travel doesn't really happen, so emulate it by setting a selection manually
                bHandled = true;
            }
        }
        else if( KEY_UP == nCode || KEY_DOWN == nCode )
        {
            bool        bUp = KEY_UP == nCode;
            if( ShouldScroll( bUp ) )
            {
                DoJump( bUp );
                bHandled = true;
            }
            else if( bUp )
            {
                if( m_pPrev )
                {
                    m_pPrev->grab_focus();
                    bHandled = true;
                }
            }
            else if( m_pNext )
            {
                m_pNext->grab_focus();
                bHandled = true;
            }
        }

        return bHandled;
    }

    void SuggestionEdit::init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, SuggestionEdit* pNext)
    {
        m_pScrollBar = pScrollBar;
        m_pPrev = pPrev;
        m_pNext = pNext;
    }

    namespace
    {
        bool GetConversions(    const Reference< XConversionDictionary >&  _xDict,
                                const OUString& _rOrg,
                                Sequence< OUString >& _rEntries )
        {
            bool    bRet = false;
            if( _xDict.is() && !_rOrg.isEmpty() )
            {
                try
                {
                    _rEntries = _xDict->getConversions( _rOrg,
                                                        0,
                                                        _rOrg.getLength(),
                                                        ConversionDirection_FROM_LEFT,
                                                        css::i18n::TextConversionOption::NONE );
                    bRet = _rEntries.hasElements();
                }
                catchconst IllegalArgumentException& )
                {
                }
            }

            return bRet;
        }
    }

    IMPL_LINK_NOARG( HangulHanjaEditDictDialog, ScrollHdl, weld::ScrolledWindow&, void )
    {
        UpdateScrollbar();
    }

    IMPL_LINK_NOARG( HangulHanjaEditDictDialog, OriginalModifyHdl, weld::ComboBox&, void )
    {
        m_bModifiedOriginal = true;
        m_aOriginal = comphelper::string::stripEnd( m_xOriginalLB->get_active_text(), ' ' );

        UpdateSuggestions();
        UpdateButtonStates();
    }

    IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl1, weld::Entry&, rEdit, void )
    {
        EditModify( &rEdit, 0 );
    }

    IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl2, weld::Entry&, rEdit, void )
    {
        EditModify( &rEdit, 1 );
    }

    IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl3, weld::Entry&, rEdit, void )
    {
        EditModify( &rEdit, 2 );
    }

    IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl4, weld::Entry&, rEdit, void )
    {
        EditModify( &rEdit, 3 );
    }

    IMPL_LINK_NOARG( HangulHanjaEditDictDialog, BookLBSelectHdl, weld::ComboBox&, void )
    {
        InitEditDictDialog( m_xBookLB->get_active() );
    }

    IMPL_LINK_NOARG( HangulHanjaEditDictDialog, NewPBPushHdl, weld::Button&, void )
    {
        DBG_ASSERT( m_xSuggestions, "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..." );
        Reference< XConversionDictionary >  xDict = m_rDictList[ m_nCurrentDict ];
        if( xDict.is() && m_xSuggestions )
        {
            //delete old entry
            bool bRemovedSomething = DeleteEntryFromDictionary( xDict );

            OUString                aLeft( m_aOriginal );
            const OUString*           pRight = m_xSuggestions->First();
            bool bAddedSomething = false;
            while( pRight )
            {
                try
                {
                    //add new entry
                    xDict->addEntry( aLeft, *pRight );
                    bAddedSomething = true;
                }
                catchconst IllegalArgumentException& )
                {
                }
                catchconst ElementExistException& )
                {
                }

                pRight = m_xSuggestions->Next();
            }

            if( bAddedSomething || bRemovedSomething )
                InitEditDictDialog( m_nCurrentDict );
        }
        else
        {
            SAL_INFO( "cui.dialogs""dictionary faded away..." );
        }
    }

    bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( 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;
                }
                catchconst NoSuchElementException& )
                {   // can not be...
                }

                ++pEntry;
                --n;
            }
        }
        return bRemovedSomething;
    }

    IMPL_LINK_NOARG( HangulHanjaEditDictDialog, DeletePBPushHdl, weld::Button&, void )
    {
        if( DeleteEntryFromDictionary( m_rDictList[ m_nCurrentDict ] ) )
        {
            m_aOriginal.clear();
            m_bModifiedOriginal = true;
            InitEditDictDialog( m_nCurrentDict );
        }
    }

    void HangulHanjaEditDictDialog::InitEditDictDialog( sal_uInt32 nSelDict )
    {
        if( m_xSuggestions )
            m_xSuggestions->Clear();

        if( m_nCurrentDict != nSelDict )
        {
            m_nCurrentDict = nSelDict;
            m_aOriginal.clear();
            m_bModifiedOriginal = true;
        }

        UpdateOriginalLB();

        m_xOriginalLB->set_entry_text( !m_aOriginal.isEmpty() ? m_aOriginal : m_aEditHintText);
        m_xOriginalLB->select_entry_region(0, -1);
        m_xOriginalLB->grab_focus();

        UpdateSuggestions();
        UpdateButtonStates();
    }

    void HangulHanjaEditDictDialog::UpdateOriginalLB()
    {
        m_xOriginalLB->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_xOriginalLB->append_text( *pEntry );

                ++pEntry;
                --n;
            }
        }
        else
        {
            SAL_INFO( "cui.dialogs""dictionary faded away..." );
        }
    }

    void HangulHanjaEditDictDialog::UpdateButtonStates()
    {
        bool bHaveValidOriginalString = !m_aOriginal.isEmpty() && m_aOriginal != m_aEditHintText;
        bool bNew = bHaveValidOriginalString && m_xSuggestions && m_xSuggestions->GetCount() > 0;
        bNew = bNew && ( m_bModifiedSuggestions || m_bModifiedOriginal );

        m_xNewPB->set_sensitive( bNew );
        m_xDeletePB->set_sensitive(!m_bModifiedOriginal && bHaveValidOriginalString);
    }

    void HangulHanjaEditDictDialog::UpdateSuggestions()
    {
        Sequence< OUString > aEntries;
        bool bFound = GetConversions( m_rDictList[ m_nCurrentDict ], m_aOriginal, aEntries );
        if( bFound )
        {
            m_bModifiedOriginal = false;

            if( m_xSuggestions )
                m_xSuggestions->Clear();

            //fill found entries into boxes
            if (aEntries.hasElements())
            {
                if( !m_xSuggestions )
                    m_xSuggestions.reset(new SuggestionList);

                for (sal_Int32 n = 0; n < aEntries.getLength(); ++n)
                    m_xSuggestions->Set(aEntries[n], n);
            }
            m_bModifiedSuggestions = false;
        }

        m_xScrollSB->vadjustment_set_value( 0 );
        UpdateScrollbar();              // will force edits to be filled new
    }

    void HangulHanjaEditDictDialog::SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum)
    {
        OUString  aStr;
        if( m_xSuggestions )
        {
            aStr = m_xSuggestions->Get(nEntryNum);
        }

        rEdit.set_text(aStr);
    }

    void HangulHanjaEditDictDialog::EditModify(const weld::Entry* pEdit, sal_uInt8 _nEntryOffset)
    {
        m_bModifiedSuggestions = true;

        OUString  aTxt( pEdit->get_text() );
        sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset;
        if( aTxt.isEmpty() )
        {
            //reset suggestion
            if( m_xSuggestions )
                m_xSuggestions->Reset( nEntryNum );
        }
        else
        {
            //set suggestion
            if( !m_xSuggestions )
                m_xSuggestions.reset(new SuggestionList);
            m_xSuggestions->Set( aTxt, nEntryNum );
        }

        UpdateButtonStates();
    }

    HangulHanjaEditDictDialog::HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& _rDictList, sal_uInt32 nSelDict)
        : GenericDialogController(pParent, u"cui/ui/hangulhanjaeditdictdialog.ui"_ustr, u"HangulHanjaEditDictDialog"_ustr)
        , m_aEditHintText        ( CuiResId(RID_CUISTR_EDITHINT) )
        , m_rDictList            ( _rDictList )
        , m_nCurrentDict         ( 0xFFFFFFFF )
        , m_nTopPos              ( 0 )
        , m_bModifiedSuggestions ( false )
        , m_bModifiedOriginal    ( false )
        , m_xBookLB(m_xBuilder->weld_combo_box(u"book"_ustr))
        , m_xOriginalLB(m_xBuilder->weld_combo_box(u"original"_ustr))
        , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry(u"edit1"_ustr), this))
        , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry(u"edit2"_ustr), this))
        , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry(u"edit3"_ustr), this))
        , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry(u"edit4"_ustr), this))
        , m_xContents(m_xBuilder->weld_widget(u"box"_ustr))
        , m_xScrollSB(m_xBuilder->weld_scrolled_window(u"scrollbar"_ustr, true))
        , m_xNewPB(m_xBuilder->weld_button(u"new"_ustr))
        , m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr))
    {
        Size aSize(m_xContents->get_preferred_size());
        m_xScrollSB->set_size_request(-1, aSize.Height());

        m_xEdit1->init( m_xScrollSB.get(), nullptr, m_xEdit2.get() );
        m_xEdit2->init( m_xScrollSB.get(), m_xEdit1.get(), m_xEdit3.get() );
        m_xEdit3->init( m_xScrollSB.get(), m_xEdit2.get(), m_xEdit4.get() );
        m_xEdit4->init( m_xScrollSB.get(), m_xEdit3.get(), nullptr );

        m_xOriginalLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, OriginalModifyHdl ) );

        m_xNewPB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, NewPBPushHdl ) );
        m_xNewPB->set_sensitive( false );

        m_xDeletePB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, DeletePBPushHdl ) );
        m_xDeletePB->set_sensitive( false );

        static_assert(MAXNUM_SUGGESTIONS >= 5, "number of suggestions should not under-run the value of 5");

        // 4 here, because we have 4 edits / page
        m_xScrollSB->vadjustment_configure(0, 0, MAXNUM_SUGGESTIONS, 1, 4, 4);
        m_xScrollSB->connect_vadjustment_changed(LINK(this, HangulHanjaEditDictDialog, ScrollHdl));

        m_xEdit1->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl1 ) );
        m_xEdit2->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl2 ) );
        m_xEdit3->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl3 ) );
        m_xEdit4->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl4 ) );

        m_xBookLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, BookLBSelectHdl ) );
        sal_uInt32  nDictCnt = m_rDictList.size();
        for( sal_uInt32 n = 0 ; n < nDictCnt ; ++n )
        {
            Reference< XConversionDictionary >  xDic( m_rDictList[n] );
            OUString aName;
            if( xDic.is() )
                aName = xDic->getName();
            m_xBookLB->append_text( aName );
        }
        m_xBookLB->set_active(nSelDict);

        InitEditDictDialog(nSelDict);
    }

    HangulHanjaEditDictDialog::~HangulHanjaEditDictDialog()
    {
    }

    void HangulHanjaEditDictDialog::UpdateScrollbar()
    {
        sal_uInt16  nPos = m_xScrollSB->vadjustment_get_value();
        m_nTopPos = nPos;

        SetEditText( *m_xEdit1, nPos++ );
        SetEditText( *m_xEdit2, nPos++ );
        SetEditText( *m_xEdit3, nPos++ );
        SetEditText( *m_xEdit4, nPos );
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=96 G=95

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge