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