/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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( 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( 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 xControl); void init(const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition); void set_sensitive(bool sensitive) { m_xControl->set_sensitive(sensitive); } void set_active(bool active) { m_xControl->set_active(active); } bool get_active() const { return m_xControl->get_active(); } void connect_clicked(const Link& rLink) { m_xControl->connect_clicked(rLink); } private: Size GetOptimalSize() const; void Paint(vcl::RenderContext& rRenderContext); ScopedVclPtr m_xVirDev; std::unique_ptr m_xControl; PseudoRubyText m_aRubyText; }; RubyRadioButton::RubyRadioButton(std::unique_ptr xControl) : m_xVirDev(xControl->create_virtual_device()) , m_xControl(std::move(xControl)) { // 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_xControl->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( 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( aPrimarySize.Width() + aSecondarySize.Width() + 5 ); return minimumSize; } SuggestionSet::SuggestionSet(std::unique_ptr 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("scrollwin", true))) , m_xValueSetWin(new weld::CustomWeld(rBuilder, "valueset", *m_xValueSet)) , m_xListBox(rBuilder.weld_tree_view("listbox")) { m_xValueSet->SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionValueSetHdl ) ); m_xListBox->connect_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("AU").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& 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, "cui/ui/hangulhanjaconversiondialog.ui", "HangulHanjaConversionDialog") , m_bDocumentMode( true ) , m_xFind(m_xBuilder->weld_button("find")) , m_xIgnore(m_xBuilder->weld_button("ignore")) , m_xIgnoreAll(m_xBuilder->weld_button("ignoreall")) , m_xReplace(m_xBuilder->weld_button("replace")) , m_xReplaceAll(m_xBuilder->weld_button("replaceall")) , m_xOptions(m_xBuilder->weld_button("options")) , m_xSuggestions(new SuggestionDisplay(*m_xBuilder)) , m_xSimpleConversion(m_xBuilder->weld_radio_button("simpleconversion")) , m_xHangulBracketed(m_xBuilder->weld_radio_button("hangulbracket")) , m_xHanjaBracketed(m_xBuilder->weld_radio_button("hanjabracket")) , m_xWordInput(m_xBuilder->weld_entry("wordinput")) , m_xOriginalWord(m_xBuilder->weld_label("originalword")) , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_above"))) , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_below"))) , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_above"))) , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_below"))) , m_xHangulOnly(m_xBuilder->weld_check_button("hangulonly")) , m_xHanjaOnly(m_xBuilder->weld_check_button("hanjaonly")) , m_xReplaceByChar(m_xBuilder->weld_check_button("replacebychar")) { m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42, m_xOriginalWord->get_text_height() * 5); const OUString sHangul(CuiResId(RID_SVXSTR_HANGUL)); const OUString sHanja(CuiResId(RID_SVXSTR_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 >& _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& rHdl) { m_aOptionsChangedLink = rHdl; } void HangulHanjaConversionDialog::SetIgnoreHdl(const Link& rHdl) { m_xIgnore->connect_clicked(rHdl); } void HangulHanjaConversionDialog::SetIgnoreAllHdl(const Link& rHdl) { m_xIgnoreAll->connect_clicked(rHdl); } void HangulHanjaConversionDialog::SetChangeHdl(const Link& rHdl ) { m_xReplace->connect_clicked(rHdl); } void HangulHanjaConversionDialog::SetChangeAllHdl(const Link& rHdl) { m_xReplaceAll->connect_clicked(rHdl); } void HangulHanjaConversionDialog::SetFindHdl(const Link& rHdl) { m_xFind->connect_clicked(rHdl); } void HangulHanjaConversionDialog::SetConversionFormatChangedHdl( const Link& rHdl ) { m_xSimpleConversion->connect_clicked( rHdl ); m_xHangulBracketed->connect_clicked( rHdl ); m_xHanjaBracketed->connect_clicked( rHdl ); m_xHanjaAbove->connect_clicked( rHdl ); m_xHanjaBelow->connect_clicked( rHdl ); m_xHangulAbove->connect_clicked( rHdl ); m_xHangulBelow->connect_clicked( rHdl ); } void HangulHanjaConversionDialog::SetClickByCharacterHdl( const Link& _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::ToggleButton&, rBox, void) { m_aClickByCharacterLink.Call(rBox); bool bByCharacter = rBox.get_active(); m_xSuggestions->DisplayListBox( !bByCharacter ); } IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::ToggleButton&, 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(); } pOldDefButton->set_has_default(false); pNewDefButton->set_has_default(true); } 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() ) { Sequence< OUString > aDictNames( xNameCont->getElementNames() ); const OUString* pDic = aDictNames.getConstArray(); sal_Int32 nCount = aDictNames.getLength(); sal_Int32 i; for( i = 0 ; i < nCount ; ++i ) { Any aAny( xNameCont->getByName( pDic[ i ] ) ); 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() ); } } catch( const ElementExistException& ) { } catch( const 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); } catch( const ElementExistException& ) { } catch( const NoSupportException& ) { } } HangulHanjaOptionsDialog::HangulHanjaOptionsDialog(weld::Window* pParent) : GenericDialogController(pParent, "cui/ui/hangulhanjaoptdialog.ui", "HangulHanjaOptDialog") , m_xDictsLB(m_xBuilder->weld_tree_view("dicts")) , m_xIgnorepostCB(m_xBuilder->weld_check_button("ignorepost")) , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button("showrecentfirst")) , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button("autoreplaceunique")) , m_xNewPB(m_xBuilder->weld_button("new")) , m_xEditPB(m_xBuilder->weld_button("edit")) , m_xDeletePB(m_xBuilder->weld_button("delete")) , m_xOkPB(m_xBuilder->weld_button("ok")) { 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_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, "cui/ui/hangulhanjaadddialog.ui", "HangulHanjaAddDialog") , m_bEntered(false) , m_xOkBtn(m_xBuilder->weld_button("ok")) , m_xDictNameED(m_xBuilder->weld_entry("entry")) { 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 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 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(); } catch( const 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; } catch( const IllegalArgumentException& ) { } catch( const 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; } catch( const 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 sal_uInt32 nCnt = aEntries.getLength(); if( nCnt ) { if( !m_xSuggestions ) m_xSuggestions.reset(new SuggestionList); const OUString* pSugg = aEntries.getConstArray(); sal_uInt32 n = 0; while( nCnt ) { m_xSuggestions->Set( pSugg[ n ], sal_uInt16( n ) ); ++n; --nCnt; } } 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, "cui/ui/hangulhanjaeditdictdialog.ui", "HangulHanjaEditDictDialog") , m_aEditHintText ( CuiResId(RID_SVXSTR_EDITHINT) ) , m_rDictList ( _rDictList ) , m_nCurrentDict ( 0xFFFFFFFF ) , m_nTopPos ( 0 ) , m_bModifiedSuggestions ( false ) , m_bModifiedOriginal ( false ) , m_xBookLB(m_xBuilder->weld_combo_box("book")) , m_xOriginalLB(m_xBuilder->weld_combo_box("original")) , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry("edit1"), this)) , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry("edit2"), this)) , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry("edit3"), this)) , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry("edit4"), this)) , m_xContents(m_xBuilder->weld_widget("box")) , m_xScrollSB(m_xBuilder->weld_scrolled_window("scrollbar", true)) , m_xNewPB(m_xBuilder->weld_button("new")) , m_xDeletePB(m_xBuilder->weld_button("delete")) { 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: */