bump product version to 6.3.0.0.beta1
[LibreOffice.git] / cui / source / dialogs / hangulhanjadlg.cxx
blob342b353527823e8cce4ebbec81ff72af825d012f
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/svapp.hxx>
32 #include <vcl/virdev.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( PushFlags::FONT );
72 m_rDev.SetFont( _rTemporaryFont );
74 ~FontSwitch() COVERITY_NOEXCEPT_FALSE
76 m_rDev.Pop();
81 /** a class which allows to draw two texts in a pseudo-ruby way (which basically
82 means one text above or below the other, and a little bit smaller)
84 class PseudoRubyText
86 public:
87 enum RubyPosition
89 eAbove, eBelow
92 protected:
93 OUString m_sPrimaryText;
94 OUString m_sSecondaryText;
95 RubyPosition m_ePosition;
97 public:
98 PseudoRubyText();
99 void init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition );
100 const OUString& getPrimaryText() const { return m_sPrimaryText; }
101 const OUString& getSecondaryText() const { return m_sSecondaryText; }
103 public:
104 void Paint( vcl::RenderContext& _rDevice, const ::tools::Rectangle& _rRect, DrawTextFlags _nTextStyle,
105 ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation );
108 PseudoRubyText::PseudoRubyText()
109 : m_ePosition(eAbove)
113 void PseudoRubyText::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition )
115 m_sPrimaryText = rPrimaryText;
116 m_sSecondaryText = rSecondaryText;
117 m_ePosition = rPosition;
121 void PseudoRubyText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& _rRect, DrawTextFlags _nTextStyle,
122 ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation )
124 Size aPlaygroundSize(_rRect.GetSize());
126 // the font for the secondary text:
127 vcl::Font aSmallerFont(rRenderContext.GetFont());
128 // heuristic: 80% of the original size
129 aSmallerFont.SetFontHeight( static_cast<long>( 0.8 * aSmallerFont.GetFontHeight() ) );
131 // let's calculate the size of our two texts
132 ::tools::Rectangle aPrimaryRect = rRenderContext.GetTextRect( _rRect, m_sPrimaryText, _nTextStyle );
133 ::tools::Rectangle aSecondaryRect;
135 FontSwitch aFontRestore(rRenderContext, aSmallerFont);
136 aSecondaryRect = rRenderContext.GetTextRect(_rRect, m_sSecondaryText, _nTextStyle);
139 // position these rectangles properly
140 // x-axis:
141 sal_Int32 nCombinedWidth = std::max( aSecondaryRect.GetWidth(), aPrimaryRect.GetWidth() );
142 // the rectangle where both texts will reside is as high as possible, and as wide as the
143 // widest of both text rects
144 aPrimaryRect.SetLeft( _rRect.Left() );
145 aSecondaryRect.SetLeft( aPrimaryRect.Left() );
146 aPrimaryRect.SetRight( _rRect.Left() + nCombinedWidth );
147 aSecondaryRect.SetRight( aPrimaryRect.Right() );
148 if (DrawTextFlags::Right & _nTextStyle)
150 // move the rectangles to the right
151 aPrimaryRect.Move( aPlaygroundSize.Width() - nCombinedWidth, 0 );
152 aSecondaryRect.Move( aPlaygroundSize.Width() - nCombinedWidth, 0 );
154 else if (DrawTextFlags::Center & _nTextStyle)
156 // center the rectangles
157 aPrimaryRect.Move( ( aPlaygroundSize.Width() - nCombinedWidth ) / 2, 0 );
158 aSecondaryRect.Move( ( aPlaygroundSize.Width() - nCombinedWidth ) / 2, 0 );
161 // y-axis:
162 sal_Int32 nCombinedHeight = aPrimaryRect.GetHeight() + aSecondaryRect.GetHeight();
163 // align to the top, for the moment
164 aPrimaryRect.Move( 0, _rRect.Top() - aPrimaryRect.Top() );
165 aSecondaryRect.Move( 0, aPrimaryRect.Top() + aPrimaryRect.GetHeight() - aSecondaryRect.Top() );
166 if (DrawTextFlags::Bottom & _nTextStyle)
168 // move the rects to the bottom
169 aPrimaryRect.Move( 0, aPlaygroundSize.Height() - nCombinedHeight );
170 aSecondaryRect.Move( 0, aPlaygroundSize.Height() - nCombinedHeight );
172 else if (DrawTextFlags::VCenter & _nTextStyle)
174 // move the rects to the bottom
175 aPrimaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 );
176 aSecondaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 );
179 // 'til here, everything we did assumes that the secondary text is painted _below_ the primary
180 // text. If this isn't the case, we need to correct the rectangles
181 if (eAbove == m_ePosition)
183 sal_Int32 nVertDistance = aSecondaryRect.Top() - aPrimaryRect.Top();
184 aSecondaryRect.Move( 0, -nVertDistance );
185 aPrimaryRect.Move( 0, nCombinedHeight - nVertDistance );
188 // now draw the texts
189 // as we already calculated the precise rectangles for the texts, we don't want to
190 // use the alignment flags given - within it's rect, every text is centered
191 DrawTextFlags nDrawTextStyle( _nTextStyle );
192 nDrawTextStyle &= ~DrawTextFlags( DrawTextFlags::Right | DrawTextFlags::Left | DrawTextFlags::Bottom | DrawTextFlags::Top );
193 nDrawTextStyle |= DrawTextFlags::Center | DrawTextFlags::VCenter;
195 rRenderContext.DrawText( aPrimaryRect, m_sPrimaryText, nDrawTextStyle );
197 FontSwitch aFontRestore(rRenderContext, aSmallerFont);
198 rRenderContext.DrawText( aSecondaryRect, m_sSecondaryText, nDrawTextStyle );
201 // outta here
202 if (_pPrimaryLocation)
203 *_pPrimaryLocation = aPrimaryRect;
204 if (_pSecondaryLocation)
205 *_pSecondaryLocation = aSecondaryRect;
208 class RubyRadioButton
210 public:
211 RubyRadioButton(std::unique_ptr<weld::RadioButton> xControl);
212 void init(const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition);
214 void set_sensitive(bool sensitive) { m_xControl->set_sensitive(sensitive); }
215 void set_active(bool active) { m_xControl->set_active(active); }
216 bool get_active() const { return m_xControl->get_active(); }
218 void connect_clicked(const Link<weld::Button&, void>& rLink) { m_xControl->connect_clicked(rLink); }
220 private:
221 Size GetOptimalSize() const;
222 void Paint(vcl::RenderContext& rRenderContext);
224 ScopedVclPtr<VirtualDevice> m_xVirDev;
225 std::unique_ptr<weld::RadioButton> m_xControl;
226 PseudoRubyText m_aRubyText;
229 RubyRadioButton::RubyRadioButton(std::unique_ptr<weld::RadioButton> xControl)
230 : m_xVirDev(xControl->create_virtual_device())
231 , m_xControl(std::move(xControl))
233 // expand the point size of the desired font to the equivalent pixel size
234 if (vcl::Window* pDefaultDevice = dynamic_cast<vcl::Window*>(Application::GetDefaultDevice()))
235 pDefaultDevice->SetPointFont(*m_xVirDev, m_xControl->get_font());
238 void RubyRadioButton::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition )
240 m_aRubyText.init(rPrimaryText, rSecondaryText, rPosition);
242 m_xVirDev->SetOutputSizePixel(GetOptimalSize());
244 Paint(*m_xVirDev);
246 m_xControl->set_image(m_xVirDev.get());
249 void RubyRadioButton::Paint(vcl::RenderContext& rRenderContext)
251 ::tools::Rectangle aOverallRect(Point(0, 0), rRenderContext.GetOutputSizePixel());
252 // inflate the rect a little bit (because the VCL radio button does the same)
253 ::tools::Rectangle aTextRect( aOverallRect );
254 aTextRect.AdjustLeft( 1 ); aTextRect.AdjustRight( -1 );
255 aTextRect.AdjustTop( 1 ); aTextRect.AdjustBottom( -1 );
257 // calculate the text flags for the painting
258 DrawTextFlags nTextStyle = DrawTextFlags::Mnemonic |
259 DrawTextFlags::Left |
260 DrawTextFlags::VCenter;
262 // paint the ruby text
263 ::tools::Rectangle aPrimaryTextLocation;
264 ::tools::Rectangle aSecondaryTextLocation;
266 m_aRubyText.Paint(rRenderContext, aTextRect, nTextStyle, &aPrimaryTextLocation, &aSecondaryTextLocation);
269 Size RubyRadioButton::GetOptimalSize() const
271 vcl::Font aSmallerFont(m_xVirDev->GetFont());
272 aSmallerFont.SetFontHeight( static_cast<long>( 0.8 * aSmallerFont.GetFontHeight() ) );
273 ::tools::Rectangle rect( Point(), Size( SAL_MAX_INT32, SAL_MAX_INT32 ) );
275 Size aPrimarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getPrimaryText() ).GetSize();
276 Size aSecondarySize;
278 FontSwitch aFontRestore(*m_xVirDev, aSmallerFont);
279 aSecondarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getSecondaryText() ).GetSize();
282 Size minimumSize;
283 minimumSize.setHeight( aPrimarySize.Height() + aSecondarySize.Height() + 5 );
284 minimumSize.setWidth( aPrimarySize.Width() + aSecondarySize.Width() + 5 );
285 return minimumSize;
288 SuggestionSet::SuggestionSet(std::unique_ptr<weld::ScrolledWindow> xScrolledWindow)
289 : SvtValueSet(std::move(xScrolledWindow))
294 void SuggestionSet::UserDraw( const UserDrawEvent& rUDEvt )
296 vcl::RenderContext* pDev = rUDEvt.GetRenderContext();
297 ::tools::Rectangle aRect = rUDEvt.GetRect();
298 sal_uInt16 nItemId = rUDEvt.GetItemId();
300 OUString sText = *static_cast< OUString* >( GetItemData( nItemId ) );
301 pDev->DrawText( aRect, sText, DrawTextFlags::Center | DrawTextFlags::VCenter );
304 SuggestionDisplay::SuggestionDisplay(weld::Builder& rBuilder)
305 : m_bDisplayListBox( true )
306 , m_bInSelectionUpdate( false )
307 , m_xValueSet(new SuggestionSet(rBuilder.weld_scrolled_window("scrollwin")))
308 , m_xValueSetWin(new weld::CustomWeld(rBuilder, "valueset", *m_xValueSet))
309 , m_xListBox(rBuilder.weld_tree_view("listbox"))
311 m_xValueSet->SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionValueSetHdl ) );
312 m_xListBox->connect_changed( LINK( this, SuggestionDisplay, SelectSuggestionListBoxHdl ) );
314 m_xValueSet->SetLineCount( LINE_CNT );
315 m_xValueSet->SetStyle( m_xValueSet->GetStyle() | WB_ITEMBORDER | WB_VSCROLL );
317 OUString const aOneCharacter("AU");
318 auto nItemWidth = 2 * m_xListBox->get_pixel_size(aOneCharacter).Width();
319 m_xValueSet->SetItemWidth( nItemWidth );
321 Size aSize(m_xListBox->get_approximate_digit_width() * 42, m_xListBox->get_text_height() * 5);
322 m_xValueSet->set_size_request(aSize.Width(), aSize.Height());
323 m_xListBox->set_size_request(aSize.Width(), aSize.Height());
325 implUpdateDisplay();
328 void SuggestionDisplay::implUpdateDisplay()
330 m_xListBox->set_visible(m_bDisplayListBox);
331 if (!m_bDisplayListBox)
332 m_xValueSetWin->show();
333 else
334 m_xValueSetWin->hide();
337 weld::Widget& SuggestionDisplay::implGetCurrentControl()
339 if (m_bDisplayListBox)
340 return *m_xListBox;
341 return *m_xValueSet->GetDrawingArea();
344 void SuggestionDisplay::DisplayListBox( bool bDisplayListBox )
346 if( m_bDisplayListBox != bDisplayListBox )
348 weld::Widget& rOldControl = implGetCurrentControl();
349 bool bHasFocus = rOldControl.has_focus();
351 m_bDisplayListBox = bDisplayListBox;
353 if( bHasFocus )
355 weld::Widget& rNewControl = implGetCurrentControl();
356 rNewControl.grab_focus();
359 implUpdateDisplay();
363 IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionValueSetHdl, SvtValueSet*, void)
365 SelectSuggestionHdl(false);
368 IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionListBoxHdl, weld::TreeView&, void)
370 SelectSuggestionHdl(true);
373 void SuggestionDisplay::SelectSuggestionHdl(bool bListBox)
375 if( m_bInSelectionUpdate )
376 return;
378 m_bInSelectionUpdate = true;
379 if (bListBox)
381 sal_uInt16 nPos = m_xListBox->get_selected_index();
382 m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
384 else
386 sal_uInt16 nPos = m_xValueSet->GetSelectedItemId()-1; //itemid == pos+1 (id 0 has special meaning)
387 m_xListBox->select(nPos);
389 m_bInSelectionUpdate = false;
390 m_aSelectLink.Call( *this );
393 void SuggestionDisplay::SetSelectHdl( const Link<SuggestionDisplay&,void>& rLink )
395 m_aSelectLink = rLink;
398 void SuggestionDisplay::Clear()
400 m_xListBox->clear();
401 m_xValueSet->Clear();
404 void SuggestionDisplay::InsertEntry( const OUString& rStr )
406 m_xListBox->append_text(rStr);
407 sal_uInt16 nItemId = m_xListBox->n_children(); //itemid == pos+1 (id 0 has special meaning)
408 m_xValueSet->InsertItem( nItemId );
409 OUString* pItemData = new OUString( rStr );
410 m_xValueSet->SetItemData( nItemId, pItemData );
413 void SuggestionDisplay::SelectEntryPos( sal_uInt16 nPos )
415 m_xListBox->select(nPos);
416 m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
419 sal_uInt16 SuggestionDisplay::GetEntryCount() const
421 return m_xListBox->n_children();
424 OUString SuggestionDisplay::GetEntry( sal_uInt16 nPos ) const
426 return m_xListBox->get_text( nPos );
429 OUString SuggestionDisplay::GetSelectedEntry() const
431 return m_xListBox->get_selected_text();
434 void SuggestionDisplay::SetHelpIds()
436 m_xValueSet->SetHelpId(HID_HANGULDLG_SUGGESTIONS_GRID);
437 m_xListBox->set_help_id(HID_HANGULDLG_SUGGESTIONS_LIST);
440 HangulHanjaConversionDialog::HangulHanjaConversionDialog(weld::Window* pParent)
441 : GenericDialogController(pParent, "cui/ui/hangulhanjaconversiondialog.ui", "HangulHanjaConversionDialog")
442 , m_bDocumentMode( true )
443 , m_xFind(m_xBuilder->weld_button("find"))
444 , m_xIgnore(m_xBuilder->weld_button("ignore"))
445 , m_xIgnoreAll(m_xBuilder->weld_button("ignoreall"))
446 , m_xReplace(m_xBuilder->weld_button("replace"))
447 , m_xReplaceAll(m_xBuilder->weld_button("replaceall"))
448 , m_xOptions(m_xBuilder->weld_button("options"))
449 , m_xSuggestions(new SuggestionDisplay(*m_xBuilder))
450 , m_xSimpleConversion(m_xBuilder->weld_radio_button("simpleconversion"))
451 , m_xHangulBracketed(m_xBuilder->weld_radio_button("hangulbracket"))
452 , m_xHanjaBracketed(m_xBuilder->weld_radio_button("hanjabracket"))
453 , m_xWordInput(m_xBuilder->weld_entry("wordinput"))
454 , m_xOriginalWord(m_xBuilder->weld_label("originalword"))
455 , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_above")))
456 , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_below")))
457 , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_above")))
458 , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_below")))
459 , m_xHangulOnly(m_xBuilder->weld_check_button("hangulonly"))
460 , m_xHanjaOnly(m_xBuilder->weld_check_button("hanjaonly"))
461 , m_xReplaceByChar(m_xBuilder->weld_check_button("replacebychar"))
463 m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42,
464 m_xOriginalWord->get_text_height() * 5);
466 const OUString sHangul(CuiResId(RID_SVXSTR_HANGUL));
467 const OUString sHanja(CuiResId(RID_SVXSTR_HANJA));
468 m_xHanjaAbove->init( sHangul, sHanja, PseudoRubyText::eAbove );
469 m_xHanjaBelow->init( sHangul, sHanja, PseudoRubyText::eBelow );
470 m_xHangulAbove->init( sHanja, sHangul, PseudoRubyText::eAbove );
471 m_xHangulBelow->init( sHanja, sHangul, PseudoRubyText::eBelow );
473 m_xWordInput->connect_changed( LINK( this, HangulHanjaConversionDialog, OnSuggestionModified ) );
474 m_xSuggestions->SetSelectHdl( LINK( this, HangulHanjaConversionDialog, OnSuggestionSelected ) );
475 m_xReplaceByChar->connect_toggled( LINK( this, HangulHanjaConversionDialog, ClickByCharacterHdl ) );
476 m_xHangulOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
477 m_xHanjaOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
478 m_xOptions->connect_clicked(LINK(this, HangulHanjaConversionDialog, OnOption));
480 // initial focus
481 FocusSuggestion( );
483 // initial control values
484 m_xSimpleConversion->set_active(true);
486 m_xSuggestions->SetHelpIds();
489 HangulHanjaConversionDialog::~HangulHanjaConversionDialog()
493 void HangulHanjaConversionDialog::FillSuggestions( const css::uno::Sequence< OUString >& _rSuggestions )
495 m_xSuggestions->Clear();
496 for ( auto const & suggestion : _rSuggestions )
497 m_xSuggestions->InsertEntry( suggestion );
499 // select the first suggestion, and fill in the suggestion edit field
500 OUString sFirstSuggestion;
501 if ( m_xSuggestions->GetEntryCount() )
503 sFirstSuggestion = m_xSuggestions->GetEntry( 0 );
504 m_xSuggestions->SelectEntryPos( 0 );
506 m_xWordInput->set_text( sFirstSuggestion );
507 m_xWordInput->save_value();
508 OnSuggestionModified( *m_xWordInput );
511 void HangulHanjaConversionDialog::SetOptionsChangedHdl(const Link<LinkParamNone*,void>& rHdl)
513 m_aOptionsChangedLink = rHdl;
516 void HangulHanjaConversionDialog::SetIgnoreHdl(const Link<weld::Button&,void>& rHdl)
518 m_xIgnore->connect_clicked(rHdl);
521 void HangulHanjaConversionDialog::SetIgnoreAllHdl(const Link<weld::Button&,void>& rHdl)
523 m_xIgnoreAll->connect_clicked(rHdl);
526 void HangulHanjaConversionDialog::SetChangeHdl(const Link<weld::Button&,void>& rHdl )
528 m_xReplace->connect_clicked(rHdl);
531 void HangulHanjaConversionDialog::SetChangeAllHdl(const Link<weld::Button&,void>& rHdl)
533 m_xReplaceAll->connect_clicked(rHdl);
536 void HangulHanjaConversionDialog::SetFindHdl(const Link<weld::Button&,void>& rHdl)
538 m_xFind->connect_clicked(rHdl);
541 void HangulHanjaConversionDialog::SetConversionFormatChangedHdl( const Link<weld::Button&,void>& rHdl )
543 m_xSimpleConversion->connect_clicked( rHdl );
544 m_xHangulBracketed->connect_clicked( rHdl );
545 m_xHanjaBracketed->connect_clicked( rHdl );
546 m_xHanjaAbove->connect_clicked( rHdl );
547 m_xHanjaBelow->connect_clicked( rHdl );
548 m_xHangulAbove->connect_clicked( rHdl );
549 m_xHangulBelow->connect_clicked( rHdl );
552 void HangulHanjaConversionDialog::SetClickByCharacterHdl( const Link<weld::ToggleButton&,void>& _rHdl )
554 m_aClickByCharacterLink = _rHdl;
557 IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionSelected, SuggestionDisplay&, void )
559 m_xWordInput->set_text(m_xSuggestions->GetSelectedEntry());
560 OnSuggestionModified( *m_xWordInput );
563 IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionModified, weld::Entry&, void )
565 m_xFind->set_sensitive(m_xWordInput->get_value_changed_from_saved());
567 bool bSameLen = m_xWordInput->get_text().getLength() == m_xOriginalWord->get_label().getLength();
568 m_xReplace->set_sensitive( m_bDocumentMode && bSameLen );
569 m_xReplaceAll->set_sensitive( m_bDocumentMode && bSameLen );
572 IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::ToggleButton&, rBox, void)
574 m_aClickByCharacterLink.Call(rBox);
575 bool bByCharacter = rBox.get_active();
576 m_xSuggestions->DisplayListBox( !bByCharacter );
579 IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::ToggleButton&, rBox, void)
581 weld::CheckButton* pOtherBox = nullptr;
582 if (&rBox == m_xHangulOnly.get())
583 pOtherBox = m_xHanjaOnly.get();
584 else
585 pOtherBox = m_xHangulOnly.get();
586 bool bBoxChecked = rBox.get_active();
587 if (bBoxChecked)
588 pOtherBox->set_active(false);
589 pOtherBox->set_sensitive(!bBoxChecked);
592 IMPL_LINK_NOARG(HangulHanjaConversionDialog, OnOption, weld::Button&, void)
594 HangulHanjaOptionsDialog aOptDlg(m_xDialog.get());
595 aOptDlg.run();
596 m_aOptionsChangedLink.Call( nullptr );
599 OUString HangulHanjaConversionDialog::GetCurrentString( ) const
601 return m_xOriginalWord->get_label();
604 void HangulHanjaConversionDialog::FocusSuggestion( )
606 m_xWordInput->grab_focus();
609 void HangulHanjaConversionDialog::SetCurrentString( const OUString& _rNewString,
610 const Sequence< OUString >& _rSuggestions, bool _bOriginatesFromDocument )
612 m_xOriginalWord->set_label(_rNewString);
614 bool bOldDocumentMode = m_bDocumentMode;
615 m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions!
616 FillSuggestions( _rSuggestions );
618 m_xIgnoreAll->set_sensitive( m_bDocumentMode );
620 // switch the def button depending if we're working for document text
621 if (bOldDocumentMode != m_bDocumentMode)
623 weld::Widget* pOldDefButton = nullptr;
624 weld::Widget* pNewDefButton = nullptr;
625 if (m_bDocumentMode)
627 pOldDefButton = m_xFind.get();
628 pNewDefButton = m_xReplace.get();
630 else
632 pOldDefButton = m_xReplace.get();
633 pNewDefButton = m_xFind.get();
636 pOldDefButton->set_has_default(false);
637 pNewDefButton->set_has_default(true);
641 OUString HangulHanjaConversionDialog::GetCurrentSuggestion( ) const
643 return m_xWordInput->get_text();
646 void HangulHanjaConversionDialog::SetByCharacter( bool _bByCharacter )
648 m_xReplaceByChar->set_active( _bByCharacter );
649 m_xSuggestions->DisplayListBox( !_bByCharacter );
652 void HangulHanjaConversionDialog::SetConversionDirectionState(
653 bool _bTryBothDirections,
654 HHC::ConversionDirection ePrimaryConversionDirection )
656 // default state: try both direction
657 m_xHangulOnly->set_active( false );
658 m_xHangulOnly->set_sensitive(true);
659 m_xHanjaOnly->set_active( false );
660 m_xHanjaOnly->set_sensitive(true);
662 if (!_bTryBothDirections)
664 weld::CheckButton* pBox = ePrimaryConversionDirection == HHC::eHangulToHanja ?
665 m_xHangulOnly.get() : m_xHanjaOnly.get();
666 pBox->set_active(true);
667 OnConversionDirectionClicked(*pBox);
671 bool HangulHanjaConversionDialog::GetUseBothDirections( ) const
673 return !m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active();
676 HHC::ConversionDirection HangulHanjaConversionDialog::GetDirection(
677 HHC::ConversionDirection eDefaultDirection ) const
679 HHC::ConversionDirection eDirection = eDefaultDirection;
680 if (m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active())
681 eDirection = HHC::eHangulToHanja;
682 else if (!m_xHangulOnly->get_active() && m_xHanjaOnly->get_active())
683 eDirection = HHC::eHanjaToHangul;
684 return eDirection;
687 void HangulHanjaConversionDialog::SetConversionFormat( HHC::ConversionFormat _eType )
689 switch ( _eType )
691 case HHC::eSimpleConversion: m_xSimpleConversion->set_active(true); break;
692 case HHC::eHangulBracketed: m_xHangulBracketed->set_active(true); break;
693 case HHC::eHanjaBracketed: m_xHanjaBracketed->set_active(true); break;
694 case HHC::eRubyHanjaAbove: m_xHanjaAbove->set_active(true); break;
695 case HHC::eRubyHanjaBelow: m_xHanjaBelow->set_active(true); break;
696 case HHC::eRubyHangulAbove: m_xHangulAbove->set_active(true); break;
697 case HHC::eRubyHangulBelow: m_xHangulBelow->set_active(true); break;
698 default:
699 OSL_FAIL( "HangulHanjaConversionDialog::SetConversionFormat: unknown type!" );
703 HHC::ConversionFormat HangulHanjaConversionDialog::GetConversionFormat( ) const
705 if ( m_xSimpleConversion->get_active() )
706 return HHC::eSimpleConversion;
707 if ( m_xHangulBracketed->get_active() )
708 return HHC::eHangulBracketed;
709 if ( m_xHanjaBracketed->get_active() )
710 return HHC::eHanjaBracketed;
711 if ( m_xHanjaAbove->get_active() )
712 return HHC::eRubyHanjaAbove;
713 if ( m_xHanjaBelow->get_active() )
714 return HHC::eRubyHanjaBelow;
715 if ( m_xHangulAbove->get_active() )
716 return HHC::eRubyHangulAbove;
717 if ( m_xHangulBelow->get_active() )
718 return HHC::eRubyHangulBelow;
720 OSL_FAIL( "HangulHanjaConversionDialog::GetConversionFormat: no radio checked?" );
721 return HHC::eSimpleConversion;
724 void HangulHanjaConversionDialog::EnableRubySupport( bool bVal )
726 m_xHanjaAbove->set_sensitive( bVal );
727 m_xHanjaBelow->set_sensitive( bVal );
728 m_xHangulAbove->set_sensitive( bVal );
729 m_xHangulBelow->set_sensitive( bVal );
732 void HangulHanjaOptionsDialog::Init()
734 if( !m_xConversionDictionaryList.is() )
736 m_xConversionDictionaryList = ConversionDictionaryList::create( ::comphelper::getProcessComponentContext() );
739 m_aDictList.clear();
740 m_xDictsLB->clear();
742 Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
743 if( xNameCont.is() )
745 Sequence< OUString > aDictNames( xNameCont->getElementNames() );
747 const OUString* pDic = aDictNames.getConstArray();
748 sal_Int32 nCount = aDictNames.getLength();
750 sal_Int32 i;
751 for( i = 0 ; i < nCount ; ++i )
753 Any aAny( xNameCont->getByName( pDic[ i ] ) );
754 Reference< XConversionDictionary > xDic;
755 if( ( aAny >>= xDic ) && xDic.is() )
757 if( LANGUAGE_KOREAN == LanguageTag( xDic->getLocale() ).getLanguageType() )
759 m_aDictList.push_back( xDic );
760 AddDict( xDic->getName(), xDic->isActive() );
765 if (m_xDictsLB->n_children())
766 m_xDictsLB->select(0);
769 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, OkHdl, weld::Button&, void)
771 sal_uInt32 nCnt = m_aDictList.size();
772 sal_uInt32 n = 0;
773 sal_uInt32 nActiveDics = 0;
774 Sequence< OUString > aActiveDics;
776 aActiveDics.realloc( nCnt );
777 OUString* pActActiveDic = aActiveDics.getArray();
779 while( nCnt )
781 Reference< XConversionDictionary > xDict = m_aDictList[ n ];
783 DBG_ASSERT( xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..." );
785 bool bActive = m_xDictsLB->get_toggle(n, 0) == TRISTATE_TRUE;
786 xDict->setActive( bActive );
787 Reference< util::XFlushable > xFlush( xDict, uno::UNO_QUERY );
788 if( xFlush.is() )
789 xFlush->flush();
791 if( bActive )
793 pActActiveDic[ nActiveDics ] = xDict->getName();
794 ++nActiveDics;
797 ++n;
798 --nCnt;
801 // save configuration
802 aActiveDics.realloc( nActiveDics );
803 Any aTmp;
804 SvtLinguConfig aLngCfg;
805 aTmp <<= aActiveDics;
806 aLngCfg.SetProperty( UPH_ACTIVE_CONVERSION_DICTIONARIES, aTmp );
808 aTmp <<= m_xIgnorepostCB->get_active();
809 aLngCfg.SetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD, aTmp );
811 aTmp <<= m_xShowrecentlyfirstCB->get_active();
812 aLngCfg.SetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, aTmp );
814 aTmp <<= m_xAutoreplaceuniqueCB->get_active();
815 aLngCfg.SetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES, aTmp );
817 m_xDialog->response(RET_OK);
820 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DictsLB_SelectHdl, weld::TreeView&, void)
822 bool bSel = m_xDictsLB->get_selected_index() != -1;
824 m_xEditPB->set_sensitive(bSel);
825 m_xDeletePB->set_sensitive(bSel);
828 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, NewDictHdl, weld::Button&, void)
830 OUString aName;
831 HangulHanjaNewDictDialog aNewDlg(m_xDialog.get());
832 aNewDlg.run();
833 if (aNewDlg.GetName(aName))
835 if( m_xConversionDictionaryList.is() )
839 Reference< XConversionDictionary > xDic =
840 m_xConversionDictionaryList->addNewDictionary( aName, LanguageTag::convertToLocale( LANGUAGE_KOREAN ), ConversionDictionaryType::HANGUL_HANJA );
842 if( xDic.is() )
844 //adapt local caches:
845 m_aDictList.push_back( xDic );
846 AddDict( xDic->getName(), xDic->isActive() );
849 catch( const ElementExistException& )
852 catch( const NoSupportException& )
859 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, EditDictHdl, weld::Button&, void)
861 int nEntry = m_xDictsLB->get_selected_index();
862 DBG_ASSERT(nEntry != -1, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not be possible with no selection!");
863 if (nEntry != -1)
865 HangulHanjaEditDictDialog aEdDlg(m_xDialog.get(), m_aDictList, nEntry);
866 aEdDlg.run();
870 IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DeleteDictHdl, weld::Button&, void)
872 int nSelPos = m_xDictsLB->get_selected_index();
873 if (nSelPos != -1)
875 Reference< XConversionDictionary > xDic( m_aDictList[ nSelPos ] );
876 if( m_xConversionDictionaryList.is() && xDic.is() )
878 Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
879 if( xNameCont.is() )
883 xNameCont->removeByName( xDic->getName() );
885 //adapt local caches:
886 m_aDictList.erase(m_aDictList.begin()+nSelPos );
887 m_xDictsLB->remove(nSelPos);
889 catch( const ElementExistException& )
892 catch( const NoSupportException& )
900 HangulHanjaOptionsDialog::HangulHanjaOptionsDialog(weld::Window* pParent)
901 : GenericDialogController(pParent, "cui/ui/hangulhanjaoptdialog.ui", "HangulHanjaOptDialog")
902 , m_xDictsLB(m_xBuilder->weld_tree_view("dicts"))
903 , m_xIgnorepostCB(m_xBuilder->weld_check_button("ignorepost"))
904 , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button("showrecentfirst"))
905 , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button("autoreplaceunique"))
906 , m_xNewPB(m_xBuilder->weld_button("new"))
907 , m_xEditPB(m_xBuilder->weld_button("edit"))
908 , m_xDeletePB(m_xBuilder->weld_button("delete"))
909 , m_xOkPB(m_xBuilder->weld_button("ok"))
911 m_xDictsLB->set_size_request(m_xDictsLB->get_approximate_digit_width() * 32,
912 m_xDictsLB->get_height_rows(5));
914 std::vector<int> aWidths;
915 aWidths.push_back(m_xDictsLB->get_checkbox_column_width());
916 m_xDictsLB->set_column_fixed_widths(aWidths);
918 m_xDictsLB->connect_changed( LINK( this, HangulHanjaOptionsDialog, DictsLB_SelectHdl ) );
920 m_xOkPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, OkHdl ) );
921 m_xNewPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, NewDictHdl ) );
922 m_xEditPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, EditDictHdl ) );
923 m_xDeletePB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, DeleteDictHdl ) );
925 SvtLinguConfig aLngCfg;
926 Any aTmp;
927 bool bVal = bool();
928 aTmp = aLngCfg.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD );
929 if( aTmp >>= bVal )
930 m_xIgnorepostCB->set_active( bVal );
932 aTmp = aLngCfg.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST );
933 if( aTmp >>= bVal )
934 m_xShowrecentlyfirstCB->set_active( bVal );
936 aTmp = aLngCfg.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES );
937 if( aTmp >>= bVal )
938 m_xAutoreplaceuniqueCB->set_active( bVal );
940 Init();
943 HangulHanjaOptionsDialog::~HangulHanjaOptionsDialog()
947 void HangulHanjaOptionsDialog::AddDict(const OUString& rName, bool bChecked)
949 m_xDictsLB->append();
950 int nRow = m_xDictsLB->n_children() - 1;
951 m_xDictsLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE, 0);
952 m_xDictsLB->set_text(nRow, rName, 1);
953 m_xDictsLB->set_id(nRow, rName);
956 IMPL_LINK_NOARG(HangulHanjaNewDictDialog, OKHdl, weld::Button&, void)
958 OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));
960 m_bEntered = !aName.isEmpty();
961 if (m_bEntered)
962 m_xDictNameED->set_text(aName); // do this in case of trailing chars have been deleted
964 m_xDialog->response(RET_OK);
967 IMPL_LINK_NOARG(HangulHanjaNewDictDialog, ModifyHdl, weld::Entry&, void)
969 OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));
971 m_xOkBtn->set_sensitive(!aName.isEmpty());
974 HangulHanjaNewDictDialog::HangulHanjaNewDictDialog(weld::Window* pParent)
975 : GenericDialogController(pParent, "cui/ui/hangulhanjaadddialog.ui", "HangulHanjaAddDialog")
976 , m_bEntered(false)
977 , m_xOkBtn(m_xBuilder->weld_button("ok"))
978 , m_xDictNameED(m_xBuilder->weld_entry("entry"))
980 m_xOkBtn->connect_clicked( LINK( this, HangulHanjaNewDictDialog, OKHdl ) );
981 m_xDictNameED->connect_changed( LINK( this, HangulHanjaNewDictDialog, ModifyHdl ) );
984 HangulHanjaNewDictDialog::~HangulHanjaNewDictDialog()
988 bool HangulHanjaNewDictDialog::GetName( OUString& _rRetName ) const
990 if( m_bEntered )
991 _rRetName = comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ');
993 return m_bEntered;
996 class SuggestionList
998 private:
999 protected:
1000 std::vector<OUString> m_vElements;
1001 sal_uInt16 m_nNumOfEntries;
1002 // index of the internal iterator, used for First() and Next() methods
1003 sal_uInt16 m_nAct;
1005 const OUString* Next_();
1006 public:
1007 SuggestionList();
1008 ~SuggestionList();
1010 void Set( const OUString& _rElement, sal_uInt16 _nNumOfElement );
1011 void Reset( sal_uInt16 _nNumOfElement );
1012 const OUString & Get( sal_uInt16 _nNumOfElement ) const;
1013 void Clear();
1015 const OUString* First();
1016 const OUString* Next();
1018 sal_uInt16 GetCount() const { return m_nNumOfEntries; }
1021 SuggestionList::SuggestionList() :
1022 m_vElements(MAXNUM_SUGGESTIONS)
1024 m_nAct = m_nNumOfEntries = 0;
1027 SuggestionList::~SuggestionList()
1029 Clear();
1032 void SuggestionList::Set( const OUString& _rElement, sal_uInt16 _nNumOfElement )
1034 m_vElements[_nNumOfElement] = _rElement;
1035 ++m_nNumOfEntries;
1038 void SuggestionList::Reset( sal_uInt16 _nNumOfElement )
1040 m_vElements[_nNumOfElement].clear();
1041 --m_nNumOfEntries;
1044 const OUString& SuggestionList::Get( sal_uInt16 _nNumOfElement ) const
1046 return m_vElements[_nNumOfElement];
1049 void SuggestionList::Clear()
1051 if( m_nNumOfEntries )
1053 for (auto & vElement : m_vElements)
1054 vElement.clear();
1055 m_nNumOfEntries = m_nAct = 0;
1059 const OUString* SuggestionList::Next_()
1061 while( m_nAct < m_vElements.size() )
1063 auto & s = m_vElements[ m_nAct ];
1064 if (!s.isEmpty())
1065 return &s;
1066 ++m_nAct;
1069 return nullptr;
1072 const OUString* SuggestionList::First()
1074 m_nAct = 0;
1075 return Next_();
1078 const OUString* SuggestionList::Next()
1080 const OUString* pRet;
1082 if( m_nAct < m_nNumOfEntries )
1084 ++m_nAct;
1085 pRet = Next_();
1087 else
1088 pRet = nullptr;
1090 return pRet;
1094 bool SuggestionEdit::ShouldScroll( bool _bUp ) const
1096 bool bRet = false;
1098 if( _bUp )
1100 if( !m_pPrev )
1101 bRet = m_pScrollBar->vadjustment_get_value() > m_pScrollBar->vadjustment_get_lower();
1103 else
1105 if( !m_pNext )
1106 bRet = m_pScrollBar->vadjustment_get_value() < ( m_pScrollBar->vadjustment_get_upper() - 4 );
1109 return bRet;
1112 void SuggestionEdit::DoJump( bool _bUp )
1114 m_pScrollBar->vadjustment_set_value( m_pScrollBar->vadjustment_get_value() + ( _bUp? -1 : 1 ) );
1115 m_pParent->UpdateScrollbar();
1118 SuggestionEdit::SuggestionEdit(std::unique_ptr<weld::Entry> xEntry, HangulHanjaEditDictDialog* pParent)
1119 : m_pParent(pParent)
1120 , m_pPrev(nullptr)
1121 , m_pNext(nullptr)
1122 , m_pScrollBar(nullptr)
1123 , m_xEntry(std::move(xEntry))
1125 m_xEntry->connect_key_press(LINK(this, SuggestionEdit, KeyInputHdl));
1128 IMPL_LINK(SuggestionEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
1130 bool bHandled = false;
1132 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
1133 sal_uInt16 nMod = rKeyCode.GetModifier();
1134 sal_uInt16 nCode = rKeyCode.GetCode();
1135 if( nCode == KEY_TAB && ( !nMod || KEY_SHIFT == nMod ) )
1137 bool bUp = KEY_SHIFT == nMod;
1138 if( ShouldScroll( bUp ) )
1140 DoJump( bUp );
1141 m_xEntry->select_region(0, -1);
1142 // Tab-travel doesn't really happen, so emulate it by setting a selection manually
1143 bHandled = true;
1146 else if( KEY_UP == nCode || KEY_DOWN == nCode )
1148 bool bUp = KEY_UP == nCode;
1149 if( ShouldScroll( bUp ) )
1151 DoJump( bUp );
1152 bHandled = true;
1154 else if( bUp )
1156 if( m_pPrev )
1158 m_pPrev->grab_focus();
1159 bHandled = true;
1162 else if( m_pNext )
1164 m_pNext->grab_focus();
1165 bHandled = true;
1169 return bHandled;
1172 void SuggestionEdit::init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, SuggestionEdit* pNext)
1174 m_pScrollBar = pScrollBar;
1175 m_pPrev = pPrev;
1176 m_pNext = pNext;
1179 namespace
1181 bool GetConversions( const Reference< XConversionDictionary >& _xDict,
1182 const OUString& _rOrg,
1183 Sequence< OUString >& _rEntries )
1185 bool bRet = false;
1186 if( _xDict.is() && !_rOrg.isEmpty() )
1190 _rEntries = _xDict->getConversions( _rOrg,
1192 _rOrg.getLength(),
1193 ConversionDirection_FROM_LEFT,
1194 css::i18n::TextConversionOption::NONE );
1195 bRet = _rEntries.getLength() > 0;
1197 catch( const IllegalArgumentException& )
1202 return bRet;
1206 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, ScrollHdl, weld::ScrolledWindow&, void )
1208 UpdateScrollbar();
1211 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, OriginalModifyHdl, weld::ComboBox&, void )
1213 m_bModifiedOriginal = true;
1214 m_aOriginal = comphelper::string::stripEnd( m_xOriginalLB->get_active_text(), ' ' );
1216 UpdateSuggestions();
1217 UpdateButtonStates();
1220 IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl1, weld::Entry&, rEdit, void )
1222 EditModify( &rEdit, 0 );
1225 IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl2, weld::Entry&, rEdit, void )
1227 EditModify( &rEdit, 1 );
1230 IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl3, weld::Entry&, rEdit, void )
1232 EditModify( &rEdit, 2 );
1235 IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl4, weld::Entry&, rEdit, void )
1237 EditModify( &rEdit, 3 );
1240 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, BookLBSelectHdl, weld::ComboBox&, void )
1242 InitEditDictDialog( m_xBookLB->get_active() );
1245 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, NewPBPushHdl, weld::Button&, void )
1247 DBG_ASSERT( m_xSuggestions, "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..." );
1248 Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
1249 if( xDict.is() && m_xSuggestions )
1251 //delete old entry
1252 bool bRemovedSomething = DeleteEntryFromDictionary( xDict );
1254 OUString aLeft( m_aOriginal );
1255 const OUString* pRight = m_xSuggestions->First();
1256 bool bAddedSomething = false;
1257 while( pRight )
1261 //add new entry
1262 xDict->addEntry( aLeft, *pRight );
1263 bAddedSomething = true;
1265 catch( const IllegalArgumentException& )
1268 catch( const ElementExistException& )
1272 pRight = m_xSuggestions->Next();
1275 if( bAddedSomething || bRemovedSomething )
1276 InitEditDictDialog( m_nCurrentDict );
1278 else
1280 SAL_INFO( "cui.dialogs", "dictionary faded away..." );
1284 bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( const Reference< XConversionDictionary >& xDict )
1286 bool bRemovedSomething = false;
1287 if( xDict.is() )
1289 OUString aOrg( m_aOriginal );
1290 Sequence< OUString > aEntries;
1291 GetConversions( xDict, m_aOriginal, aEntries );
1293 sal_uInt32 n = aEntries.getLength();
1294 OUString* pEntry = aEntries.getArray();
1295 while( n )
1299 xDict->removeEntry( aOrg, *pEntry );
1300 bRemovedSomething = true;
1302 catch( const NoSuchElementException& )
1303 { // can not be...
1306 ++pEntry;
1307 --n;
1310 return bRemovedSomething;
1313 IMPL_LINK_NOARG( HangulHanjaEditDictDialog, DeletePBPushHdl, weld::Button&, void )
1315 if( DeleteEntryFromDictionary( m_rDictList[ m_nCurrentDict ] ) )
1317 m_aOriginal.clear();
1318 m_bModifiedOriginal = true;
1319 InitEditDictDialog( m_nCurrentDict );
1323 void HangulHanjaEditDictDialog::InitEditDictDialog( sal_uInt32 nSelDict )
1325 if( m_xSuggestions )
1326 m_xSuggestions->Clear();
1328 if( m_nCurrentDict != nSelDict )
1330 m_nCurrentDict = nSelDict;
1331 m_aOriginal.clear();
1332 m_bModifiedOriginal = true;
1335 UpdateOriginalLB();
1337 m_xOriginalLB->set_entry_text( !m_aOriginal.isEmpty() ? m_aOriginal : m_aEditHintText);
1338 m_xOriginalLB->select_entry_region(0, -1);
1339 m_xOriginalLB->grab_focus();
1341 UpdateSuggestions();
1342 UpdateButtonStates();
1345 void HangulHanjaEditDictDialog::UpdateOriginalLB()
1347 m_xOriginalLB->clear();
1348 Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
1349 if( xDict.is() )
1351 Sequence< OUString > aEntries = xDict->getConversionEntries( ConversionDirection_FROM_LEFT );
1352 sal_uInt32 n = aEntries.getLength();
1353 OUString* pEntry = aEntries.getArray();
1354 while( n )
1356 m_xOriginalLB->append_text( *pEntry );
1358 ++pEntry;
1359 --n;
1362 else
1364 SAL_INFO( "cui.dialogs", "dictionary faded away..." );
1368 void HangulHanjaEditDictDialog::UpdateButtonStates()
1370 bool bHaveValidOriginalString = !m_aOriginal.isEmpty() && m_aOriginal != m_aEditHintText;
1371 bool bNew = bHaveValidOriginalString && m_xSuggestions && m_xSuggestions->GetCount() > 0;
1372 bNew = bNew && ( m_bModifiedSuggestions || m_bModifiedOriginal );
1374 m_xNewPB->set_sensitive( bNew );
1375 m_xDeletePB->set_sensitive(!m_bModifiedOriginal && bHaveValidOriginalString);
1378 void HangulHanjaEditDictDialog::UpdateSuggestions()
1380 Sequence< OUString > aEntries;
1381 bool bFound = GetConversions( m_rDictList[ m_nCurrentDict ], m_aOriginal, aEntries );
1382 if( bFound )
1384 m_bModifiedOriginal = false;
1386 if( m_xSuggestions )
1387 m_xSuggestions->Clear();
1389 //fill found entries into boxes
1390 sal_uInt32 nCnt = aEntries.getLength();
1391 if( nCnt )
1393 if( !m_xSuggestions )
1394 m_xSuggestions.reset(new SuggestionList);
1396 const OUString* pSugg = aEntries.getConstArray();
1397 sal_uInt32 n = 0;
1398 while( nCnt )
1400 m_xSuggestions->Set( pSugg[ n ], sal_uInt16( n ) );
1401 ++n;
1402 --nCnt;
1405 m_bModifiedSuggestions = false;
1408 m_xScrollSB->vadjustment_set_value( 0 );
1409 UpdateScrollbar(); // will force edits to be filled new
1412 void HangulHanjaEditDictDialog::SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum)
1414 OUString aStr;
1415 if( m_xSuggestions )
1417 aStr = m_xSuggestions->Get(nEntryNum);
1420 rEdit.set_text(aStr);
1423 void HangulHanjaEditDictDialog::EditModify(const weld::Entry* pEdit, sal_uInt8 _nEntryOffset)
1425 m_bModifiedSuggestions = true;
1427 OUString aTxt( pEdit->get_text() );
1428 sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset;
1429 if( aTxt.isEmpty() )
1431 //reset suggestion
1432 if( m_xSuggestions )
1433 m_xSuggestions->Reset( nEntryNum );
1435 else
1437 //set suggestion
1438 if( !m_xSuggestions )
1439 m_xSuggestions.reset(new SuggestionList);
1440 m_xSuggestions->Set( aTxt, nEntryNum );
1443 UpdateButtonStates();
1446 HangulHanjaEditDictDialog::HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& _rDictList, sal_uInt32 nSelDict)
1447 : GenericDialogController(pParent, "cui/ui/hangulhanjaeditdictdialog.ui", "HangulHanjaEditDictDialog")
1448 , m_aEditHintText ( CuiResId(RID_SVXSTR_EDITHINT) )
1449 , m_rDictList ( _rDictList )
1450 , m_nCurrentDict ( 0xFFFFFFFF )
1451 , m_nTopPos ( 0 )
1452 , m_bModifiedSuggestions ( false )
1453 , m_bModifiedOriginal ( false )
1454 , m_xBookLB(m_xBuilder->weld_combo_box("book"))
1455 , m_xOriginalLB(m_xBuilder->weld_combo_box("original"))
1456 , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry("edit1"), this))
1457 , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry("edit2"), this))
1458 , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry("edit3"), this))
1459 , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry("edit4"), this))
1460 , m_xContents(m_xBuilder->weld_widget("box"))
1461 , m_xScrollSB(m_xBuilder->weld_scrolled_window("scrollbar"))
1462 , m_xNewPB(m_xBuilder->weld_button("new"))
1463 , m_xDeletePB(m_xBuilder->weld_button("delete"))
1465 m_xScrollSB->set_user_managed_scrolling();
1467 Size aSize(m_xContents->get_preferred_size());
1468 m_xScrollSB->set_size_request(-1, aSize.Height());
1470 m_xEdit1->init( m_xScrollSB.get(), nullptr, m_xEdit2.get() );
1471 m_xEdit2->init( m_xScrollSB.get(), m_xEdit1.get(), m_xEdit3.get() );
1472 m_xEdit3->init( m_xScrollSB.get(), m_xEdit2.get(), m_xEdit4.get() );
1473 m_xEdit4->init( m_xScrollSB.get(), m_xEdit3.get(), nullptr );
1475 m_xOriginalLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, OriginalModifyHdl ) );
1477 m_xNewPB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, NewPBPushHdl ) );
1478 m_xNewPB->set_sensitive( false );
1480 m_xDeletePB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, DeletePBPushHdl ) );
1481 m_xDeletePB->set_sensitive( false );
1483 static_assert(MAXNUM_SUGGESTIONS >= 5, "number of suggestions should not under-run the value of 5");
1485 // 4 here, because we have 4 edits / page
1486 m_xScrollSB->vadjustment_configure(0, 0, MAXNUM_SUGGESTIONS, 1, 4, 4);
1487 m_xScrollSB->connect_vadjustment_changed(LINK(this, HangulHanjaEditDictDialog, ScrollHdl));
1489 m_xEdit1->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl1 ) );
1490 m_xEdit2->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl2 ) );
1491 m_xEdit3->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl3 ) );
1492 m_xEdit4->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl4 ) );
1494 m_xBookLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, BookLBSelectHdl ) );
1495 sal_uInt32 nDictCnt = m_rDictList.size();
1496 for( sal_uInt32 n = 0 ; n < nDictCnt ; ++n )
1498 Reference< XConversionDictionary > xDic( m_rDictList[n] );
1499 OUString aName;
1500 if( xDic.is() )
1501 aName = xDic->getName();
1502 m_xBookLB->append_text( aName );
1504 m_xBookLB->set_active(nSelDict);
1506 InitEditDictDialog(nSelDict);
1509 HangulHanjaEditDictDialog::~HangulHanjaEditDictDialog()
1513 void HangulHanjaEditDictDialog::UpdateScrollbar()
1515 sal_uInt16 nPos = m_xScrollSB->vadjustment_get_value();
1516 m_nTopPos = nPos;
1518 SetEditText( *m_xEdit1, nPos++ );
1519 SetEditText( *m_xEdit2, nPos++ );
1520 SetEditText( *m_xEdit3, nPos++ );
1521 SetEditText( *m_xEdit4, nPos );
1525 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */