tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / cui / source / dialogs / hangulhanjadlg.cxx
blob66a3643e3b01007cdc2b5d1cc9478ce027afcda8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hangulhanjadlg.hxx>
21 #include <dialmgr.hxx>
23 #include <helpids.h>
24 #include <strings.hrc>
26 #include <algorithm>
27 #include <sal/log.hxx>
28 #include <osl/diagnose.h>
29 #include <tools/debug.hxx>
30 #include <i18nlangtag/languagetag.hxx>
31 #include <vcl/virdev.hxx>
32 #include <vcl/weldutils.hxx>
33 #include <unotools/lingucfg.hxx>
34 #include <unotools/linguprops.hxx>
35 #include <com/sun/star/lang/NoSupportException.hpp>
36 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
37 #include <com/sun/star/linguistic2/ConversionDirection.hpp>
38 #include <com/sun/star/linguistic2/ConversionDictionaryList.hpp>
39 #include <com/sun/star/i18n/TextConversionOption.hpp>
40 #include <com/sun/star/util/XFlushable.hpp>
42 #include <comphelper/processfactory.hxx>
43 #include <comphelper/string.hxx>
45 #define HHC editeng::HangulHanjaConversion
46 #define LINE_CNT static_cast< sal_uInt16 >(2)
47 #define MAXNUM_SUGGESTIONS 50
50 namespace svx
53 using namespace ::com::sun::star;
54 using namespace css::uno;
55 using namespace css::linguistic2;
56 using namespace css::lang;
57 using namespace css::container;
60 namespace
62 class FontSwitch
64 private:
65 OutputDevice& m_rDev;
67 public:
68 FontSwitch( OutputDevice& _rDev, const vcl::Font& _rTemporaryFont )
69 :m_rDev( _rDev )
71 m_rDev.Push( vcl::PushFlags::FONT );
72 m_rDev.SetFont( _rTemporaryFont );
74 ~FontSwitch() COVERITY_NOEXCEPT_FALSE
76 m_rDev.Pop();
80 /** a class which allows to draw two texts in a pseudo-ruby way (which basically
81 means one text above or below the other, and a little bit smaller)
83 class PseudoRubyText
85 public:
86 enum RubyPosition
88 eAbove, eBelow
91 protected:
92 OUString m_sPrimaryText;
93 OUString m_sSecondaryText;
94 RubyPosition m_ePosition;
96 public:
97 PseudoRubyText();
98 void init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition );
99 const OUString& getPrimaryText() const { return m_sPrimaryText; }
100 const OUString& getSecondaryText() const { return m_sSecondaryText; }
102 public:
103 void Paint( vcl::RenderContext& _rDevice, const ::tools::Rectangle& _rRect,
104 ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation );
109 PseudoRubyText::PseudoRubyText()
110 : m_ePosition(eAbove)
114 void PseudoRubyText::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition )
116 m_sPrimaryText = rPrimaryText;
117 m_sSecondaryText = rSecondaryText;
118 m_ePosition = rPosition;
122 void PseudoRubyText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& _rRect,
123 ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation )
125 // calculate the text flags for the painting
126 constexpr DrawTextFlags nTextStyle = DrawTextFlags::Mnemonic |
127 DrawTextFlags::Left |
128 DrawTextFlags::VCenter;
130 Size aPlaygroundSize(_rRect.GetSize());
132 // the font for the secondary text:
133 vcl::Font aSmallerFont(rRenderContext.GetFont());
134 // heuristic: 80% of the original size
135 aSmallerFont.SetFontHeight( static_cast<tools::Long>( 0.8 * aSmallerFont.GetFontHeight() ) );
137 // let's calculate the size of our two texts
138 ::tools::Rectangle aPrimaryRect = rRenderContext.GetTextRect( _rRect, m_sPrimaryText, nTextStyle );
139 ::tools::Rectangle aSecondaryRect;
141 FontSwitch aFontRestore(rRenderContext, aSmallerFont);
142 aSecondaryRect = rRenderContext.GetTextRect(_rRect, m_sSecondaryText, nTextStyle);
145 // position these rectangles properly
146 // x-axis:
147 sal_Int32 nCombinedWidth = std::max( aSecondaryRect.GetWidth(), aPrimaryRect.GetWidth() );
148 // the rectangle where both texts will reside is as high as possible, and as wide as the
149 // widest of both text rects
150 aPrimaryRect.SetLeft( _rRect.Left() );
151 aSecondaryRect.SetLeft( aPrimaryRect.Left() );
152 aPrimaryRect.SetRight( _rRect.Left() + nCombinedWidth );
153 aSecondaryRect.SetRight( aPrimaryRect.Right() );
155 // y-axis:
156 sal_Int32 nCombinedHeight = aPrimaryRect.GetHeight() + aSecondaryRect.GetHeight();
157 // align to the top, for the moment
158 aPrimaryRect.Move( 0, _rRect.Top() - aPrimaryRect.Top() );
159 aSecondaryRect.Move( 0, aPrimaryRect.Top() + aPrimaryRect.GetHeight() - aSecondaryRect.Top() );
160 // move the rects to the bottom
161 aPrimaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 );
162 aSecondaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 );
164 // 'til here, everything we did assumes that the secondary text is painted _below_ the primary
165 // text. If this isn't the case, we need to correct the rectangles
166 if (eAbove == m_ePosition)
168 sal_Int32 nVertDistance = aSecondaryRect.Top() - aPrimaryRect.Top();
169 aSecondaryRect.Move( 0, -nVertDistance );
170 aPrimaryRect.Move( 0, nCombinedHeight - nVertDistance );
173 // now draw the texts
174 // as we already calculated the precise rectangles for the texts, we don't want to
175 // use the alignment flags given - within its rect, every text is centered
176 DrawTextFlags nDrawTextStyle( nTextStyle );
177 nDrawTextStyle &= ~DrawTextFlags( DrawTextFlags::Right | DrawTextFlags::Left | DrawTextFlags::Bottom | DrawTextFlags::Top );
178 nDrawTextStyle |= DrawTextFlags::Center | DrawTextFlags::VCenter;
180 rRenderContext.DrawText( aPrimaryRect, m_sPrimaryText, nDrawTextStyle );
182 FontSwitch aFontRestore(rRenderContext, aSmallerFont);
183 rRenderContext.DrawText( aSecondaryRect, m_sSecondaryText, nDrawTextStyle );
186 // outta here
187 if (_pPrimaryLocation)
188 *_pPrimaryLocation = aPrimaryRect;
189 if (_pSecondaryLocation)
190 *_pSecondaryLocation = aSecondaryRect;
193 class RubyRadioButton
195 public:
196 RubyRadioButton(std::unique_ptr<weld::RadioButton> xControl, std::unique_ptr<weld::Image> xImage);
197 void init(const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition);
199 void set_sensitive(bool sensitive)
201 m_xControl->set_sensitive(sensitive);
202 m_xImage->set_sensitive(sensitive);
204 void set_active(bool active) { m_xControl->set_active(active); }
205 bool get_active() const { return m_xControl->get_active(); }
207 void connect_toggled(const Link<weld::Toggleable&, void>& rLink) { m_xControl->connect_toggled(rLink); }
209 private:
210 Size GetOptimalSize() const;
211 void Paint(vcl::RenderContext& rRenderContext);
213 ScopedVclPtr<VirtualDevice> m_xVirDev;
214 std::unique_ptr<weld::RadioButton> m_xControl;
215 std::unique_ptr<weld::Image> m_xImage;
216 PseudoRubyText m_aRubyText;
219 RubyRadioButton::RubyRadioButton(std::unique_ptr<weld::RadioButton> xControl, std::unique_ptr<weld::Image> xImage)
220 : m_xVirDev(xControl->create_virtual_device())
221 , m_xControl(std::move(xControl))
222 , m_xImage(std::move(xImage))
224 // expand the point size of the desired font to the equivalent pixel size
225 weld::SetPointFont(*m_xVirDev, m_xControl->get_font());
228 void RubyRadioButton::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition )
230 m_aRubyText.init(rPrimaryText, rSecondaryText, rPosition);
232 m_xVirDev->SetOutputSizePixel(GetOptimalSize());
234 Paint(*m_xVirDev);
236 m_xImage->set_image(m_xVirDev.get());
239 void RubyRadioButton::Paint(vcl::RenderContext& rRenderContext)
241 ::tools::Rectangle aOverallRect(Point(0, 0), rRenderContext.GetOutputSizePixel());
242 // inflate the rect a little bit (because the VCL radio button does the same)
243 ::tools::Rectangle aTextRect( aOverallRect );
244 aTextRect.AdjustLeft( 1 ); aTextRect.AdjustRight( -1 );
245 aTextRect.AdjustTop( 1 ); aTextRect.AdjustBottom( -1 );
247 // paint the ruby text
248 ::tools::Rectangle aPrimaryTextLocation;
249 ::tools::Rectangle aSecondaryTextLocation;
251 m_aRubyText.Paint(rRenderContext, aTextRect, &aPrimaryTextLocation, &aSecondaryTextLocation);
254 Size RubyRadioButton::GetOptimalSize() const
256 vcl::Font aSmallerFont(m_xVirDev->GetFont());
257 aSmallerFont.SetFontHeight( static_cast<tools::Long>( 0.8 * aSmallerFont.GetFontHeight() ) );
258 ::tools::Rectangle rect( Point(), Size( SAL_MAX_INT32, SAL_MAX_INT32 ) );
260 Size aPrimarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getPrimaryText() ).GetSize();
261 Size aSecondarySize;
263 FontSwitch aFontRestore(*m_xVirDev, aSmallerFont);
264 aSecondarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getSecondaryText() ).GetSize();
267 Size minimumSize;
268 minimumSize.setHeight( aPrimarySize.Height() + aSecondarySize.Height() + 5 );
269 minimumSize.setWidth(std::max(aPrimarySize.Width(), aSecondarySize.Width()) + 5 );
270 return minimumSize;
273 SuggestionSet::SuggestionSet(std::unique_ptr<weld::ScrolledWindow> xScrolledWindow)
274 : ValueSet(std::move(xScrolledWindow))
279 void SuggestionSet::UserDraw( const UserDrawEvent& rUDEvt )
281 vcl::RenderContext* pDev = rUDEvt.GetRenderContext();
282 ::tools::Rectangle aRect = rUDEvt.GetRect();
283 sal_uInt16 nItemId = rUDEvt.GetItemId();
285 OUString sText = *static_cast< OUString* >( GetItemData( nItemId ) );
286 pDev->DrawText( aRect, sText, DrawTextFlags::Center | DrawTextFlags::VCenter );
289 SuggestionDisplay::SuggestionDisplay(weld::Builder& rBuilder)
290 : m_bDisplayListBox( true )
291 , m_bInSelectionUpdate( false )
292 , m_xValueSet(new SuggestionSet(rBuilder.weld_scrolled_window(u"scrollwin"_ustr, true)))
293 , m_xValueSetWin(new weld::CustomWeld(rBuilder, u"valueset"_ustr, *m_xValueSet))
294 , m_xListBox(rBuilder.weld_tree_view(u"listbox"_ustr))
296 m_xValueSet->SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionValueSetHdl ) );
297 m_xListBox->connect_selection_changed(
298 LINK(this, SuggestionDisplay, SelectSuggestionListBoxHdl));
300 m_xValueSet->SetLineCount( LINE_CNT );
301 m_xValueSet->SetStyle( m_xValueSet->GetStyle() | WB_ITEMBORDER | WB_VSCROLL );
303 auto nItemWidth = 2 * m_xListBox->get_pixel_size(u"AU"_ustr).Width();
304 m_xValueSet->SetItemWidth( nItemWidth );
306 Size aSize(m_xListBox->get_approximate_digit_width() * 42, m_xListBox->get_text_height() * 5);
307 m_xValueSet->set_size_request(aSize.Width(), aSize.Height());
308 m_xListBox->set_size_request(aSize.Width(), aSize.Height());
310 implUpdateDisplay();
313 void SuggestionDisplay::implUpdateDisplay()
315 m_xListBox->set_visible(m_bDisplayListBox);
316 if (!m_bDisplayListBox)
317 m_xValueSetWin->show();
318 else
319 m_xValueSetWin->hide();
322 weld::Widget& SuggestionDisplay::implGetCurrentControl()
324 if (m_bDisplayListBox)
325 return *m_xListBox;
326 return *m_xValueSet->GetDrawingArea();
329 void SuggestionDisplay::DisplayListBox( bool bDisplayListBox )
331 if( m_bDisplayListBox == bDisplayListBox )
332 return;
334 weld::Widget& rOldControl = implGetCurrentControl();
335 bool bHasFocus = rOldControl.has_focus();
337 m_bDisplayListBox = bDisplayListBox;
339 if( bHasFocus )
341 weld::Widget& rNewControl = implGetCurrentControl();
342 rNewControl.grab_focus();
345 implUpdateDisplay();
348 IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionValueSetHdl, ValueSet*, void)
350 SelectSuggestionHdl(false);
353 IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionListBoxHdl, weld::TreeView&, void)
355 SelectSuggestionHdl(true);
358 void SuggestionDisplay::SelectSuggestionHdl(bool bListBox)
360 if( m_bInSelectionUpdate )
361 return;
363 m_bInSelectionUpdate = true;
364 if (bListBox)
366 sal_uInt16 nPos = m_xListBox->get_selected_index();
367 m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
369 else
371 sal_uInt16 nPos = m_xValueSet->GetSelectedItemId()-1; //itemid == pos+1 (id 0 has special meaning)
372 m_xListBox->select(nPos);
374 m_bInSelectionUpdate = false;
375 m_aSelectLink.Call( *this );
378 void SuggestionDisplay::SetSelectHdl( const Link<SuggestionDisplay&,void>& rLink )
380 m_aSelectLink = rLink;
383 void SuggestionDisplay::Clear()
385 m_xListBox->clear();
386 m_xValueSet->Clear();
389 void SuggestionDisplay::InsertEntry( const OUString& rStr )
391 m_xListBox->append_text(rStr);
392 sal_uInt16 nItemId = m_xListBox->n_children(); //itemid == pos+1 (id 0 has special meaning)
393 m_xValueSet->InsertItem( nItemId );
394 OUString* pItemData = new OUString( rStr );
395 m_xValueSet->SetItemData( nItemId, pItemData );
398 void SuggestionDisplay::SelectEntryPos( sal_uInt16 nPos )
400 m_xListBox->select(nPos);
401 m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
404 sal_uInt16 SuggestionDisplay::GetEntryCount() const
406 return m_xListBox->n_children();
409 OUString SuggestionDisplay::GetEntry( sal_uInt16 nPos ) const
411 return m_xListBox->get_text( nPos );
414 OUString SuggestionDisplay::GetSelectedEntry() const
416 return m_xListBox->get_selected_text();
419 void SuggestionDisplay::SetHelpIds()
421 m_xValueSet->SetHelpId(HID_HANGULDLG_SUGGESTIONS_GRID);
422 m_xListBox->set_help_id(HID_HANGULDLG_SUGGESTIONS_LIST);
425 HangulHanjaConversionDialog::HangulHanjaConversionDialog(weld::Widget* pParent)
426 : GenericDialogController(pParent, u"cui/ui/hangulhanjaconversiondialog.ui"_ustr, u"HangulHanjaConversionDialog"_ustr)
427 , m_bDocumentMode( true )
428 , m_xFind(m_xBuilder->weld_button(u"find"_ustr))
429 , m_xIgnore(m_xBuilder->weld_button(u"ignore"_ustr))
430 , m_xIgnoreAll(m_xBuilder->weld_button(u"ignoreall"_ustr))
431 , m_xReplace(m_xBuilder->weld_button(u"replace"_ustr))
432 , m_xReplaceAll(m_xBuilder->weld_button(u"replaceall"_ustr))
433 , m_xOptions(m_xBuilder->weld_button(u"options"_ustr))
434 , m_xSuggestions(new SuggestionDisplay(*m_xBuilder))
435 , m_xSimpleConversion(m_xBuilder->weld_radio_button(u"simpleconversion"_ustr))
436 , m_xHangulBracketed(m_xBuilder->weld_radio_button(u"hangulbracket"_ustr))
437 , m_xHanjaBracketed(m_xBuilder->weld_radio_button(u"hanjabracket"_ustr))
438 , m_xWordInput(m_xBuilder->weld_entry(u"wordinput"_ustr))
439 , m_xOriginalWord(m_xBuilder->weld_label(u"originalword"_ustr))
440 , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hanja_above"_ustr),
441 m_xBuilder->weld_image(u"hanja_above_img"_ustr)))
442 , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hanja_below"_ustr),
443 m_xBuilder->weld_image(u"hanja_below_img"_ustr)))
444 , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hangul_above"_ustr),
445 m_xBuilder->weld_image(u"hangul_above_img"_ustr)))
446 , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hangul_below"_ustr),
447 m_xBuilder->weld_image(u"hangul_below_img"_ustr)))
448 , m_xHangulOnly(m_xBuilder->weld_check_button(u"hangulonly"_ustr))
449 , m_xHanjaOnly(m_xBuilder->weld_check_button(u"hanjaonly"_ustr))
450 , m_xReplaceByChar(m_xBuilder->weld_check_button(u"replacebychar"_ustr))
452 m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42,
453 m_xOriginalWord->get_text_height() * 5);
455 const OUString sHangul(CuiResId(RID_CUISTR_HANGUL));
456 const OUString sHanja(CuiResId(RID_CUISTR_HANJA));
457 m_xHanjaAbove->init( sHangul, sHanja, PseudoRubyText::eAbove );
458 m_xHanjaBelow->init( sHangul, sHanja, PseudoRubyText::eBelow );
459 m_xHangulAbove->init( sHanja, sHangul, PseudoRubyText::eAbove );
460 m_xHangulBelow->init( sHanja, sHangul, PseudoRubyText::eBelow );
462 m_xWordInput->connect_changed( LINK( this, HangulHanjaConversionDialog, OnSuggestionModified ) );
463 m_xSuggestions->SetSelectHdl( LINK( this, HangulHanjaConversionDialog, OnSuggestionSelected ) );
464 m_xReplaceByChar->connect_toggled( LINK( this, HangulHanjaConversionDialog, ClickByCharacterHdl ) );
465 m_xHangulOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
466 m_xHanjaOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
467 m_xOptions->connect_clicked(LINK(this, HangulHanjaConversionDialog, OnOption));
469 // initial focus
470 FocusSuggestion( );
472 // initial control values
473 m_xSimpleConversion->set_active(true);
475 m_xSuggestions->SetHelpIds();
478 HangulHanjaConversionDialog::~HangulHanjaConversionDialog()
482 void HangulHanjaConversionDialog::FillSuggestions( const css::uno::Sequence< OUString >& _rSuggestions )
484 m_xSuggestions->Clear();
485 for ( auto const & suggestion : _rSuggestions )
486 m_xSuggestions->InsertEntry( suggestion );
488 // select the first suggestion, and fill in the suggestion edit field
489 OUString sFirstSuggestion;
490 if ( m_xSuggestions->GetEntryCount() )
492 sFirstSuggestion = m_xSuggestions->GetEntry( 0 );
493 m_xSuggestions->SelectEntryPos( 0 );
495 m_xWordInput->set_text( sFirstSuggestion );
496 m_xWordInput->save_value();
497 OnSuggestionModified( *m_xWordInput );
500 void HangulHanjaConversionDialog::SetOptionsChangedHdl(const Link<LinkParamNone*,void>& rHdl)
502 m_aOptionsChangedLink = rHdl;
505 void HangulHanjaConversionDialog::SetIgnoreHdl(const Link<weld::Button&,void>& rHdl)
507 m_xIgnore->connect_clicked(rHdl);
510 void HangulHanjaConversionDialog::SetIgnoreAllHdl(const Link<weld::Button&,void>& rHdl)
512 m_xIgnoreAll->connect_clicked(rHdl);
515 void HangulHanjaConversionDialog::SetChangeHdl(const Link<weld::Button&,void>& rHdl )
517 m_xReplace->connect_clicked(rHdl);
520 void HangulHanjaConversionDialog::SetChangeAllHdl(const Link<weld::Button&,void>& rHdl)
522 m_xReplaceAll->connect_clicked(rHdl);
525 void HangulHanjaConversionDialog::SetFindHdl(const Link<weld::Button&,void>& rHdl)
527 m_xFind->connect_clicked(rHdl);
530 void HangulHanjaConversionDialog::SetConversionFormatChangedHdl( const Link<weld::Toggleable&,void>& rHdl )
532 m_xSimpleConversion->connect_toggled( rHdl );
533 m_xHangulBracketed->connect_toggled( rHdl );
534 m_xHanjaBracketed->connect_toggled( rHdl );
535 m_xHanjaAbove->connect_toggled( rHdl );
536 m_xHanjaBelow->connect_toggled( rHdl );
537 m_xHangulAbove->connect_toggled( rHdl );
538 m_xHangulBelow->connect_toggled( rHdl );
541 void HangulHanjaConversionDialog::SetClickByCharacterHdl( const Link<weld::Toggleable&,void>& _rHdl )
543 m_aClickByCharacterLink = _rHdl;
546 IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionSelected, SuggestionDisplay&, void )
548 m_xWordInput->set_text(m_xSuggestions->GetSelectedEntry());
549 OnSuggestionModified( *m_xWordInput );
552 IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionModified, weld::Entry&, void )
554 m_xFind->set_sensitive(m_xWordInput->get_value_changed_from_saved());
556 bool bSameLen = m_xWordInput->get_text().getLength() == m_xOriginalWord->get_label().getLength();
557 m_xReplace->set_sensitive( m_bDocumentMode && bSameLen );
558 m_xReplaceAll->set_sensitive( m_bDocumentMode && bSameLen );
561 IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::Toggleable&, rBox, void)
563 m_aClickByCharacterLink.Call(rBox);
564 bool bByCharacter = rBox.get_active();
565 m_xSuggestions->DisplayListBox( !bByCharacter );
568 IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::Toggleable&, rBox, void)
570 weld::CheckButton* pOtherBox = nullptr;
571 if (&rBox == m_xHangulOnly.get())
572 pOtherBox = m_xHanjaOnly.get();
573 else
574 pOtherBox = m_xHangulOnly.get();
575 bool bBoxChecked = rBox.get_active();
576 if (bBoxChecked)
577 pOtherBox->set_active(false);
578 pOtherBox->set_sensitive(!bBoxChecked);
581 IMPL_LINK_NOARG(HangulHanjaConversionDialog, OnOption, weld::Button&, void)
583 HangulHanjaOptionsDialog aOptDlg(m_xDialog.get());
584 aOptDlg.run();
585 m_aOptionsChangedLink.Call( nullptr );
588 OUString HangulHanjaConversionDialog::GetCurrentString( ) const
590 return m_xOriginalWord->get_label();
593 void HangulHanjaConversionDialog::FocusSuggestion( )
595 m_xWordInput->grab_focus();
598 void HangulHanjaConversionDialog::SetCurrentString( const OUString& _rNewString,
599 const Sequence< OUString >& _rSuggestions, bool _bOriginatesFromDocument )
601 m_xOriginalWord->set_label(_rNewString);
603 bool bOldDocumentMode = m_bDocumentMode;
604 m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions!
605 FillSuggestions( _rSuggestions );
607 m_xIgnoreAll->set_sensitive( m_bDocumentMode );
609 // switch the def button depending if we're working for document text
610 if (bOldDocumentMode == m_bDocumentMode)
611 return;
613 weld::Widget* pOldDefButton = nullptr;
614 weld::Widget* pNewDefButton = nullptr;
615 if (m_bDocumentMode)
617 pOldDefButton = m_xFind.get();
618 pNewDefButton = m_xReplace.get();
620 else
622 pOldDefButton = m_xReplace.get();
623 pNewDefButton = m_xFind.get();
626 m_xDialog->change_default_widget(pOldDefButton, pNewDefButton);
629 OUString HangulHanjaConversionDialog::GetCurrentSuggestion( ) const
631 return m_xWordInput->get_text();
634 void HangulHanjaConversionDialog::SetByCharacter( bool _bByCharacter )
636 m_xReplaceByChar->set_active( _bByCharacter );
637 m_xSuggestions->DisplayListBox( !_bByCharacter );
640 void HangulHanjaConversionDialog::SetConversionDirectionState(
641 bool _bTryBothDirections,
642 HHC::ConversionDirection ePrimaryConversionDirection )
644 // default state: try both direction
645 m_xHangulOnly->set_active( false );
646 m_xHangulOnly->set_sensitive(true);
647 m_xHanjaOnly->set_active( false );
648 m_xHanjaOnly->set_sensitive(true);
650 if (!_bTryBothDirections)
652 weld::CheckButton* pBox = ePrimaryConversionDirection == HHC::eHangulToHanja ?
653 m_xHangulOnly.get() : m_xHanjaOnly.get();
654 pBox->set_active(true);
655 OnConversionDirectionClicked(*pBox);
659 bool HangulHanjaConversionDialog::GetUseBothDirections( ) const
661 return !m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active();
664 HHC::ConversionDirection HangulHanjaConversionDialog::GetDirection(
665 HHC::ConversionDirection eDefaultDirection ) const
667 HHC::ConversionDirection eDirection = eDefaultDirection;
668 if (m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active())
669 eDirection = HHC::eHangulToHanja;
670 else if (!m_xHangulOnly->get_active() && m_xHanjaOnly->get_active())
671 eDirection = HHC::eHanjaToHangul;
672 return eDirection;
675 void HangulHanjaConversionDialog::SetConversionFormat( HHC::ConversionFormat _eType )
677 switch ( _eType )
679 case HHC::eSimpleConversion: m_xSimpleConversion->set_active(true); break;
680 case HHC::eHangulBracketed: m_xHangulBracketed->set_active(true); break;
681 case HHC::eHanjaBracketed: m_xHanjaBracketed->set_active(true); break;
682 case HHC::eRubyHanjaAbove: m_xHanjaAbove->set_active(true); break;
683 case HHC::eRubyHanjaBelow: m_xHanjaBelow->set_active(true); break;
684 case HHC::eRubyHangulAbove: m_xHangulAbove->set_active(true); break;
685 case HHC::eRubyHangulBelow: m_xHangulBelow->set_active(true); break;
686 default:
687 OSL_FAIL( "HangulHanjaConversionDialog::SetConversionFormat: unknown type!" );
691 HHC::ConversionFormat HangulHanjaConversionDialog::GetConversionFormat( ) const
693 if ( m_xSimpleConversion->get_active() )
694 return HHC::eSimpleConversion;
695 if ( m_xHangulBracketed->get_active() )
696 return HHC::eHangulBracketed;
697 if ( m_xHanjaBracketed->get_active() )
698 return HHC::eHanjaBracketed;
699 if ( m_xHanjaAbove->get_active() )
700 return HHC::eRubyHanjaAbove;
701 if ( m_xHanjaBelow->get_active() )
702 return HHC::eRubyHanjaBelow;
703 if ( m_xHangulAbove->get_active() )
704 return HHC::eRubyHangulAbove;
705 if ( m_xHangulBelow->get_active() )
706 return HHC::eRubyHangulBelow;
708 OSL_FAIL( "HangulHanjaConversionDialog::GetConversionFormat: no radio checked?" );
709 return HHC::eSimpleConversion;
712 void HangulHanjaConversionDialog::EnableRubySupport( bool bVal )
714 m_xHanjaAbove->set_sensitive( bVal );
715 m_xHanjaBelow->set_sensitive( bVal );
716 m_xHangulAbove->set_sensitive( bVal );
717 m_xHangulBelow->set_sensitive( bVal );
720 void HangulHanjaOptionsDialog::Init()
722 if( !m_xConversionDictionaryList.is() )
724 m_xConversionDictionaryList = ConversionDictionaryList::create( ::comphelper::getProcessComponentContext() );
727 m_aDictList.clear();
728 m_xDictsLB->clear();
730 Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
731 if( xNameCont.is() )
733 for (auto& name : xNameCont->getElementNames())
735 Any aAny(xNameCont->getByName(name));
736 Reference< XConversionDictionary > xDic;
737 if( ( aAny >>= xDic ) && xDic.is() )
739 if( LANGUAGE_KOREAN == LanguageTag( xDic->getLocale() ).getLanguageType() )
741 m_aDictList.push_back( xDic );
742 AddDict( xDic->getName(), xDic->isActive() );
747 if (m_xDictsLB->n_children())
748 m_xDictsLB->select(0);
751 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, OkHdl, weld::Button&, void)
753 sal_uInt32 nCnt = m_aDictList.size();
754 sal_uInt32 n = 0;
755 sal_uInt32 nActiveDics = 0;
756 Sequence< OUString > aActiveDics;
758 aActiveDics.realloc( nCnt );
759 OUString* pActActiveDic = aActiveDics.getArray();
761 while( nCnt )
763 Reference< XConversionDictionary > xDict = m_aDictList[ n ];
765 DBG_ASSERT( xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..." );
767 bool bActive = m_xDictsLB->get_toggle(n) == TRISTATE_TRUE;
768 xDict->setActive( bActive );
769 Reference< util::XFlushable > xFlush( xDict, uno::UNO_QUERY );
770 if( xFlush.is() )
771 xFlush->flush();
773 if( bActive )
775 pActActiveDic[ nActiveDics ] = xDict->getName();
776 ++nActiveDics;
779 ++n;
780 --nCnt;
783 // save configuration
784 aActiveDics.realloc( nActiveDics );
785 Any aTmp;
786 SvtLinguConfig aLngCfg;
787 aTmp <<= aActiveDics;
788 aLngCfg.SetProperty( UPH_ACTIVE_CONVERSION_DICTIONARIES, aTmp );
790 aTmp <<= m_xIgnorepostCB->get_active();
791 aLngCfg.SetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD, aTmp );
793 aTmp <<= m_xShowrecentlyfirstCB->get_active();
794 aLngCfg.SetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, aTmp );
796 aTmp <<= m_xAutoreplaceuniqueCB->get_active();
797 aLngCfg.SetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES, aTmp );
799 m_xDialog->response(RET_OK);
802 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DictsLB_SelectHdl, weld::TreeView&, void)
804 bool bSel = m_xDictsLB->get_selected_index() != -1;
806 m_xEditPB->set_sensitive(bSel);
807 m_xDeletePB->set_sensitive(bSel);
810 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, NewDictHdl, weld::Button&, void)
812 OUString aName;
813 HangulHanjaNewDictDialog aNewDlg(m_xDialog.get());
814 aNewDlg.run();
815 if (!aNewDlg.GetName(aName))
816 return;
818 if( !m_xConversionDictionaryList.is() )
819 return;
823 Reference< XConversionDictionary > xDic =
824 m_xConversionDictionaryList->addNewDictionary( aName, LanguageTag::convertToLocale( LANGUAGE_KOREAN ), ConversionDictionaryType::HANGUL_HANJA );
826 if( xDic.is() )
828 //adapt local caches:
829 m_aDictList.push_back( xDic );
830 AddDict( xDic->getName(), xDic->isActive() );
833 catch( const ElementExistException& )
836 catch( const NoSupportException& )
841 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, EditDictHdl, weld::Button&, void)
843 int nEntry = m_xDictsLB->get_selected_index();
844 DBG_ASSERT(nEntry != -1, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not be possible with no selection!");
845 if (nEntry != -1)
847 HangulHanjaEditDictDialog aEdDlg(m_xDialog.get(), m_aDictList, nEntry);
848 aEdDlg.run();
852 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DeleteDictHdl, weld::Button&, void)
854 int nSelPos = m_xDictsLB->get_selected_index();
855 if (nSelPos == -1)
856 return;
858 Reference< XConversionDictionary > xDic( m_aDictList[ nSelPos ] );
859 if( !(m_xConversionDictionaryList.is() && xDic.is()) )
860 return;
862 Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
863 if( !xNameCont.is() )
864 return;
868 xNameCont->removeByName( xDic->getName() );
870 //adapt local caches:
871 m_aDictList.erase(m_aDictList.begin()+nSelPos );
872 m_xDictsLB->remove(nSelPos);
874 catch( const ElementExistException& )
877 catch( const NoSupportException& )
882 HangulHanjaOptionsDialog::HangulHanjaOptionsDialog(weld::Window* pParent)
883 : GenericDialogController(pParent, u"cui/ui/hangulhanjaoptdialog.ui"_ustr, u"HangulHanjaOptDialog"_ustr)
884 , m_xDictsLB(m_xBuilder->weld_tree_view(u"dicts"_ustr))
885 , m_xIgnorepostCB(m_xBuilder->weld_check_button(u"ignorepost"_ustr))
886 , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button(u"showrecentfirst"_ustr))
887 , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button(u"autoreplaceunique"_ustr))
888 , m_xNewPB(m_xBuilder->weld_button(u"new"_ustr))
889 , m_xEditPB(m_xBuilder->weld_button(u"edit"_ustr))
890 , m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr))
891 , m_xOkPB(m_xBuilder->weld_button(u"ok"_ustr))
893 m_xDictsLB->set_size_request(m_xDictsLB->get_approximate_digit_width() * 32,
894 m_xDictsLB->get_height_rows(5));
896 m_xDictsLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
898 m_xDictsLB->connect_selection_changed(
899 LINK(this, HangulHanjaOptionsDialog, DictsLB_SelectHdl));
901 m_xOkPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, OkHdl ) );
902 m_xNewPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, NewDictHdl ) );
903 m_xEditPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, EditDictHdl ) );
904 m_xDeletePB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, DeleteDictHdl ) );
906 SvtLinguConfig aLngCfg;
907 Any aTmp;
908 bool bVal = bool();
909 aTmp = aLngCfg.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD );
910 if( aTmp >>= bVal )
911 m_xIgnorepostCB->set_active( bVal );
913 aTmp = aLngCfg.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST );
914 if( aTmp >>= bVal )
915 m_xShowrecentlyfirstCB->set_active( bVal );
917 aTmp = aLngCfg.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES );
918 if( aTmp >>= bVal )
919 m_xAutoreplaceuniqueCB->set_active( bVal );
921 Init();
924 HangulHanjaOptionsDialog::~HangulHanjaOptionsDialog()
928 void HangulHanjaOptionsDialog::AddDict(const OUString& rName, bool bChecked)
930 m_xDictsLB->append();
931 int nRow = m_xDictsLB->n_children() - 1;
932 m_xDictsLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
933 m_xDictsLB->set_text(nRow, rName, 0);
934 m_xDictsLB->set_id(nRow, rName);
937 IMPL_LINK_NOARG(HangulHanjaNewDictDialog, OKHdl, weld::Button&, void)
939 OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));
941 m_bEntered = !aName.isEmpty();
942 if (m_bEntered)
943 m_xDictNameED->set_text(aName); // do this in case of trailing chars have been deleted
945 m_xDialog->response(RET_OK);
948 IMPL_LINK_NOARG(HangulHanjaNewDictDialog, ModifyHdl, weld::Entry&, void)
950 OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));
952 m_xOkBtn->set_sensitive(!aName.isEmpty());
955 HangulHanjaNewDictDialog::HangulHanjaNewDictDialog(weld::Window* pParent)
956 : GenericDialogController(pParent, u"cui/ui/hangulhanjaadddialog.ui"_ustr, u"HangulHanjaAddDialog"_ustr)
957 , m_bEntered(false)
958 , m_xOkBtn(m_xBuilder->weld_button(u"ok"_ustr))
959 , m_xDictNameED(m_xBuilder->weld_entry(u"entry"_ustr))
961 m_xOkBtn->connect_clicked( LINK( this, HangulHanjaNewDictDialog, OKHdl ) );
962 m_xDictNameED->connect_changed( LINK( this, HangulHanjaNewDictDialog, ModifyHdl ) );
965 HangulHanjaNewDictDialog::~HangulHanjaNewDictDialog()
969 bool HangulHanjaNewDictDialog::GetName( OUString& _rRetName ) const
971 if( m_bEntered )
972 _rRetName = comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ');
974 return m_bEntered;
977 class SuggestionList
979 private:
980 protected:
981 std::vector<OUString> m_vElements;
982 sal_uInt16 m_nNumOfEntries;
983 // index of the internal iterator, used for First() and Next() methods
984 sal_uInt16 m_nAct;
986 const OUString* Next_();
987 public:
988 SuggestionList();
989 ~SuggestionList();
991 void Set( const OUString& _rElement, sal_uInt16 _nNumOfElement );
992 void Reset( sal_uInt16 _nNumOfElement );
993 const OUString & Get( sal_uInt16 _nNumOfElement ) const;
994 void Clear();
996 const OUString* First();
997 const OUString* Next();
999 sal_uInt16 GetCount() const { return m_nNumOfEntries; }
1002 SuggestionList::SuggestionList() :
1003 m_vElements(MAXNUM_SUGGESTIONS)
1005 m_nAct = m_nNumOfEntries = 0;
1008 SuggestionList::~SuggestionList()
1010 Clear();
1013 void SuggestionList::Set( const OUString& _rElement, sal_uInt16 _nNumOfElement )
1015 m_vElements[_nNumOfElement] = _rElement;
1016 ++m_nNumOfEntries;
1019 void SuggestionList::Reset( sal_uInt16 _nNumOfElement )
1021 m_vElements[_nNumOfElement].clear();
1022 --m_nNumOfEntries;
1025 const OUString& SuggestionList::Get( sal_uInt16 _nNumOfElement ) const
1027 return m_vElements[_nNumOfElement];
1030 void SuggestionList::Clear()
1032 if( m_nNumOfEntries )
1034 for (auto & vElement : m_vElements)
1035 vElement.clear();
1036 m_nNumOfEntries = m_nAct = 0;
1040 const OUString* SuggestionList::Next_()
1042 while( m_nAct < m_vElements.size() )
1044 auto & s = m_vElements[ m_nAct ];
1045 if (!s.isEmpty())
1046 return &s;
1047 ++m_nAct;
1050 return nullptr;
1053 const OUString* SuggestionList::First()
1055 m_nAct = 0;
1056 return Next_();
1059 const OUString* SuggestionList::Next()
1061 const OUString* pRet;
1063 if( m_nAct < m_nNumOfEntries )
1065 ++m_nAct;
1066 pRet = Next_();
1068 else
1069 pRet = nullptr;
1071 return pRet;
1075 bool SuggestionEdit::ShouldScroll( bool _bUp ) const
1077 bool bRet = false;
1079 if( _bUp )
1081 if( !m_pPrev )
1082 bRet = m_pScrollBar->vadjustment_get_value() > m_pScrollBar->vadjustment_get_lower();
1084 else
1086 if( !m_pNext )
1087 bRet = m_pScrollBar->vadjustment_get_value() < ( m_pScrollBar->vadjustment_get_upper() - 4 );
1090 return bRet;
1093 void SuggestionEdit::DoJump( bool _bUp )
1095 m_pScrollBar->vadjustment_set_value( m_pScrollBar->vadjustment_get_value() + ( _bUp? -1 : 1 ) );
1096 m_pParent->UpdateScrollbar();
1099 SuggestionEdit::SuggestionEdit(std::unique_ptr<weld::Entry> xEntry, HangulHanjaEditDictDialog* pParent)
1100 : m_pParent(pParent)
1101 , m_pPrev(nullptr)
1102 , m_pNext(nullptr)
1103 , m_pScrollBar(nullptr)
1104 , m_xEntry(std::move(xEntry))
1106 m_xEntry->connect_key_press(LINK(this, SuggestionEdit, KeyInputHdl));
1109 IMPL_LINK(SuggestionEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
1111 bool bHandled = false;
1113 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
1114 sal_uInt16 nMod = rKeyCode.GetModifier();
1115 sal_uInt16 nCode = rKeyCode.GetCode();
1116 if( nCode == KEY_TAB && ( !nMod || KEY_SHIFT == nMod ) )
1118 bool bUp = KEY_SHIFT == nMod;
1119 if( ShouldScroll( bUp ) )
1121 DoJump( bUp );
1122 m_xEntry->select_region(0, -1);
1123 // Tab-travel doesn't really happen, so emulate it by setting a selection manually
1124 bHandled = true;
1127 else if( KEY_UP == nCode || KEY_DOWN == nCode )
1129 bool bUp = KEY_UP == nCode;
1130 if( ShouldScroll( bUp ) )
1132 DoJump( bUp );
1133 bHandled = true;
1135 else if( bUp )
1137 if( m_pPrev )
1139 m_pPrev->grab_focus();
1140 bHandled = true;
1143 else if( m_pNext )
1145 m_pNext->grab_focus();
1146 bHandled = true;
1150 return bHandled;
1153 void SuggestionEdit::init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, SuggestionEdit* pNext)
1155 m_pScrollBar = pScrollBar;
1156 m_pPrev = pPrev;
1157 m_pNext = pNext;
1160 namespace
1162 bool GetConversions( const Reference< XConversionDictionary >& _xDict,
1163 const OUString& _rOrg,
1164 Sequence< OUString >& _rEntries )
1166 bool bRet = false;
1167 if( _xDict.is() && !_rOrg.isEmpty() )
1171 _rEntries = _xDict->getConversions( _rOrg,
1173 _rOrg.getLength(),
1174 ConversionDirection_FROM_LEFT,
1175 css::i18n::TextConversionOption::NONE );
1176 bRet = _rEntries.hasElements();
1178 catch( const IllegalArgumentException& )
1183 return bRet;
1187 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, ScrollHdl, weld::ScrolledWindow&, void )
1189 UpdateScrollbar();
1192 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, OriginalModifyHdl, weld::ComboBox&, void )
1194 m_bModifiedOriginal = true;
1195 m_aOriginal = comphelper::string::stripEnd( m_xOriginalLB->get_active_text(), ' ' );
1197 UpdateSuggestions();
1198 UpdateButtonStates();
1201 IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl1, weld::Entry&, rEdit, void )
1203 EditModify( &rEdit, 0 );
1206 IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl2, weld::Entry&, rEdit, void )
1208 EditModify( &rEdit, 1 );
1211 IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl3, weld::Entry&, rEdit, void )
1213 EditModify( &rEdit, 2 );
1216 IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl4, weld::Entry&, rEdit, void )
1218 EditModify( &rEdit, 3 );
1221 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, BookLBSelectHdl, weld::ComboBox&, void )
1223 InitEditDictDialog( m_xBookLB->get_active() );
1226 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, NewPBPushHdl, weld::Button&, void )
1228 DBG_ASSERT( m_xSuggestions, "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..." );
1229 Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
1230 if( xDict.is() && m_xSuggestions )
1232 //delete old entry
1233 bool bRemovedSomething = DeleteEntryFromDictionary( xDict );
1235 OUString aLeft( m_aOriginal );
1236 const OUString* pRight = m_xSuggestions->First();
1237 bool bAddedSomething = false;
1238 while( pRight )
1242 //add new entry
1243 xDict->addEntry( aLeft, *pRight );
1244 bAddedSomething = true;
1246 catch( const IllegalArgumentException& )
1249 catch( const ElementExistException& )
1253 pRight = m_xSuggestions->Next();
1256 if( bAddedSomething || bRemovedSomething )
1257 InitEditDictDialog( m_nCurrentDict );
1259 else
1261 SAL_INFO( "cui.dialogs", "dictionary faded away..." );
1265 bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( const Reference< XConversionDictionary >& xDict )
1267 bool bRemovedSomething = false;
1268 if( xDict.is() )
1270 OUString aOrg( m_aOriginal );
1271 Sequence< OUString > aEntries;
1272 GetConversions( xDict, m_aOriginal, aEntries );
1274 sal_uInt32 n = aEntries.getLength();
1275 OUString* pEntry = aEntries.getArray();
1276 while( n )
1280 xDict->removeEntry( aOrg, *pEntry );
1281 bRemovedSomething = true;
1283 catch( const NoSuchElementException& )
1284 { // can not be...
1287 ++pEntry;
1288 --n;
1291 return bRemovedSomething;
1294 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, DeletePBPushHdl, weld::Button&, void )
1296 if( DeleteEntryFromDictionary( m_rDictList[ m_nCurrentDict ] ) )
1298 m_aOriginal.clear();
1299 m_bModifiedOriginal = true;
1300 InitEditDictDialog( m_nCurrentDict );
1304 void HangulHanjaEditDictDialog::InitEditDictDialog( sal_uInt32 nSelDict )
1306 if( m_xSuggestions )
1307 m_xSuggestions->Clear();
1309 if( m_nCurrentDict != nSelDict )
1311 m_nCurrentDict = nSelDict;
1312 m_aOriginal.clear();
1313 m_bModifiedOriginal = true;
1316 UpdateOriginalLB();
1318 m_xOriginalLB->set_entry_text( !m_aOriginal.isEmpty() ? m_aOriginal : m_aEditHintText);
1319 m_xOriginalLB->select_entry_region(0, -1);
1320 m_xOriginalLB->grab_focus();
1322 UpdateSuggestions();
1323 UpdateButtonStates();
1326 void HangulHanjaEditDictDialog::UpdateOriginalLB()
1328 m_xOriginalLB->clear();
1329 Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
1330 if( xDict.is() )
1332 Sequence< OUString > aEntries = xDict->getConversionEntries( ConversionDirection_FROM_LEFT );
1333 sal_uInt32 n = aEntries.getLength();
1334 OUString* pEntry = aEntries.getArray();
1335 while( n )
1337 m_xOriginalLB->append_text( *pEntry );
1339 ++pEntry;
1340 --n;
1343 else
1345 SAL_INFO( "cui.dialogs", "dictionary faded away..." );
1349 void HangulHanjaEditDictDialog::UpdateButtonStates()
1351 bool bHaveValidOriginalString = !m_aOriginal.isEmpty() && m_aOriginal != m_aEditHintText;
1352 bool bNew = bHaveValidOriginalString && m_xSuggestions && m_xSuggestions->GetCount() > 0;
1353 bNew = bNew && ( m_bModifiedSuggestions || m_bModifiedOriginal );
1355 m_xNewPB->set_sensitive( bNew );
1356 m_xDeletePB->set_sensitive(!m_bModifiedOriginal && bHaveValidOriginalString);
1359 void HangulHanjaEditDictDialog::UpdateSuggestions()
1361 Sequence< OUString > aEntries;
1362 bool bFound = GetConversions( m_rDictList[ m_nCurrentDict ], m_aOriginal, aEntries );
1363 if( bFound )
1365 m_bModifiedOriginal = false;
1367 if( m_xSuggestions )
1368 m_xSuggestions->Clear();
1370 //fill found entries into boxes
1371 if (aEntries.hasElements())
1373 if( !m_xSuggestions )
1374 m_xSuggestions.reset(new SuggestionList);
1376 for (sal_Int32 n = 0; n < aEntries.getLength(); ++n)
1377 m_xSuggestions->Set(aEntries[n], n);
1379 m_bModifiedSuggestions = false;
1382 m_xScrollSB->vadjustment_set_value( 0 );
1383 UpdateScrollbar(); // will force edits to be filled new
1386 void HangulHanjaEditDictDialog::SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum)
1388 OUString aStr;
1389 if( m_xSuggestions )
1391 aStr = m_xSuggestions->Get(nEntryNum);
1394 rEdit.set_text(aStr);
1397 void HangulHanjaEditDictDialog::EditModify(const weld::Entry* pEdit, sal_uInt8 _nEntryOffset)
1399 m_bModifiedSuggestions = true;
1401 OUString aTxt( pEdit->get_text() );
1402 sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset;
1403 if( aTxt.isEmpty() )
1405 //reset suggestion
1406 if( m_xSuggestions )
1407 m_xSuggestions->Reset( nEntryNum );
1409 else
1411 //set suggestion
1412 if( !m_xSuggestions )
1413 m_xSuggestions.reset(new SuggestionList);
1414 m_xSuggestions->Set( aTxt, nEntryNum );
1417 UpdateButtonStates();
1420 HangulHanjaEditDictDialog::HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& _rDictList, sal_uInt32 nSelDict)
1421 : GenericDialogController(pParent, u"cui/ui/hangulhanjaeditdictdialog.ui"_ustr, u"HangulHanjaEditDictDialog"_ustr)
1422 , m_aEditHintText ( CuiResId(RID_CUISTR_EDITHINT) )
1423 , m_rDictList ( _rDictList )
1424 , m_nCurrentDict ( 0xFFFFFFFF )
1425 , m_nTopPos ( 0 )
1426 , m_bModifiedSuggestions ( false )
1427 , m_bModifiedOriginal ( false )
1428 , m_xBookLB(m_xBuilder->weld_combo_box(u"book"_ustr))
1429 , m_xOriginalLB(m_xBuilder->weld_combo_box(u"original"_ustr))
1430 , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry(u"edit1"_ustr), this))
1431 , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry(u"edit2"_ustr), this))
1432 , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry(u"edit3"_ustr), this))
1433 , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry(u"edit4"_ustr), this))
1434 , m_xContents(m_xBuilder->weld_widget(u"box"_ustr))
1435 , m_xScrollSB(m_xBuilder->weld_scrolled_window(u"scrollbar"_ustr, true))
1436 , m_xNewPB(m_xBuilder->weld_button(u"new"_ustr))
1437 , m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr))
1439 Size aSize(m_xContents->get_preferred_size());
1440 m_xScrollSB->set_size_request(-1, aSize.Height());
1442 m_xEdit1->init( m_xScrollSB.get(), nullptr, m_xEdit2.get() );
1443 m_xEdit2->init( m_xScrollSB.get(), m_xEdit1.get(), m_xEdit3.get() );
1444 m_xEdit3->init( m_xScrollSB.get(), m_xEdit2.get(), m_xEdit4.get() );
1445 m_xEdit4->init( m_xScrollSB.get(), m_xEdit3.get(), nullptr );
1447 m_xOriginalLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, OriginalModifyHdl ) );
1449 m_xNewPB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, NewPBPushHdl ) );
1450 m_xNewPB->set_sensitive( false );
1452 m_xDeletePB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, DeletePBPushHdl ) );
1453 m_xDeletePB->set_sensitive( false );
1455 static_assert(MAXNUM_SUGGESTIONS >= 5, "number of suggestions should not under-run the value of 5");
1457 // 4 here, because we have 4 edits / page
1458 m_xScrollSB->vadjustment_configure(0, 0, MAXNUM_SUGGESTIONS, 1, 4, 4);
1459 m_xScrollSB->connect_vadjustment_changed(LINK(this, HangulHanjaEditDictDialog, ScrollHdl));
1461 m_xEdit1->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl1 ) );
1462 m_xEdit2->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl2 ) );
1463 m_xEdit3->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl3 ) );
1464 m_xEdit4->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl4 ) );
1466 m_xBookLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, BookLBSelectHdl ) );
1467 sal_uInt32 nDictCnt = m_rDictList.size();
1468 for( sal_uInt32 n = 0 ; n < nDictCnt ; ++n )
1470 Reference< XConversionDictionary > xDic( m_rDictList[n] );
1471 OUString aName;
1472 if( xDic.is() )
1473 aName = xDic->getName();
1474 m_xBookLB->append_text( aName );
1476 m_xBookLB->set_active(nSelDict);
1478 InitEditDictDialog(nSelDict);
1481 HangulHanjaEditDictDialog::~HangulHanjaEditDictDialog()
1485 void HangulHanjaEditDictDialog::UpdateScrollbar()
1487 sal_uInt16 nPos = m_xScrollSB->vadjustment_get_value();
1488 m_nTopPos = nPos;
1490 SetEditText( *m_xEdit1, nPos++ );
1491 SetEditText( *m_xEdit2, nPos++ );
1492 SetEditText( *m_xEdit3, nPos++ );
1493 SetEditText( *m_xEdit4, nPos );
1497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */