LibreOffice Module cui (master)  1
hangulhanjadlg.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <hangulhanjadlg.hxx>
21 #include <dialmgr.hxx>
22 
23 #include <helpids.h>
24 #include <strings.hrc>
25 
26 #include <algorithm>
27 #include <sal/log.hxx>
28 #include <osl/diagnose.h>
29 #include <tools/debug.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/virdev.hxx>
33 #include <vcl/weldutils.hxx>
34 #include <unotools/lingucfg.hxx>
35 #include <unotools/linguprops.hxx>
36 #include <com/sun/star/lang/NoSupportException.hpp>
37 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
38 #include <com/sun/star/linguistic2/ConversionDirection.hpp>
39 #include <com/sun/star/linguistic2/ConversionDictionaryList.hpp>
40 #include <com/sun/star/i18n/TextConversionOption.hpp>
41 #include <com/sun/star/util/XFlushable.hpp>
42 
44 #include <comphelper/string.hxx>
45 
46 #define HHC editeng::HangulHanjaConversion
47 #define LINE_CNT static_cast< sal_uInt16 >(2)
48 #define MAXNUM_SUGGESTIONS 50
49 
50 
51 namespace svx
52 {
53 
54  using namespace ::com::sun::star;
55  using namespace css::uno;
56  using namespace css::linguistic2;
57  using namespace css::lang;
58  using namespace css::container;
59 
60 
61  namespace
62  {
63  class FontSwitch
64  {
65  private:
67 
68  public:
69  FontSwitch( OutputDevice& _rDev, const vcl::Font& _rTemporaryFont )
70  :m_rDev( _rDev )
71  {
72  m_rDev.Push( vcl::PushFlags::FONT );
73  m_rDev.SetFont( _rTemporaryFont );
74  }
75  ~FontSwitch() COVERITY_NOEXCEPT_FALSE
76  {
77  m_rDev.Pop();
78  }
79  };
80 
84  class PseudoRubyText
85  {
86  public:
87  enum RubyPosition
88  {
89  eAbove, eBelow
90  };
91 
92  protected:
93  OUString m_sPrimaryText;
94  OUString m_sSecondaryText;
96 
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; }
102 
103  public:
104  void Paint( vcl::RenderContext& _rDevice, const ::tools::Rectangle& _rRect,
105  ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation );
106  };
107 
108  }
109 
110  PseudoRubyText::PseudoRubyText()
111  : m_ePosition(eAbove)
112  {
113  }
114 
115  void PseudoRubyText::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition )
116  {
117  m_sPrimaryText = rPrimaryText;
118  m_sSecondaryText = rSecondaryText;
119  m_ePosition = rPosition;
120  }
121 
122 
123  void PseudoRubyText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& _rRect,
124  ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation )
125  {
126  // calculate the text flags for the painting
127  constexpr DrawTextFlags nTextStyle = DrawTextFlags::Mnemonic |
128  DrawTextFlags::Left |
129  DrawTextFlags::VCenter;
130 
131  Size aPlaygroundSize(_rRect.GetSize());
132 
133  // the font for the secondary text:
134  vcl::Font aSmallerFont(rRenderContext.GetFont());
135  // heuristic: 80% of the original size
136  aSmallerFont.SetFontHeight( static_cast<tools::Long>( 0.8 * aSmallerFont.GetFontHeight() ) );
137 
138  // let's calculate the size of our two texts
139  ::tools::Rectangle aPrimaryRect = rRenderContext.GetTextRect( _rRect, m_sPrimaryText, nTextStyle );
140  ::tools::Rectangle aSecondaryRect;
141  {
142  FontSwitch aFontRestore(rRenderContext, aSmallerFont);
143  aSecondaryRect = rRenderContext.GetTextRect(_rRect, m_sSecondaryText, nTextStyle);
144  }
145 
146  // position these rectangles properly
147  // x-axis:
148  sal_Int32 nCombinedWidth = std::max( aSecondaryRect.GetWidth(), aPrimaryRect.GetWidth() );
149  // the rectangle where both texts will reside is as high as possible, and as wide as the
150  // widest of both text rects
151  aPrimaryRect.SetLeft( _rRect.Left() );
152  aSecondaryRect.SetLeft( aPrimaryRect.Left() );
153  aPrimaryRect.SetRight( _rRect.Left() + nCombinedWidth );
154  aSecondaryRect.SetRight( aPrimaryRect.Right() );
155 
156  // y-axis:
157  sal_Int32 nCombinedHeight = aPrimaryRect.GetHeight() + aSecondaryRect.GetHeight();
158  // align to the top, for the moment
159  aPrimaryRect.Move( 0, _rRect.Top() - aPrimaryRect.Top() );
160  aSecondaryRect.Move( 0, aPrimaryRect.Top() + aPrimaryRect.GetHeight() - aSecondaryRect.Top() );
161  // move the rects to the bottom
162  aPrimaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 );
163  aSecondaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 );
164 
165  // 'til here, everything we did assumes that the secondary text is painted _below_ the primary
166  // text. If this isn't the case, we need to correct the rectangles
167  if (eAbove == m_ePosition)
168  {
169  sal_Int32 nVertDistance = aSecondaryRect.Top() - aPrimaryRect.Top();
170  aSecondaryRect.Move( 0, -nVertDistance );
171  aPrimaryRect.Move( 0, nCombinedHeight - nVertDistance );
172  }
173 
174  // now draw the texts
175  // as we already calculated the precise rectangles for the texts, we don't want to
176  // use the alignment flags given - within its rect, every text is centered
177  DrawTextFlags nDrawTextStyle( nTextStyle );
178  nDrawTextStyle &= ~DrawTextFlags( DrawTextFlags::Right | DrawTextFlags::Left | DrawTextFlags::Bottom | DrawTextFlags::Top );
179  nDrawTextStyle |= DrawTextFlags::Center | DrawTextFlags::VCenter;
180 
181  rRenderContext.DrawText( aPrimaryRect, m_sPrimaryText, nDrawTextStyle );
182  {
183  FontSwitch aFontRestore(rRenderContext, aSmallerFont);
184  rRenderContext.DrawText( aSecondaryRect, m_sSecondaryText, nDrawTextStyle );
185  }
186 
187  // outta here
188  if (_pPrimaryLocation)
189  *_pPrimaryLocation = aPrimaryRect;
190  if (_pSecondaryLocation)
191  *_pSecondaryLocation = aSecondaryRect;
192  }
193 
195  {
196  public:
197  RubyRadioButton(std::unique_ptr<weld::RadioButton> xControl, std::unique_ptr<weld::Image> xImage);
198  void init(const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition);
199 
200  void set_sensitive(bool sensitive)
201  {
202  m_xControl->set_sensitive(sensitive);
203  m_xImage->set_sensitive(sensitive);
204  }
205  void set_active(bool active) { m_xControl->set_active(active); }
206  bool get_active() const { return m_xControl->get_active(); }
207 
208  void connect_toggled(const Link<weld::Toggleable&, void>& rLink) { m_xControl->connect_toggled(rLink); }
209 
210  private:
211  Size GetOptimalSize() const;
212  void Paint(vcl::RenderContext& rRenderContext);
213 
215  std::unique_ptr<weld::RadioButton> m_xControl;
216  std::unique_ptr<weld::Image> m_xImage;
217  PseudoRubyText m_aRubyText;
218  };
219 
220  RubyRadioButton::RubyRadioButton(std::unique_ptr<weld::RadioButton> xControl, std::unique_ptr<weld::Image> xImage)
221  : m_xVirDev(xControl->create_virtual_device())
222  , m_xControl(std::move(xControl))
223  , m_xImage(std::move(xImage))
224  {
225  // expand the point size of the desired font to the equivalent pixel size
226  weld::SetPointFont(*m_xVirDev, m_xControl->get_font());
227  }
228 
229  void RubyRadioButton::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition )
230  {
231  m_aRubyText.init(rPrimaryText, rSecondaryText, rPosition);
232 
233  m_xVirDev->SetOutputSizePixel(GetOptimalSize());
234 
235  Paint(*m_xVirDev);
236 
237  m_xImage->set_image(m_xVirDev.get());
238  }
239 
241  {
242  ::tools::Rectangle aOverallRect(Point(0, 0), rRenderContext.GetOutputSizePixel());
243  // inflate the rect a little bit (because the VCL radio button does the same)
244  ::tools::Rectangle aTextRect( aOverallRect );
245  aTextRect.AdjustLeft( 1 ); aTextRect.AdjustRight( -1 );
246  aTextRect.AdjustTop( 1 ); aTextRect.AdjustBottom( -1 );
247 
248  // paint the ruby text
249  ::tools::Rectangle aPrimaryTextLocation;
250  ::tools::Rectangle aSecondaryTextLocation;
251 
252  m_aRubyText.Paint(rRenderContext, aTextRect, &aPrimaryTextLocation, &aSecondaryTextLocation);
253  }
254 
256  {
257  vcl::Font aSmallerFont(m_xVirDev->GetFont());
258  aSmallerFont.SetFontHeight( static_cast<tools::Long>( 0.8 * aSmallerFont.GetFontHeight() ) );
260 
261  Size aPrimarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getPrimaryText() ).GetSize();
262  Size aSecondarySize;
263  {
264  FontSwitch aFontRestore(*m_xVirDev, aSmallerFont);
265  aSecondarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getSecondaryText() ).GetSize();
266  }
267 
268  Size minimumSize;
269  minimumSize.setHeight( aPrimarySize.Height() + aSecondarySize.Height() + 5 );
270  minimumSize.setWidth(std::max(aPrimarySize.Width(), aSecondarySize.Width()) + 5 );
271  return minimumSize;
272  }
273 
274  SuggestionSet::SuggestionSet(std::unique_ptr<weld::ScrolledWindow> xScrolledWindow)
275  : ValueSet(std::move(xScrolledWindow))
276 
277  {
278  }
279 
281  {
282  vcl::RenderContext* pDev = rUDEvt.GetRenderContext();
283  ::tools::Rectangle aRect = rUDEvt.GetRect();
284  sal_uInt16 nItemId = rUDEvt.GetItemId();
285 
286  OUString sText = *static_cast< OUString* >( GetItemData( nItemId ) );
287  pDev->DrawText( aRect, sText, DrawTextFlags::Center | DrawTextFlags::VCenter );
288  }
289 
291  : m_bDisplayListBox( true )
292  , m_bInSelectionUpdate( false )
293  , m_xValueSet(new SuggestionSet(rBuilder.weld_scrolled_window("scrollwin", true)))
294  , m_xValueSetWin(new weld::CustomWeld(rBuilder, "valueset", *m_xValueSet))
295  , m_xListBox(rBuilder.weld_tree_view("listbox"))
296  {
297  m_xValueSet->SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionValueSetHdl ) );
298  m_xListBox->connect_changed( LINK( this, SuggestionDisplay, SelectSuggestionListBoxHdl ) );
299 
300  m_xValueSet->SetLineCount( LINE_CNT );
301  m_xValueSet->SetStyle( m_xValueSet->GetStyle() | WB_ITEMBORDER | WB_VSCROLL );
302 
303  auto nItemWidth = 2 * m_xListBox->get_pixel_size("AU").Width();
304  m_xValueSet->SetItemWidth( nItemWidth );
305 
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());
309 
311  }
312 
314  {
315  m_xListBox->set_visible(m_bDisplayListBox);
316  if (!m_bDisplayListBox)
317  m_xValueSetWin->show();
318  else
319  m_xValueSetWin->hide();
320  }
321 
323  {
324  if (m_bDisplayListBox)
325  return *m_xListBox;
326  return *m_xValueSet->GetDrawingArea();
327  }
328 
329  void SuggestionDisplay::DisplayListBox( bool bDisplayListBox )
330  {
331  if( m_bDisplayListBox == bDisplayListBox )
332  return;
333 
334  weld::Widget& rOldControl = implGetCurrentControl();
335  bool bHasFocus = rOldControl.has_focus();
336 
337  m_bDisplayListBox = bDisplayListBox;
338 
339  if( bHasFocus )
340  {
341  weld::Widget& rNewControl = implGetCurrentControl();
342  rNewControl.grab_focus();
343  }
344 
346  }
347 
348  IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionValueSetHdl, ValueSet*, void)
349  {
350  SelectSuggestionHdl(false);
351  }
352 
353  IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionListBoxHdl, weld::TreeView&, void)
354  {
355  SelectSuggestionHdl(true);
356  }
357 
359  {
361  return;
362 
363  m_bInSelectionUpdate = true;
364  if (bListBox)
365  {
366  sal_uInt16 nPos = m_xListBox->get_selected_index();
367  m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
368  }
369  else
370  {
371  sal_uInt16 nPos = m_xValueSet->GetSelectedItemId()-1; //itemid == pos+1 (id 0 has special meaning)
372  m_xListBox->select(nPos);
373  }
374  m_bInSelectionUpdate = false;
375  m_aSelectLink.Call( *this );
376  }
377 
379  {
380  m_aSelectLink = rLink;
381  }
382 
384  {
385  m_xListBox->clear();
386  m_xValueSet->Clear();
387  }
388 
389  void SuggestionDisplay::InsertEntry( const OUString& rStr )
390  {
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 );
396  }
397 
398  void SuggestionDisplay::SelectEntryPos( sal_uInt16 nPos )
399  {
400  m_xListBox->select(nPos);
401  m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
402  }
403 
405  {
406  return m_xListBox->n_children();
407  }
408 
409  OUString SuggestionDisplay::GetEntry( sal_uInt16 nPos ) const
410  {
411  return m_xListBox->get_text( nPos );
412  }
413 
415  {
416  return m_xListBox->get_selected_text();
417  }
418 
420  {
423  }
424 
426  : GenericDialogController(pParent, "cui/ui/hangulhanjaconversiondialog.ui", "HangulHanjaConversionDialog")
427  , m_bDocumentMode( true )
428  , m_xFind(m_xBuilder->weld_button("find"))
429  , m_xIgnore(m_xBuilder->weld_button("ignore"))
430  , m_xIgnoreAll(m_xBuilder->weld_button("ignoreall"))
431  , m_xReplace(m_xBuilder->weld_button("replace"))
432  , m_xReplaceAll(m_xBuilder->weld_button("replaceall"))
433  , m_xOptions(m_xBuilder->weld_button("options"))
434  , m_xSuggestions(new SuggestionDisplay(*m_xBuilder))
435  , m_xSimpleConversion(m_xBuilder->weld_radio_button("simpleconversion"))
436  , m_xHangulBracketed(m_xBuilder->weld_radio_button("hangulbracket"))
437  , m_xHanjaBracketed(m_xBuilder->weld_radio_button("hanjabracket"))
438  , m_xWordInput(m_xBuilder->weld_entry("wordinput"))
439  , m_xOriginalWord(m_xBuilder->weld_label("originalword"))
440  , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_above"),
441  m_xBuilder->weld_image("hanja_above_img")))
442  , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_below"),
443  m_xBuilder->weld_image("hanja_below_img")))
444  , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_above"),
445  m_xBuilder->weld_image("hangul_above_img")))
446  , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_below"),
447  m_xBuilder->weld_image("hangul_below_img")))
448  , m_xHangulOnly(m_xBuilder->weld_check_button("hangulonly"))
449  , m_xHanjaOnly(m_xBuilder->weld_check_button("hanjaonly"))
450  , m_xReplaceByChar(m_xBuilder->weld_check_button("replacebychar"))
451  {
452  m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42,
453  m_xOriginalWord->get_text_height() * 5);
454 
455  const OUString sHangul(CuiResId(RID_SVXSTR_HANGUL));
456  const OUString sHanja(CuiResId(RID_SVXSTR_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 );
461 
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));
468 
469  // initial focus
470  FocusSuggestion( );
471 
472  // initial control values
473  m_xSimpleConversion->set_active(true);
474 
475  m_xSuggestions->SetHelpIds();
476  }
477 
479  {
480  }
481 
482  void HangulHanjaConversionDialog::FillSuggestions( const css::uno::Sequence< OUString >& _rSuggestions )
483  {
484  m_xSuggestions->Clear();
485  for ( auto const & suggestion : _rSuggestions )
486  m_xSuggestions->InsertEntry( suggestion );
487 
488  // select the first suggestion, and fill in the suggestion edit field
489  OUString sFirstSuggestion;
490  if ( m_xSuggestions->GetEntryCount() )
491  {
492  sFirstSuggestion = m_xSuggestions->GetEntry( 0 );
493  m_xSuggestions->SelectEntryPos( 0 );
494  }
495  m_xWordInput->set_text( sFirstSuggestion );
496  m_xWordInput->save_value();
497  OnSuggestionModified( *m_xWordInput );
498  }
499 
501  {
502  m_aOptionsChangedLink = rHdl;
503  }
504 
506  {
507  m_xIgnore->connect_clicked(rHdl);
508  }
509 
511  {
512  m_xIgnoreAll->connect_clicked(rHdl);
513  }
514 
516  {
517  m_xReplace->connect_clicked(rHdl);
518  }
519 
521  {
522  m_xReplaceAll->connect_clicked(rHdl);
523  }
524 
526  {
527  m_xFind->connect_clicked(rHdl);
528  }
529 
531  {
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 );
539  }
540 
542  {
543  m_aClickByCharacterLink = _rHdl;
544  }
545 
547  {
548  m_xWordInput->set_text(m_xSuggestions->GetSelectedEntry());
549  OnSuggestionModified( *m_xWordInput );
550  }
551 
552  IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionModified, weld::Entry&, void )
553  {
554  m_xFind->set_sensitive(m_xWordInput->get_value_changed_from_saved());
555 
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 );
559  }
560 
561  IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::Toggleable&, rBox, void)
562  {
563  m_aClickByCharacterLink.Call(rBox);
564  bool bByCharacter = rBox.get_active();
565  m_xSuggestions->DisplayListBox( !bByCharacter );
566  }
567 
568  IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::Toggleable&, rBox, void)
569  {
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);
579  }
580 
582  {
583  HangulHanjaOptionsDialog aOptDlg(m_xDialog.get());
584  aOptDlg.run();
585  m_aOptionsChangedLink.Call( nullptr );
586  }
587 
589  {
590  return m_xOriginalWord->get_label();
591  }
592 
594  {
595  m_xWordInput->grab_focus();
596  }
597 
598  void HangulHanjaConversionDialog::SetCurrentString( const OUString& _rNewString,
599  const Sequence< OUString >& _rSuggestions, bool _bOriginatesFromDocument )
600  {
601  m_xOriginalWord->set_label(_rNewString);
602 
603  bool bOldDocumentMode = m_bDocumentMode;
604  m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions!
605  FillSuggestions( _rSuggestions );
606 
607  m_xIgnoreAll->set_sensitive( m_bDocumentMode );
608 
609  // switch the def button depending if we're working for document text
610  if (bOldDocumentMode == m_bDocumentMode)
611  return;
612 
613  weld::Widget* pOldDefButton = nullptr;
614  weld::Widget* pNewDefButton = nullptr;
615  if (m_bDocumentMode)
616  {
617  pOldDefButton = m_xFind.get();
618  pNewDefButton = m_xReplace.get();
619  }
620  else
621  {
622  pOldDefButton = m_xReplace.get();
623  pNewDefButton = m_xFind.get();
624  }
625 
626  pOldDefButton->set_has_default(false);
627  pNewDefButton->set_has_default(true);
628  }
629 
631  {
632  return m_xWordInput->get_text();
633  }
634 
636  {
637  m_xReplaceByChar->set_active( _bByCharacter );
638  m_xSuggestions->DisplayListBox( !_bByCharacter );
639  }
640 
642  bool _bTryBothDirections,
643  HHC::ConversionDirection ePrimaryConversionDirection )
644  {
645  // default state: try both direction
646  m_xHangulOnly->set_active( false );
647  m_xHangulOnly->set_sensitive(true);
648  m_xHanjaOnly->set_active( false );
649  m_xHanjaOnly->set_sensitive(true);
650 
651  if (!_bTryBothDirections)
652  {
653  weld::CheckButton* pBox = ePrimaryConversionDirection == HHC::eHangulToHanja ?
654  m_xHangulOnly.get() : m_xHanjaOnly.get();
655  pBox->set_active(true);
656  OnConversionDirectionClicked(*pBox);
657  }
658  }
659 
661  {
662  return !m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active();
663  }
664 
666  HHC::ConversionDirection eDefaultDirection ) const
667  {
668  HHC::ConversionDirection eDirection = eDefaultDirection;
669  if (m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active())
670  eDirection = HHC::eHangulToHanja;
671  else if (!m_xHangulOnly->get_active() && m_xHanjaOnly->get_active())
672  eDirection = HHC::eHanjaToHangul;
673  return eDirection;
674  }
675 
676  void HangulHanjaConversionDialog::SetConversionFormat( HHC::ConversionFormat _eType )
677  {
678  switch ( _eType )
679  {
680  case HHC::eSimpleConversion: m_xSimpleConversion->set_active(true); break;
681  case HHC::eHangulBracketed: m_xHangulBracketed->set_active(true); break;
682  case HHC::eHanjaBracketed: m_xHanjaBracketed->set_active(true); break;
683  case HHC::eRubyHanjaAbove: m_xHanjaAbove->set_active(true); break;
684  case HHC::eRubyHanjaBelow: m_xHanjaBelow->set_active(true); break;
685  case HHC::eRubyHangulAbove: m_xHangulAbove->set_active(true); break;
686  case HHC::eRubyHangulBelow: m_xHangulBelow->set_active(true); break;
687  default:
688  OSL_FAIL( "HangulHanjaConversionDialog::SetConversionFormat: unknown type!" );
689  }
690  }
691 
693  {
694  if ( m_xSimpleConversion->get_active() )
695  return HHC::eSimpleConversion;
696  if ( m_xHangulBracketed->get_active() )
697  return HHC::eHangulBracketed;
698  if ( m_xHanjaBracketed->get_active() )
699  return HHC::eHanjaBracketed;
700  if ( m_xHanjaAbove->get_active() )
701  return HHC::eRubyHanjaAbove;
702  if ( m_xHanjaBelow->get_active() )
703  return HHC::eRubyHanjaBelow;
704  if ( m_xHangulAbove->get_active() )
705  return HHC::eRubyHangulAbove;
706  if ( m_xHangulBelow->get_active() )
707  return HHC::eRubyHangulBelow;
708 
709  OSL_FAIL( "HangulHanjaConversionDialog::GetConversionFormat: no radio checked?" );
710  return HHC::eSimpleConversion;
711  }
712 
714  {
715  m_xHanjaAbove->set_sensitive( bVal );
716  m_xHanjaBelow->set_sensitive( bVal );
717  m_xHangulAbove->set_sensitive( bVal );
718  m_xHangulBelow->set_sensitive( bVal );
719  }
720 
722  {
723  if( !m_xConversionDictionaryList.is() )
724  {
725  m_xConversionDictionaryList = ConversionDictionaryList::create( ::comphelper::getProcessComponentContext() );
726  }
727 
728  m_aDictList.clear();
729  m_xDictsLB->clear();
730 
731  Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
732  if( xNameCont.is() )
733  {
734  Sequence< OUString > aDictNames( xNameCont->getElementNames() );
735 
736  const OUString* pDic = aDictNames.getConstArray();
737  sal_Int32 nCount = aDictNames.getLength();
738 
739  sal_Int32 i;
740  for( i = 0 ; i < nCount ; ++i )
741  {
742  Any aAny( xNameCont->getByName( pDic[ i ] ) );
743  Reference< XConversionDictionary > xDic;
744  if( ( aAny >>= xDic ) && xDic.is() )
745  {
746  if( LANGUAGE_KOREAN == LanguageTag( xDic->getLocale() ).getLanguageType() )
747  {
748  m_aDictList.push_back( xDic );
749  AddDict( xDic->getName(), xDic->isActive() );
750  }
751  }
752  }
753  }
754  if (m_xDictsLB->n_children())
755  m_xDictsLB->select(0);
756  }
757 
759  {
760  sal_uInt32 nCnt = m_aDictList.size();
761  sal_uInt32 n = 0;
762  sal_uInt32 nActiveDics = 0;
763  Sequence< OUString > aActiveDics;
764 
765  aActiveDics.realloc( nCnt );
766  OUString* pActActiveDic = aActiveDics.getArray();
767 
768  while( nCnt )
769  {
770  Reference< XConversionDictionary > xDict = m_aDictList[ n ];
771 
772  DBG_ASSERT( xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..." );
773 
774  bool bActive = m_xDictsLB->get_toggle(n) == TRISTATE_TRUE;
775  xDict->setActive( bActive );
776  Reference< util::XFlushable > xFlush( xDict, uno::UNO_QUERY );
777  if( xFlush.is() )
778  xFlush->flush();
779 
780  if( bActive )
781  {
782  pActActiveDic[ nActiveDics ] = xDict->getName();
783  ++nActiveDics;
784  }
785 
786  ++n;
787  --nCnt;
788  }
789 
790  // save configuration
791  aActiveDics.realloc( nActiveDics );
792  Any aTmp;
793  SvtLinguConfig aLngCfg;
794  aTmp <<= aActiveDics;
796 
797  aTmp <<= m_xIgnorepostCB->get_active();
799 
800  aTmp <<= m_xShowrecentlyfirstCB->get_active();
802 
803  aTmp <<= m_xAutoreplaceuniqueCB->get_active();
805 
806  m_xDialog->response(RET_OK);
807  }
808 
810  {
811  bool bSel = m_xDictsLB->get_selected_index() != -1;
812 
813  m_xEditPB->set_sensitive(bSel);
814  m_xDeletePB->set_sensitive(bSel);
815  }
816 
818  {
819  OUString aName;
820  HangulHanjaNewDictDialog aNewDlg(m_xDialog.get());
821  aNewDlg.run();
822  if (!aNewDlg.GetName(aName))
823  return;
824 
825  if( !m_xConversionDictionaryList.is() )
826  return;
827 
828  try
829  {
830  Reference< XConversionDictionary > xDic =
831  m_xConversionDictionaryList->addNewDictionary( aName, LanguageTag::convertToLocale( LANGUAGE_KOREAN ), ConversionDictionaryType::HANGUL_HANJA );
832 
833  if( xDic.is() )
834  {
835  //adapt local caches:
836  m_aDictList.push_back( xDic );
837  AddDict( xDic->getName(), xDic->isActive() );
838  }
839  }
840  catch( const ElementExistException& )
841  {
842  }
843  catch( const NoSupportException& )
844  {
845  }
846  }
847 
849  {
850  int nEntry = m_xDictsLB->get_selected_index();
851  DBG_ASSERT(nEntry != -1, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not be possible with no selection!");
852  if (nEntry != -1)
853  {
854  HangulHanjaEditDictDialog aEdDlg(m_xDialog.get(), m_aDictList, nEntry);
855  aEdDlg.run();
856  }
857  }
858 
860  {
861  int nSelPos = m_xDictsLB->get_selected_index();
862  if (nSelPos == -1)
863  return;
864 
865  Reference< XConversionDictionary > xDic( m_aDictList[ nSelPos ] );
866  if( !(m_xConversionDictionaryList.is() && xDic.is()) )
867  return;
868 
869  Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
870  if( !xNameCont.is() )
871  return;
872 
873  try
874  {
875  xNameCont->removeByName( xDic->getName() );
876 
877  //adapt local caches:
878  m_aDictList.erase(m_aDictList.begin()+nSelPos );
879  m_xDictsLB->remove(nSelPos);
880  }
881  catch( const ElementExistException& )
882  {
883  }
884  catch( const NoSupportException& )
885  {
886  }
887  }
888 
890  : GenericDialogController(pParent, "cui/ui/hangulhanjaoptdialog.ui", "HangulHanjaOptDialog")
891  , m_xDictsLB(m_xBuilder->weld_tree_view("dicts"))
892  , m_xIgnorepostCB(m_xBuilder->weld_check_button("ignorepost"))
893  , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button("showrecentfirst"))
894  , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button("autoreplaceunique"))
895  , m_xNewPB(m_xBuilder->weld_button("new"))
896  , m_xEditPB(m_xBuilder->weld_button("edit"))
897  , m_xDeletePB(m_xBuilder->weld_button("delete"))
898  , m_xOkPB(m_xBuilder->weld_button("ok"))
899  {
900  m_xDictsLB->set_size_request(m_xDictsLB->get_approximate_digit_width() * 32,
901  m_xDictsLB->get_height_rows(5));
902 
903  m_xDictsLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
904 
905  m_xDictsLB->connect_changed( LINK( this, HangulHanjaOptionsDialog, DictsLB_SelectHdl ) );
906 
907  m_xOkPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, OkHdl ) );
908  m_xNewPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, NewDictHdl ) );
909  m_xEditPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, EditDictHdl ) );
910  m_xDeletePB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, DeleteDictHdl ) );
911 
912  SvtLinguConfig aLngCfg;
913  Any aTmp;
914  bool bVal = bool();
916  if( aTmp >>= bVal )
917  m_xIgnorepostCB->set_active( bVal );
918 
920  if( aTmp >>= bVal )
921  m_xShowrecentlyfirstCB->set_active( bVal );
922 
924  if( aTmp >>= bVal )
925  m_xAutoreplaceuniqueCB->set_active( bVal );
926 
927  Init();
928  }
929 
931  {
932  }
933 
934  void HangulHanjaOptionsDialog::AddDict(const OUString& rName, bool bChecked)
935  {
936  m_xDictsLB->append();
937  int nRow = m_xDictsLB->n_children() - 1;
938  m_xDictsLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
939  m_xDictsLB->set_text(nRow, rName, 0);
940  m_xDictsLB->set_id(nRow, rName);
941  }
942 
944  {
945  OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));
946 
947  m_bEntered = !aName.isEmpty();
948  if (m_bEntered)
949  m_xDictNameED->set_text(aName); // do this in case of trailing chars have been deleted
950 
951  m_xDialog->response(RET_OK);
952  }
953 
955  {
956  OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));
957 
958  m_xOkBtn->set_sensitive(!aName.isEmpty());
959  }
960 
962  : GenericDialogController(pParent, "cui/ui/hangulhanjaadddialog.ui", "HangulHanjaAddDialog")
963  , m_bEntered(false)
964  , m_xOkBtn(m_xBuilder->weld_button("ok"))
965  , m_xDictNameED(m_xBuilder->weld_entry("entry"))
966  {
967  m_xOkBtn->connect_clicked( LINK( this, HangulHanjaNewDictDialog, OKHdl ) );
968  m_xDictNameED->connect_changed( LINK( this, HangulHanjaNewDictDialog, ModifyHdl ) );
969  }
970 
972  {
973  }
974 
975  bool HangulHanjaNewDictDialog::GetName( OUString& _rRetName ) const
976  {
977  if( m_bEntered )
978  _rRetName = comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ');
979 
980  return m_bEntered;
981  }
982 
984  {
985  private:
986  protected:
987  std::vector<OUString> m_vElements;
988  sal_uInt16 m_nNumOfEntries;
989  // index of the internal iterator, used for First() and Next() methods
990  sal_uInt16 m_nAct;
991 
992  const OUString* Next_();
993  public:
994  SuggestionList();
995  ~SuggestionList();
996 
997  void Set( const OUString& _rElement, sal_uInt16 _nNumOfElement );
998  void Reset( sal_uInt16 _nNumOfElement );
999  const OUString & Get( sal_uInt16 _nNumOfElement ) const;
1000  void Clear();
1001 
1002  const OUString* First();
1003  const OUString* Next();
1004 
1005  sal_uInt16 GetCount() const { return m_nNumOfEntries; }
1006  };
1007 
1009  m_vElements(MAXNUM_SUGGESTIONS)
1010  {
1011  m_nAct = m_nNumOfEntries = 0;
1012  }
1013 
1015  {
1016  Clear();
1017  }
1018 
1019  void SuggestionList::Set( const OUString& _rElement, sal_uInt16 _nNumOfElement )
1020  {
1021  m_vElements[_nNumOfElement] = _rElement;
1022  ++m_nNumOfEntries;
1023  }
1024 
1025  void SuggestionList::Reset( sal_uInt16 _nNumOfElement )
1026  {
1027  m_vElements[_nNumOfElement].clear();
1028  --m_nNumOfEntries;
1029  }
1030 
1031  const OUString& SuggestionList::Get( sal_uInt16 _nNumOfElement ) const
1032  {
1033  return m_vElements[_nNumOfElement];
1034  }
1035 
1037  {
1038  if( m_nNumOfEntries )
1039  {
1040  for (auto & vElement : m_vElements)
1041  vElement.clear();
1042  m_nNumOfEntries = m_nAct = 0;
1043  }
1044  }
1045 
1046  const OUString* SuggestionList::Next_()
1047  {
1048  while( m_nAct < m_vElements.size() )
1049  {
1050  auto & s = m_vElements[ m_nAct ];
1051  if (!s.isEmpty())
1052  return &s;
1053  ++m_nAct;
1054  }
1055 
1056  return nullptr;
1057  }
1058 
1059  const OUString* SuggestionList::First()
1060  {
1061  m_nAct = 0;
1062  return Next_();
1063  }
1064 
1065  const OUString* SuggestionList::Next()
1066  {
1067  const OUString* pRet;
1068 
1069  if( m_nAct < m_nNumOfEntries )
1070  {
1071  ++m_nAct;
1072  pRet = Next_();
1073  }
1074  else
1075  pRet = nullptr;
1076 
1077  return pRet;
1078  }
1079 
1080 
1081  bool SuggestionEdit::ShouldScroll( bool _bUp ) const
1082  {
1083  bool bRet = false;
1084 
1085  if( _bUp )
1086  {
1087  if( !m_pPrev )
1089  }
1090  else
1091  {
1092  if( !m_pNext )
1094  }
1095 
1096  return bRet;
1097  }
1098 
1099  void SuggestionEdit::DoJump( bool _bUp )
1100  {
1103  }
1104 
1105  SuggestionEdit::SuggestionEdit(std::unique_ptr<weld::Entry> xEntry, HangulHanjaEditDictDialog* pParent)
1106  : m_pParent(pParent)
1107  , m_pPrev(nullptr)
1108  , m_pNext(nullptr)
1109  , m_pScrollBar(nullptr)
1110  , m_xEntry(std::move(xEntry))
1111  {
1112  m_xEntry->connect_key_press(LINK(this, SuggestionEdit, KeyInputHdl));
1113  }
1114 
1115  IMPL_LINK(SuggestionEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
1116  {
1117  bool bHandled = false;
1118 
1119  const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
1120  sal_uInt16 nMod = rKeyCode.GetModifier();
1121  sal_uInt16 nCode = rKeyCode.GetCode();
1122  if( nCode == KEY_TAB && ( !nMod || KEY_SHIFT == nMod ) )
1123  {
1124  bool bUp = KEY_SHIFT == nMod;
1125  if( ShouldScroll( bUp ) )
1126  {
1127  DoJump( bUp );
1128  m_xEntry->select_region(0, -1);
1129  // Tab-travel doesn't really happen, so emulate it by setting a selection manually
1130  bHandled = true;
1131  }
1132  }
1133  else if( KEY_UP == nCode || KEY_DOWN == nCode )
1134  {
1135  bool bUp = KEY_UP == nCode;
1136  if( ShouldScroll( bUp ) )
1137  {
1138  DoJump( bUp );
1139  bHandled = true;
1140  }
1141  else if( bUp )
1142  {
1143  if( m_pPrev )
1144  {
1145  m_pPrev->grab_focus();
1146  bHandled = true;
1147  }
1148  }
1149  else if( m_pNext )
1150  {
1151  m_pNext->grab_focus();
1152  bHandled = true;
1153  }
1154  }
1155 
1156  return bHandled;
1157  }
1158 
1160  {
1161  m_pScrollBar = pScrollBar;
1162  m_pPrev = pPrev;
1163  m_pNext = pNext;
1164  }
1165 
1166  namespace
1167  {
1168  bool GetConversions( const Reference< XConversionDictionary >& _xDict,
1169  const OUString& _rOrg,
1170  Sequence< OUString >& _rEntries )
1171  {
1172  bool bRet = false;
1173  if( _xDict.is() && !_rOrg.isEmpty() )
1174  {
1175  try
1176  {
1177  _rEntries = _xDict->getConversions( _rOrg,
1178  0,
1179  _rOrg.getLength(),
1180  ConversionDirection_FROM_LEFT,
1181  css::i18n::TextConversionOption::NONE );
1182  bRet = _rEntries.hasElements();
1183  }
1184  catch( const IllegalArgumentException& )
1185  {
1186  }
1187  }
1188 
1189  return bRet;
1190  }
1191  }
1192 
1194  {
1195  UpdateScrollbar();
1196  }
1197 
1199  {
1200  m_bModifiedOriginal = true;
1201  m_aOriginal = comphelper::string::stripEnd( m_xOriginalLB->get_active_text(), ' ' );
1202 
1203  UpdateSuggestions();
1204  UpdateButtonStates();
1205  }
1206 
1207  IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl1, weld::Entry&, rEdit, void )
1208  {
1209  EditModify( &rEdit, 0 );
1210  }
1211 
1212  IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl2, weld::Entry&, rEdit, void )
1213  {
1214  EditModify( &rEdit, 1 );
1215  }
1216 
1217  IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl3, weld::Entry&, rEdit, void )
1218  {
1219  EditModify( &rEdit, 2 );
1220  }
1221 
1222  IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl4, weld::Entry&, rEdit, void )
1223  {
1224  EditModify( &rEdit, 3 );
1225  }
1226 
1228  {
1229  InitEditDictDialog( m_xBookLB->get_active() );
1230  }
1231 
1233  {
1234  DBG_ASSERT( m_xSuggestions, "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..." );
1235  Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
1236  if( xDict.is() && m_xSuggestions )
1237  {
1238  //delete old entry
1239  bool bRemovedSomething = DeleteEntryFromDictionary( xDict );
1240 
1241  OUString aLeft( m_aOriginal );
1242  const OUString* pRight = m_xSuggestions->First();
1243  bool bAddedSomething = false;
1244  while( pRight )
1245  {
1246  try
1247  {
1248  //add new entry
1249  xDict->addEntry( aLeft, *pRight );
1250  bAddedSomething = true;
1251  }
1252  catch( const IllegalArgumentException& )
1253  {
1254  }
1255  catch( const ElementExistException& )
1256  {
1257  }
1258 
1259  pRight = m_xSuggestions->Next();
1260  }
1261 
1262  if( bAddedSomething || bRemovedSomething )
1263  InitEditDictDialog( m_nCurrentDict );
1264  }
1265  else
1266  {
1267  SAL_INFO( "cui.dialogs", "dictionary faded away..." );
1268  }
1269  }
1270 
1271  bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( const Reference< XConversionDictionary >& xDict )
1272  {
1273  bool bRemovedSomething = false;
1274  if( xDict.is() )
1275  {
1276  OUString aOrg( m_aOriginal );
1278  GetConversions( xDict, m_aOriginal, aEntries );
1279 
1280  sal_uInt32 n = aEntries.getLength();
1281  OUString* pEntry = aEntries.getArray();
1282  while( n )
1283  {
1284  try
1285  {
1286  xDict->removeEntry( aOrg, *pEntry );
1287  bRemovedSomething = true;
1288  }
1289  catch( const NoSuchElementException& )
1290  { // can not be...
1291  }
1292 
1293  ++pEntry;
1294  --n;
1295  }
1296  }
1297  return bRemovedSomething;
1298  }
1299 
1301  {
1302  if( DeleteEntryFromDictionary( m_rDictList[ m_nCurrentDict ] ) )
1303  {
1304  m_aOriginal.clear();
1305  m_bModifiedOriginal = true;
1306  InitEditDictDialog( m_nCurrentDict );
1307  }
1308  }
1309 
1311  {
1312  if( m_xSuggestions )
1313  m_xSuggestions->Clear();
1314 
1315  if( m_nCurrentDict != nSelDict )
1316  {
1317  m_nCurrentDict = nSelDict;
1318  m_aOriginal.clear();
1319  m_bModifiedOriginal = true;
1320  }
1321 
1322  UpdateOriginalLB();
1323 
1324  m_xOriginalLB->set_entry_text( !m_aOriginal.isEmpty() ? m_aOriginal : m_aEditHintText);
1325  m_xOriginalLB->select_entry_region(0, -1);
1326  m_xOriginalLB->grab_focus();
1327 
1330  }
1331 
1333  {
1334  m_xOriginalLB->clear();
1335  Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
1336  if( xDict.is() )
1337  {
1338  Sequence< OUString > aEntries = xDict->getConversionEntries( ConversionDirection_FROM_LEFT );
1339  sal_uInt32 n = aEntries.getLength();
1340  OUString* pEntry = aEntries.getArray();
1341  while( n )
1342  {
1343  m_xOriginalLB->append_text( *pEntry );
1344 
1345  ++pEntry;
1346  --n;
1347  }
1348  }
1349  else
1350  {
1351  SAL_INFO( "cui.dialogs", "dictionary faded away..." );
1352  }
1353  }
1354 
1356  {
1357  bool bHaveValidOriginalString = !m_aOriginal.isEmpty() && m_aOriginal != m_aEditHintText;
1358  bool bNew = bHaveValidOriginalString && m_xSuggestions && m_xSuggestions->GetCount() > 0;
1359  bNew = bNew && ( m_bModifiedSuggestions || m_bModifiedOriginal );
1360 
1361  m_xNewPB->set_sensitive( bNew );
1362  m_xDeletePB->set_sensitive(!m_bModifiedOriginal && bHaveValidOriginalString);
1363  }
1364 
1366  {
1368  bool bFound = GetConversions( m_rDictList[ m_nCurrentDict ], m_aOriginal, aEntries );
1369  if( bFound )
1370  {
1371  m_bModifiedOriginal = false;
1372 
1373  if( m_xSuggestions )
1374  m_xSuggestions->Clear();
1375 
1376  //fill found entries into boxes
1377  sal_uInt32 nCnt = aEntries.getLength();
1378  if( nCnt )
1379  {
1380  if( !m_xSuggestions )
1381  m_xSuggestions.reset(new SuggestionList);
1382 
1383  const OUString* pSugg = aEntries.getConstArray();
1384  sal_uInt32 n = 0;
1385  while( nCnt )
1386  {
1387  m_xSuggestions->Set( pSugg[ n ], sal_uInt16( n ) );
1388  ++n;
1389  --nCnt;
1390  }
1391  }
1392  m_bModifiedSuggestions = false;
1393  }
1394 
1395  m_xScrollSB->vadjustment_set_value( 0 );
1396  UpdateScrollbar(); // will force edits to be filled new
1397  }
1398 
1399  void HangulHanjaEditDictDialog::SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum)
1400  {
1401  OUString aStr;
1402  if( m_xSuggestions )
1403  {
1404  aStr = m_xSuggestions->Get(nEntryNum);
1405  }
1406 
1407  rEdit.set_text(aStr);
1408  }
1409 
1411  {
1412  m_bModifiedSuggestions = true;
1413 
1414  OUString aTxt( pEdit->get_text() );
1415  sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset;
1416  if( aTxt.isEmpty() )
1417  {
1418  //reset suggestion
1419  if( m_xSuggestions )
1420  m_xSuggestions->Reset( nEntryNum );
1421  }
1422  else
1423  {
1424  //set suggestion
1425  if( !m_xSuggestions )
1426  m_xSuggestions.reset(new SuggestionList);
1427  m_xSuggestions->Set( aTxt, nEntryNum );
1428  }
1429 
1431  }
1432 
1434  : GenericDialogController(pParent, "cui/ui/hangulhanjaeditdictdialog.ui", "HangulHanjaEditDictDialog")
1435  , m_aEditHintText ( CuiResId(RID_SVXSTR_EDITHINT) )
1436  , m_rDictList ( _rDictList )
1437  , m_nCurrentDict ( 0xFFFFFFFF )
1438  , m_nTopPos ( 0 )
1439  , m_bModifiedSuggestions ( false )
1440  , m_bModifiedOriginal ( false )
1441  , m_xBookLB(m_xBuilder->weld_combo_box("book"))
1442  , m_xOriginalLB(m_xBuilder->weld_combo_box("original"))
1443  , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry("edit1"), this))
1444  , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry("edit2"), this))
1445  , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry("edit3"), this))
1446  , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry("edit4"), this))
1447  , m_xContents(m_xBuilder->weld_widget("box"))
1448  , m_xScrollSB(m_xBuilder->weld_scrolled_window("scrollbar", true))
1449  , m_xNewPB(m_xBuilder->weld_button("new"))
1450  , m_xDeletePB(m_xBuilder->weld_button("delete"))
1451  {
1452  Size aSize(m_xContents->get_preferred_size());
1453  m_xScrollSB->set_size_request(-1, aSize.Height());
1454 
1455  m_xEdit1->init( m_xScrollSB.get(), nullptr, m_xEdit2.get() );
1456  m_xEdit2->init( m_xScrollSB.get(), m_xEdit1.get(), m_xEdit3.get() );
1457  m_xEdit3->init( m_xScrollSB.get(), m_xEdit2.get(), m_xEdit4.get() );
1458  m_xEdit4->init( m_xScrollSB.get(), m_xEdit3.get(), nullptr );
1459 
1460  m_xOriginalLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, OriginalModifyHdl ) );
1461 
1462  m_xNewPB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, NewPBPushHdl ) );
1463  m_xNewPB->set_sensitive( false );
1464 
1465  m_xDeletePB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, DeletePBPushHdl ) );
1466  m_xDeletePB->set_sensitive( false );
1467 
1468  static_assert(MAXNUM_SUGGESTIONS >= 5, "number of suggestions should not under-run the value of 5");
1469 
1470  // 4 here, because we have 4 edits / page
1471  m_xScrollSB->vadjustment_configure(0, 0, MAXNUM_SUGGESTIONS, 1, 4, 4);
1472  m_xScrollSB->connect_vadjustment_changed(LINK(this, HangulHanjaEditDictDialog, ScrollHdl));
1473 
1474  m_xEdit1->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl1 ) );
1475  m_xEdit2->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl2 ) );
1476  m_xEdit3->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl3 ) );
1477  m_xEdit4->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl4 ) );
1478 
1479  m_xBookLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, BookLBSelectHdl ) );
1480  sal_uInt32 nDictCnt = m_rDictList.size();
1481  for( sal_uInt32 n = 0 ; n < nDictCnt ; ++n )
1482  {
1483  Reference< XConversionDictionary > xDic( m_rDictList[n] );
1484  OUString aName;
1485  if( xDic.is() )
1486  aName = xDic->getName();
1487  m_xBookLB->append_text( aName );
1488  }
1489  m_xBookLB->set_active(nSelDict);
1490 
1491  InitEditDictDialog(nSelDict);
1492  }
1493 
1495  {
1496  }
1497 
1499  {
1500  sal_uInt16 nPos = m_xScrollSB->vadjustment_get_value();
1501  m_nTopPos = nPos;
1502 
1503  SetEditText( *m_xEdit1, nPos++ );
1504  SetEditText( *m_xEdit2, nPos++ );
1505  SetEditText( *m_xEdit3, nPos++ );
1506  SetEditText( *m_xEdit4, nPos );
1507  }
1508 }
1509 
1510 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetEditText(SuggestionEdit &rEdit, sal_uInt16 nEntryNum)
RubyPosition m_ePosition
virtual ~HangulHanjaConversionDialog() override
OString stripEnd(std::string_view rIn, char c)
std::unique_ptr< weld::Button > m_xFind
#define UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES
std::unique_ptr< RubyRadioButton > m_xHangulAbove
std::unique_ptr< weld::RadioButton > m_xHangulBracketed
OUString GetCurrentSuggestion() const
retrieves the current suggestion
void SetConversionFormat(editeng::HangulHanjaConversion::ConversionFormat _eType)
void setWidth(tools::Long nWidth)
std::unique_ptr< RubyRadioButton > m_xHanjaAbove
const OUString * First()
std::unique_ptr< weld::Entry > m_xEntry
Reference< XControl > m_xControl
const tools::Rectangle & GetRect() const
std::unique_ptr< weld::Widget > m_xContents
std::unique_ptr< weld::Label > m_xOriginalWord
constexpr tools::Long Left() const
void init(const OUString &rPrimaryText, const OUString &rSecondaryText, const PseudoRubyText::RubyPosition &rPosition)
RubyPosition
void DoJump(bool _bUp)
void connect_toggled(const Link< weld::Toggleable &, void > &rLink)
virtual int vadjustment_get_lower() const =0
std::unique_ptr< weld::Button > m_xIgnoreAll
void SelectEntryPos(sal_uInt16 nPos)
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
std::unique_ptr< weld::CheckButton > m_xHanjaOnly
void DisplayListBox(bool bDisplayListBox)
#define LANGUAGE_KOREAN
SuggestionSet(std::unique_ptr< weld::ScrolledWindow > xScrolledWindow)
sal_Int64 n
SuggestionEdit(std::unique_ptr< weld::Entry > xEntry, HangulHanjaEditDictDialog *pParent)
std::unique_ptr< weld::Entry > m_xWordInput
std::unique_ptr< weld::Button > m_xEditPB
sal_uInt16 GetCode() const
void set_active(bool active)
virtual int vadjustment_get_upper() const =0
std::unique_ptr< weld::CheckButton > m_xReplaceByChar
WinBits const WB_VSCROLL
virtual void UserDraw(const UserDrawEvent &rUDEvt) override
virtual void vadjustment_set_value(int value)=0
void SetIgnoreHdl(const Link< weld::Button &, void > &_rHdl)
void * GetItemData(sal_uInt16 nItemId) const
bool get_active() const
TRISTATE_TRUE
std::vector< css::uno::Reference< css::linguistic2::XConversionDictionary > > HHDictList
DrawTextFlags
virtual ~HangulHanjaOptionsDialog() override
HangulHanjaEditDictDialog(weld::Window *pParent, HHDictList &rDictList, sal_uInt32 nSelDict)
constexpr sal_uInt16 KEY_UP
sal_uInt16 GetCount() const
void SetCurrentString(const OUString &_rNewString, const css::uno::Sequence< OUString > &_rSuggestions, bool _bOriginatesFromDocument)
css::uno::Reference< css::linguistic2::XConversionDictionaryList > m_xConversionDictionaryList
constexpr tools::Long Width() const
tools::Rectangle GetTextRect(const tools::Rectangle &rRect, const OUString &rStr, DrawTextFlags nStyle=DrawTextFlags::WordBreak, TextRectInfo *pInfo=nullptr, const vcl::ITextLayout *_pTextLayout=nullptr) const
std::unique_ptr< weld::Button > m_xOptions
std::unique_ptr< weld::ScrolledWindow > m_xScrollSB
std::unique_ptr< RubyRadioButton > m_xHanjaBelow
const vcl::Font & GetFont() const
#define WB_ITEMBORDER
void SetClickByCharacterHdl(const Link< weld::Toggleable &, void > &_rHdl)
std::unique_ptr< SuggestionEdit > m_xEdit4
virtual void set_has_default(bool has_default)=0
std::unique_ptr< weld::Button > m_xDeletePB
int nCount
std::unique_ptr< weld::Button > m_xNewPB
constexpr tools::Long GetWidth() const
SuggestionEdit * m_pPrev
void set_text(const OUString &rText)
void SetConversionFormatChangedHdl(const Link< weld::Toggleable &, void > &_rHdl)
HangulHanjaConversionDialog(weld::Widget *pParent)
sal_uInt16 GetModifier() const
sal_uInt16 nCode
std::unique_ptr< weld::RadioButton > m_xSimpleConversion
OUString GetEntry(sal_uInt16 nPos) const
void Set(const OUString &_rElement, sal_uInt16 _nNumOfElement)
constexpr void SetLeft(tools::Long v)
SuggestionDisplay(weld::Builder &rBuilder)
constexpr sal_uInt16 KEY_DOWN
std::unique_ptr< weld::Button > m_xIgnore
OutputDevice & m_rDev
void FillSuggestions(const css::uno::Sequence< OUString > &_rSuggestions)
fill the suggestion list box with suggestions for the actual input
OUString CuiResId(TranslateId aKey)
Definition: cuiresmgr.cxx:23
std::unique_ptr< weld::Button > m_xReplace
std::unique_ptr< weld::CustomWeld > m_xValueSetWin
vcl::RenderContext * GetRenderContext() const
#define SAL_MAX_INT32
#define DBG_ASSERT(sCon, aError)
int i
bool ShouldScroll(bool _bUp) const
void EnableRubySupport(bool bVal)
enables or disables the checkboxes for ruby formatted replacements
std::unique_ptr< weld::RadioButton > m_xHanjaBracketed
virtual bool has_focus() const =0
std::unique_ptr< weld::RadioButton > m_xControl
bool m_bDocumentMode
are we working for a document? This is normally true, but in case the user uses the "find" functional...
TRISTATE_FALSE
virtual void set_active(bool active)=0
void SetOptionsChangedHdl(const Link< LinkParamNone *, void > &_rHdl)
constexpr tools::Long Right() const
std::unique_ptr< weld::Button > m_xOkPB
void SetChangeHdl(const Link< weld::Button &, void > &_rHdl)
Link< LinkParamNone *, void > m_aOptionsChangedLink
void InitEditDictDialog(sal_uInt32 nSelDict)
constexpr tools::Long Top() const
IMPL_LINK(ClassificationDialog, SelectClassificationHdl, weld::ComboBox &, rBox, void)
void AddDict(const OUString &_rName, bool _bChecked)
virtual int vadjustment_get_value() const =0
constexpr void SetRight(tools::Long v)
std::unique_ptr< SuggestionDisplay > m_xSuggestions
bool GetUseBothDirections() const
should text which does not match the primary conversion direction be ignored?
std::unique_ptr< weld::Button > m_xDeletePB
Size GetOutputSizePixel() const
void SelectSuggestionHdl(bool bListBox)
#define UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST
std::unique_ptr< SuggestionEdit > m_xEdit2
const OUString * Next_()
SuggestionEdit * m_pNext
#define LINE_CNT
virtual OUString get_text() const =0
std::unique_ptr< weld::Image > m_xImage
sal_uInt16 GetItemId() const
const OUString & Get(sal_uInt16 _nNumOfElement) const
std::unique_ptr< weld::CheckButton > m_xHangulOnly
virtual ~HangulHanjaEditDictDialog() override
Link< SuggestionDisplay &, void > m_aSelectLink
void SetSelectHdl(const Link< SuggestionDisplay &, void > &rLink)
weld::ScrolledWindow * m_pScrollBar
void Paint(vcl::RenderContext &rRenderContext)
void SetIgnoreAllHdl(const Link< weld::Button &, void > &_rHdl)
void SetConversionDirectionState(bool _bTryBothDirections, editeng::HangulHanjaConversion::ConversionDirection _ePrimaryConversionDirection)
weld::Entry & rEdit
void SetFindHdl(const Link< weld::Button &, void > &_rHdl)
void Init()
reads settings from core and init controls
constexpr tools::Long Height() const
unsigned char sal_uInt8
void SetFont(const vcl::Font &rNewFont)
std::unique_ptr< SuggestionSet > m_xValueSet
virtual void grab_focus()=0
void EditModify(const weld::Entry *pEdit, sal_uInt8 nEntryOffset)
HangulHanjaNewDictDialog(weld::Window *pParent)
#define SAL_INFO(area, stream)
OUString aName
std::unique_ptr< weld::Button > m_xOkBtn
RET_OK
PseudoRubyText m_aRubyText
std::unique_ptr< weld::ComboBox > m_xOriginalLB
OUString GetSelectedEntry() const
void SetPointFont(OutputDevice &rDevice, const vcl::Font &rFont)
void set_sensitive(bool sensitive)
Reference< XExecutableDialog > m_xDialog
sal_uInt16 GetEntryCount() const
std::unique_ptr< SuggestionEdit > m_xEdit3
bool SetProperty(const OUString &rPropertyName, const css::uno::Any &rValue)
virtual short run()
Reference< XComponentContext > getProcessComponentContext()
std::unique_ptr< weld::TreeView > m_xListBox
virtual ~HangulHanjaNewDictDialog() override
constexpr OStringLiteral HID_HANGULDLG_SUGGESTIONS_LIST
Definition: helpids.h:35
const OUString * Next()
IMPL_LINK_NOARG(AccessibilityCheckEntry, GotoButtonClicked, weld::Button &, void)
FILE * init(int, char **)
ScopedVclPtr< VirtualDevice > m_xVirDev
void SetFontHeight(tools::Long nHeight)
std::unique_ptr< SuggestionList > m_xSuggestions
OUString m_sPrimaryText
void setHeight(tools::Long nHeight)
std::unique_ptr< weld::Entry > m_xDictNameED
Link< weld::Toggleable &, void > m_aClickByCharacterLink
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
std::unique_ptr< weld::CheckButton > m_xShowrecentlyfirstCB
#define UPH_IS_IGNORE_POST_POSITIONAL_WORD
VirtualDevice * get() const
ScXMLEditAttributeMap::Entry const aEntries[]
void InsertEntry(const OUString &rStr)
std::unique_ptr< SuggestionEdit > m_xEdit1
editeng::HangulHanjaConversion::ConversionFormat GetConversionFormat() const
css::uno::Any GetProperty(const OUString &rPropertyName) const
std::unique_ptr< weld::Button > m_xNewPB
constexpr OStringLiteral HID_HANGULDLG_SUGGESTIONS_GRID
Definition: helpids.h:33
std::unique_ptr< weld::ComboBox > m_xBookLB
void SetByCharacter(bool _bByCharacter)
#define UPH_ACTIVE_CONVERSION_DICTIONARIES
Size GetOptimalSize() const
std::unique_ptr< weld::Button > m_xReplaceAll
std::unique_ptr< weld::CheckButton > m_xAutoreplaceuniqueCB
constexpr sal_uInt16 KEY_SHIFT
std::unique_ptr< weld::CheckButton > m_xIgnorepostCB
std::unique_ptr< weld::TreeView > m_xDictsLB
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
void SetChangeAllHdl(const Link< weld::Button &, void > &_rHdl)
bool GetName(OUString &_rRetName) const
virtual bool get_active() const =0
aStr
editeng::HangulHanjaConversion::ConversionDirection GetDirection(editeng::HangulHanjaConversion::ConversionDirection eDefaultDirection) const
get current conversion direction to use (return argument if GetUseBothDirections is true) ...
OUString m_sSecondaryText
std::unique_ptr< RubyRadioButton > m_xHangulBelow
bool DeleteEntryFromDictionary(const css::uno::Reference< css::linguistic2::XConversionDictionary > &xDict)
void Reset(sal_uInt16 _nNumOfElement)
weld::Widget & implGetCurrentControl()
void init(weld::ScrolledWindow *pScrollBar, SuggestionEdit *pPrev, SuggestionEdit *pNext)
sal_uInt16 nPos
virtual void set_sensitive(bool sensitive)=0
constexpr sal_uInt16 KEY_TAB
#define MAXNUM_SUGGESTIONS
std::vector< OUString > m_vElements
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
HangulHanjaEditDictDialog * m_pParent
constexpr tools::Long GetHeight() const
HangulHanjaOptionsDialog(weld::Window *pParent)