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<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 it's 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<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  : SvtValueSet(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")))
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  OUString const aOneCharacter("AU");
298  auto nItemWidth = 2 * m_xListBox->get_pixel_size(aOneCharacter).Width();
299  m_xValueSet->SetItemWidth( nItemWidth );
300 
301  Size aSize(m_xListBox->get_approximate_digit_width() * 42, m_xListBox->get_text_height() * 5);
302  m_xValueSet->set_size_request(aSize.Width(), aSize.Height());
303  m_xListBox->set_size_request(aSize.Width(), aSize.Height());
304 
306  }
307 
309  {
310  m_xListBox->set_visible(m_bDisplayListBox);
311  if (!m_bDisplayListBox)
312  m_xValueSetWin->show();
313  else
314  m_xValueSetWin->hide();
315  }
316 
318  {
319  if (m_bDisplayListBox)
320  return *m_xListBox;
321  return *m_xValueSet->GetDrawingArea();
322  }
323 
324  void SuggestionDisplay::DisplayListBox( bool bDisplayListBox )
325  {
326  if( m_bDisplayListBox != bDisplayListBox )
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 
343  IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionValueSetHdl, SvtValueSet*, void)
344  {
345  SelectSuggestionHdl(false);
346  }
347 
348  IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionListBoxHdl, weld::TreeView&, void)
349  {
350  SelectSuggestionHdl(true);
351  }
352 
354  {
356  return;
357 
358  m_bInSelectionUpdate = true;
359  if (bListBox)
360  {
361  sal_uInt16 nPos = m_xListBox->get_selected_index();
362  m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
363  }
364  else
365  {
366  sal_uInt16 nPos = m_xValueSet->GetSelectedItemId()-1; //itemid == pos+1 (id 0 has special meaning)
367  m_xListBox->select(nPos);
368  }
369  m_bInSelectionUpdate = false;
370  m_aSelectLink.Call( *this );
371  }
372 
374  {
375  m_aSelectLink = rLink;
376  }
377 
379  {
380  m_xListBox->clear();
381  m_xValueSet->Clear();
382  }
383 
384  void SuggestionDisplay::InsertEntry( const OUString& rStr )
385  {
386  m_xListBox->append_text(rStr);
387  sal_uInt16 nItemId = m_xListBox->n_children(); //itemid == pos+1 (id 0 has special meaning)
388  m_xValueSet->InsertItem( nItemId );
389  OUString* pItemData = new OUString( rStr );
390  m_xValueSet->SetItemData( nItemId, pItemData );
391  }
392 
393  void SuggestionDisplay::SelectEntryPos( sal_uInt16 nPos )
394  {
395  m_xListBox->select(nPos);
396  m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning)
397  }
398 
400  {
401  return m_xListBox->n_children();
402  }
403 
404  OUString SuggestionDisplay::GetEntry( sal_uInt16 nPos ) const
405  {
406  return m_xListBox->get_text( nPos );
407  }
408 
410  {
411  return m_xListBox->get_selected_text();
412  }
413 
415  {
418  }
419 
421  : GenericDialogController(pParent, "cui/ui/hangulhanjaconversiondialog.ui", "HangulHanjaConversionDialog")
422  , m_bDocumentMode( true )
423  , m_xFind(m_xBuilder->weld_button("find"))
424  , m_xIgnore(m_xBuilder->weld_button("ignore"))
425  , m_xIgnoreAll(m_xBuilder->weld_button("ignoreall"))
426  , m_xReplace(m_xBuilder->weld_button("replace"))
427  , m_xReplaceAll(m_xBuilder->weld_button("replaceall"))
428  , m_xOptions(m_xBuilder->weld_button("options"))
429  , m_xSuggestions(new SuggestionDisplay(*m_xBuilder))
430  , m_xSimpleConversion(m_xBuilder->weld_radio_button("simpleconversion"))
431  , m_xHangulBracketed(m_xBuilder->weld_radio_button("hangulbracket"))
432  , m_xHanjaBracketed(m_xBuilder->weld_radio_button("hanjabracket"))
433  , m_xWordInput(m_xBuilder->weld_entry("wordinput"))
434  , m_xOriginalWord(m_xBuilder->weld_label("originalword"))
435  , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_above")))
436  , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_below")))
437  , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_above")))
438  , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_below")))
439  , m_xHangulOnly(m_xBuilder->weld_check_button("hangulonly"))
440  , m_xHanjaOnly(m_xBuilder->weld_check_button("hanjaonly"))
441  , m_xReplaceByChar(m_xBuilder->weld_check_button("replacebychar"))
442  {
443  m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42,
444  m_xOriginalWord->get_text_height() * 5);
445 
446  const OUString sHangul(CuiResId(RID_SVXSTR_HANGUL));
447  const OUString sHanja(CuiResId(RID_SVXSTR_HANJA));
448  m_xHanjaAbove->init( sHangul, sHanja, PseudoRubyText::eAbove );
449  m_xHanjaBelow->init( sHangul, sHanja, PseudoRubyText::eBelow );
450  m_xHangulAbove->init( sHanja, sHangul, PseudoRubyText::eAbove );
451  m_xHangulBelow->init( sHanja, sHangul, PseudoRubyText::eBelow );
452 
453  m_xWordInput->connect_changed( LINK( this, HangulHanjaConversionDialog, OnSuggestionModified ) );
454  m_xSuggestions->SetSelectHdl( LINK( this, HangulHanjaConversionDialog, OnSuggestionSelected ) );
455  m_xReplaceByChar->connect_toggled( LINK( this, HangulHanjaConversionDialog, ClickByCharacterHdl ) );
456  m_xHangulOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
457  m_xHanjaOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) );
458  m_xOptions->connect_clicked(LINK(this, HangulHanjaConversionDialog, OnOption));
459 
460  // initial focus
461  FocusSuggestion( );
462 
463  // initial control values
464  m_xSimpleConversion->set_active(true);
465 
466  m_xSuggestions->SetHelpIds();
467  }
468 
470  {
471  }
472 
473  void HangulHanjaConversionDialog::FillSuggestions( const css::uno::Sequence< OUString >& _rSuggestions )
474  {
475  m_xSuggestions->Clear();
476  for ( auto const & suggestion : _rSuggestions )
477  m_xSuggestions->InsertEntry( suggestion );
478 
479  // select the first suggestion, and fill in the suggestion edit field
480  OUString sFirstSuggestion;
481  if ( m_xSuggestions->GetEntryCount() )
482  {
483  sFirstSuggestion = m_xSuggestions->GetEntry( 0 );
484  m_xSuggestions->SelectEntryPos( 0 );
485  }
486  m_xWordInput->set_text( sFirstSuggestion );
487  m_xWordInput->save_value();
488  OnSuggestionModified( *m_xWordInput );
489  }
490 
492  {
493  m_aOptionsChangedLink = rHdl;
494  }
495 
497  {
498  m_xIgnore->connect_clicked(rHdl);
499  }
500 
502  {
503  m_xIgnoreAll->connect_clicked(rHdl);
504  }
505 
507  {
508  m_xReplace->connect_clicked(rHdl);
509  }
510 
512  {
513  m_xReplaceAll->connect_clicked(rHdl);
514  }
515 
517  {
518  m_xFind->connect_clicked(rHdl);
519  }
520 
522  {
523  m_xSimpleConversion->connect_clicked( rHdl );
524  m_xHangulBracketed->connect_clicked( rHdl );
525  m_xHanjaBracketed->connect_clicked( rHdl );
526  m_xHanjaAbove->connect_clicked( rHdl );
527  m_xHanjaBelow->connect_clicked( rHdl );
528  m_xHangulAbove->connect_clicked( rHdl );
529  m_xHangulBelow->connect_clicked( rHdl );
530  }
531 
533  {
534  m_aClickByCharacterLink = _rHdl;
535  }
536 
538  {
539  m_xWordInput->set_text(m_xSuggestions->GetSelectedEntry());
540  OnSuggestionModified( *m_xWordInput );
541  }
542 
543  IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionModified, weld::Entry&, void )
544  {
545  m_xFind->set_sensitive(m_xWordInput->get_value_changed_from_saved());
546 
547  bool bSameLen = m_xWordInput->get_text().getLength() == m_xOriginalWord->get_label().getLength();
548  m_xReplace->set_sensitive( m_bDocumentMode && bSameLen );
549  m_xReplaceAll->set_sensitive( m_bDocumentMode && bSameLen );
550  }
551 
552  IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::ToggleButton&, rBox, void)
553  {
554  m_aClickByCharacterLink.Call(rBox);
555  bool bByCharacter = rBox.get_active();
556  m_xSuggestions->DisplayListBox( !bByCharacter );
557  }
558 
559  IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::ToggleButton&, rBox, void)
560  {
561  weld::CheckButton* pOtherBox = nullptr;
562  if (&rBox == m_xHangulOnly.get())
563  pOtherBox = m_xHanjaOnly.get();
564  else
565  pOtherBox = m_xHangulOnly.get();
566  bool bBoxChecked = rBox.get_active();
567  if (bBoxChecked)
568  pOtherBox->set_active(false);
569  pOtherBox->set_sensitive(!bBoxChecked);
570  }
571 
573  {
574  HangulHanjaOptionsDialog aOptDlg(m_xDialog.get());
575  aOptDlg.run();
576  m_aOptionsChangedLink.Call( nullptr );
577  }
578 
580  {
581  return m_xOriginalWord->get_label();
582  }
583 
585  {
586  m_xWordInput->grab_focus();
587  }
588 
589  void HangulHanjaConversionDialog::SetCurrentString( const OUString& _rNewString,
590  const Sequence< OUString >& _rSuggestions, bool _bOriginatesFromDocument )
591  {
592  m_xOriginalWord->set_label(_rNewString);
593 
594  bool bOldDocumentMode = m_bDocumentMode;
595  m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions!
596  FillSuggestions( _rSuggestions );
597 
598  m_xIgnoreAll->set_sensitive( m_bDocumentMode );
599 
600  // switch the def button depending if we're working for document text
601  if (bOldDocumentMode != m_bDocumentMode)
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  }
620 
622  {
623  return m_xWordInput->get_text();
624  }
625 
627  {
628  m_xReplaceByChar->set_active( _bByCharacter );
629  m_xSuggestions->DisplayListBox( !_bByCharacter );
630  }
631 
633  bool _bTryBothDirections,
634  HHC::ConversionDirection ePrimaryConversionDirection )
635  {
636  // default state: try both direction
637  m_xHangulOnly->set_active( false );
638  m_xHangulOnly->set_sensitive(true);
639  m_xHanjaOnly->set_active( false );
640  m_xHanjaOnly->set_sensitive(true);
641 
642  if (!_bTryBothDirections)
643  {
644  weld::CheckButton* pBox = ePrimaryConversionDirection == HHC::eHangulToHanja ?
645  m_xHangulOnly.get() : m_xHanjaOnly.get();
646  pBox->set_active(true);
647  OnConversionDirectionClicked(*pBox);
648  }
649  }
650 
652  {
653  return !m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active();
654  }
655 
657  HHC::ConversionDirection eDefaultDirection ) const
658  {
659  HHC::ConversionDirection eDirection = eDefaultDirection;
660  if (m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active())
661  eDirection = HHC::eHangulToHanja;
662  else if (!m_xHangulOnly->get_active() && m_xHanjaOnly->get_active())
663  eDirection = HHC::eHanjaToHangul;
664  return eDirection;
665  }
666 
667  void HangulHanjaConversionDialog::SetConversionFormat( HHC::ConversionFormat _eType )
668  {
669  switch ( _eType )
670  {
671  case HHC::eSimpleConversion: m_xSimpleConversion->set_active(true); break;
672  case HHC::eHangulBracketed: m_xHangulBracketed->set_active(true); break;
673  case HHC::eHanjaBracketed: m_xHanjaBracketed->set_active(true); break;
674  case HHC::eRubyHanjaAbove: m_xHanjaAbove->set_active(true); break;
675  case HHC::eRubyHanjaBelow: m_xHanjaBelow->set_active(true); break;
676  case HHC::eRubyHangulAbove: m_xHangulAbove->set_active(true); break;
677  case HHC::eRubyHangulBelow: m_xHangulBelow->set_active(true); break;
678  default:
679  OSL_FAIL( "HangulHanjaConversionDialog::SetConversionFormat: unknown type!" );
680  }
681  }
682 
684  {
685  if ( m_xSimpleConversion->get_active() )
686  return HHC::eSimpleConversion;
687  if ( m_xHangulBracketed->get_active() )
688  return HHC::eHangulBracketed;
689  if ( m_xHanjaBracketed->get_active() )
690  return HHC::eHanjaBracketed;
691  if ( m_xHanjaAbove->get_active() )
692  return HHC::eRubyHanjaAbove;
693  if ( m_xHanjaBelow->get_active() )
694  return HHC::eRubyHanjaBelow;
695  if ( m_xHangulAbove->get_active() )
696  return HHC::eRubyHangulAbove;
697  if ( m_xHangulBelow->get_active() )
698  return HHC::eRubyHangulBelow;
699 
700  OSL_FAIL( "HangulHanjaConversionDialog::GetConversionFormat: no radio checked?" );
701  return HHC::eSimpleConversion;
702  }
703 
705  {
706  m_xHanjaAbove->set_sensitive( bVal );
707  m_xHanjaBelow->set_sensitive( bVal );
708  m_xHangulAbove->set_sensitive( bVal );
709  m_xHangulBelow->set_sensitive( bVal );
710  }
711 
713  {
714  if( !m_xConversionDictionaryList.is() )
715  {
716  m_xConversionDictionaryList = ConversionDictionaryList::create( ::comphelper::getProcessComponentContext() );
717  }
718 
719  m_aDictList.clear();
720  m_xDictsLB->clear();
721 
722  Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
723  if( xNameCont.is() )
724  {
725  Sequence< OUString > aDictNames( xNameCont->getElementNames() );
726 
727  const OUString* pDic = aDictNames.getConstArray();
728  sal_Int32 nCount = aDictNames.getLength();
729 
730  sal_Int32 i;
731  for( i = 0 ; i < nCount ; ++i )
732  {
733  Any aAny( xNameCont->getByName( pDic[ i ] ) );
734  Reference< XConversionDictionary > xDic;
735  if( ( aAny >>= xDic ) && xDic.is() )
736  {
737  if( LANGUAGE_KOREAN == LanguageTag( xDic->getLocale() ).getLanguageType() )
738  {
739  m_aDictList.push_back( xDic );
740  AddDict( xDic->getName(), xDic->isActive() );
741  }
742  }
743  }
744  }
745  if (m_xDictsLB->n_children())
746  m_xDictsLB->select(0);
747  }
748 
750  {
751  sal_uInt32 nCnt = m_aDictList.size();
752  sal_uInt32 n = 0;
753  sal_uInt32 nActiveDics = 0;
754  Sequence< OUString > aActiveDics;
755 
756  aActiveDics.realloc( nCnt );
757  OUString* pActActiveDic = aActiveDics.getArray();
758 
759  while( nCnt )
760  {
761  Reference< XConversionDictionary > xDict = m_aDictList[ n ];
762 
763  DBG_ASSERT( xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..." );
764 
765  bool bActive = m_xDictsLB->get_toggle(n, 0) == TRISTATE_TRUE;
766  xDict->setActive( bActive );
767  Reference< util::XFlushable > xFlush( xDict, uno::UNO_QUERY );
768  if( xFlush.is() )
769  xFlush->flush();
770 
771  if( bActive )
772  {
773  pActActiveDic[ nActiveDics ] = xDict->getName();
774  ++nActiveDics;
775  }
776 
777  ++n;
778  --nCnt;
779  }
780 
781  // save configuration
782  aActiveDics.realloc( nActiveDics );
783  Any aTmp;
784  SvtLinguConfig aLngCfg;
785  aTmp <<= aActiveDics;
787 
788  aTmp <<= m_xIgnorepostCB->get_active();
790 
791  aTmp <<= m_xShowrecentlyfirstCB->get_active();
793 
794  aTmp <<= m_xAutoreplaceuniqueCB->get_active();
796 
797  m_xDialog->response(RET_OK);
798  }
799 
801  {
802  bool bSel = m_xDictsLB->get_selected_index() != -1;
803 
804  m_xEditPB->set_sensitive(bSel);
805  m_xDeletePB->set_sensitive(bSel);
806  }
807 
809  {
810  OUString aName;
811  HangulHanjaNewDictDialog aNewDlg(m_xDialog.get());
812  aNewDlg.run();
813  if (aNewDlg.GetName(aName))
814  {
815  if( m_xConversionDictionaryList.is() )
816  {
817  try
818  {
819  Reference< XConversionDictionary > xDic =
820  m_xConversionDictionaryList->addNewDictionary( aName, LanguageTag::convertToLocale( LANGUAGE_KOREAN ), ConversionDictionaryType::HANGUL_HANJA );
821 
822  if( xDic.is() )
823  {
824  //adapt local caches:
825  m_aDictList.push_back( xDic );
826  AddDict( xDic->getName(), xDic->isActive() );
827  }
828  }
829  catch( const ElementExistException& )
830  {
831  }
832  catch( const NoSupportException& )
833  {
834  }
835  }
836  }
837  }
838 
840  {
841  int nEntry = m_xDictsLB->get_selected_index();
842  DBG_ASSERT(nEntry != -1, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not be possible with no selection!");
843  if (nEntry != -1)
844  {
845  HangulHanjaEditDictDialog aEdDlg(m_xDialog.get(), m_aDictList, nEntry);
846  aEdDlg.run();
847  }
848  }
849 
851  {
852  int nSelPos = m_xDictsLB->get_selected_index();
853  if (nSelPos != -1)
854  {
855  Reference< XConversionDictionary > xDic( m_aDictList[ nSelPos ] );
856  if( m_xConversionDictionaryList.is() && xDic.is() )
857  {
858  Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer();
859  if( xNameCont.is() )
860  {
861  try
862  {
863  xNameCont->removeByName( xDic->getName() );
864 
865  //adapt local caches:
866  m_aDictList.erase(m_aDictList.begin()+nSelPos );
867  m_xDictsLB->remove(nSelPos);
868  }
869  catch( const ElementExistException& )
870  {
871  }
872  catch( const NoSupportException& )
873  {
874  }
875  }
876  }
877  }
878  }
879 
881  : GenericDialogController(pParent, "cui/ui/hangulhanjaoptdialog.ui", "HangulHanjaOptDialog")
882  , m_xDictsLB(m_xBuilder->weld_tree_view("dicts"))
883  , m_xIgnorepostCB(m_xBuilder->weld_check_button("ignorepost"))
884  , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button("showrecentfirst"))
885  , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button("autoreplaceunique"))
886  , m_xNewPB(m_xBuilder->weld_button("new"))
887  , m_xEditPB(m_xBuilder->weld_button("edit"))
888  , m_xDeletePB(m_xBuilder->weld_button("delete"))
889  , m_xOkPB(m_xBuilder->weld_button("ok"))
890  {
891  m_xDictsLB->set_size_request(m_xDictsLB->get_approximate_digit_width() * 32,
892  m_xDictsLB->get_height_rows(5));
893 
894  std::vector<int> aWidths;
895  aWidths.push_back(m_xDictsLB->get_checkbox_column_width());
896  m_xDictsLB->set_column_fixed_widths(aWidths);
897 
898  m_xDictsLB->connect_changed( LINK( this, HangulHanjaOptionsDialog, DictsLB_SelectHdl ) );
899 
900  m_xOkPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, OkHdl ) );
901  m_xNewPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, NewDictHdl ) );
902  m_xEditPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, EditDictHdl ) );
903  m_xDeletePB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, DeleteDictHdl ) );
904 
905  SvtLinguConfig aLngCfg;
906  Any aTmp;
907  bool bVal = bool();
909  if( aTmp >>= bVal )
910  m_xIgnorepostCB->set_active( bVal );
911 
913  if( aTmp >>= bVal )
914  m_xShowrecentlyfirstCB->set_active( bVal );
915 
917  if( aTmp >>= bVal )
918  m_xAutoreplaceuniqueCB->set_active( bVal );
919 
920  Init();
921  }
922 
924  {
925  }
926 
927  void HangulHanjaOptionsDialog::AddDict(const OUString& rName, bool bChecked)
928  {
929  m_xDictsLB->append();
930  int nRow = m_xDictsLB->n_children() - 1;
931  m_xDictsLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE, 0);
932  m_xDictsLB->set_text(nRow, rName, 1);
933  m_xDictsLB->set_id(nRow, rName);
934  }
935 
937  {
938  OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));
939 
940  m_bEntered = !aName.isEmpty();
941  if (m_bEntered)
942  m_xDictNameED->set_text(aName); // do this in case of trailing chars have been deleted
943 
944  m_xDialog->response(RET_OK);
945  }
946 
948  {
949  OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '));
950 
951  m_xOkBtn->set_sensitive(!aName.isEmpty());
952  }
953 
955  : GenericDialogController(pParent, "cui/ui/hangulhanjaadddialog.ui", "HangulHanjaAddDialog")
956  , m_bEntered(false)
957  , m_xOkBtn(m_xBuilder->weld_button("ok"))
958  , m_xDictNameED(m_xBuilder->weld_entry("entry"))
959  {
960  m_xOkBtn->connect_clicked( LINK( this, HangulHanjaNewDictDialog, OKHdl ) );
961  m_xDictNameED->connect_changed( LINK( this, HangulHanjaNewDictDialog, ModifyHdl ) );
962  }
963 
965  {
966  }
967 
968  bool HangulHanjaNewDictDialog::GetName( OUString& _rRetName ) const
969  {
970  if( m_bEntered )
971  _rRetName = comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ');
972 
973  return m_bEntered;
974  }
975 
977  {
978  private:
979  protected:
980  std::vector<OUString> m_vElements;
981  sal_uInt16 m_nNumOfEntries;
982  // index of the internal iterator, used for First() and Next() methods
983  sal_uInt16 m_nAct;
984 
985  const OUString* Next_();
986  public:
987  SuggestionList();
988  ~SuggestionList();
989 
990  void Set( const OUString& _rElement, sal_uInt16 _nNumOfElement );
991  void Reset( sal_uInt16 _nNumOfElement );
992  const OUString & Get( sal_uInt16 _nNumOfElement ) const;
993  void Clear();
994 
995  const OUString* First();
996  const OUString* Next();
997 
998  sal_uInt16 GetCount() const { return m_nNumOfEntries; }
999  };
1000 
1002  m_vElements(MAXNUM_SUGGESTIONS)
1003  {
1004  m_nAct = m_nNumOfEntries = 0;
1005  }
1006 
1008  {
1009  Clear();
1010  }
1011 
1012  void SuggestionList::Set( const OUString& _rElement, sal_uInt16 _nNumOfElement )
1013  {
1014  m_vElements[_nNumOfElement] = _rElement;
1015  ++m_nNumOfEntries;
1016  }
1017 
1018  void SuggestionList::Reset( sal_uInt16 _nNumOfElement )
1019  {
1020  m_vElements[_nNumOfElement].clear();
1021  --m_nNumOfEntries;
1022  }
1023 
1024  const OUString& SuggestionList::Get( sal_uInt16 _nNumOfElement ) const
1025  {
1026  return m_vElements[_nNumOfElement];
1027  }
1028 
1030  {
1031  if( m_nNumOfEntries )
1032  {
1033  for (auto & vElement : m_vElements)
1034  vElement.clear();
1035  m_nNumOfEntries = m_nAct = 0;
1036  }
1037  }
1038 
1039  const OUString* SuggestionList::Next_()
1040  {
1041  while( m_nAct < m_vElements.size() )
1042  {
1043  auto & s = m_vElements[ m_nAct ];
1044  if (!s.isEmpty())
1045  return &s;
1046  ++m_nAct;
1047  }
1048 
1049  return nullptr;
1050  }
1051 
1052  const OUString* SuggestionList::First()
1053  {
1054  m_nAct = 0;
1055  return Next_();
1056  }
1057 
1058  const OUString* SuggestionList::Next()
1059  {
1060  const OUString* pRet;
1061 
1062  if( m_nAct < m_nNumOfEntries )
1063  {
1064  ++m_nAct;
1065  pRet = Next_();
1066  }
1067  else
1068  pRet = nullptr;
1069 
1070  return pRet;
1071  }
1072 
1073 
1074  bool SuggestionEdit::ShouldScroll( bool _bUp ) const
1075  {
1076  bool bRet = false;
1077 
1078  if( _bUp )
1079  {
1080  if( !m_pPrev )
1082  }
1083  else
1084  {
1085  if( !m_pNext )
1087  }
1088 
1089  return bRet;
1090  }
1091 
1092  void SuggestionEdit::DoJump( bool _bUp )
1093  {
1096  }
1097 
1098  SuggestionEdit::SuggestionEdit(std::unique_ptr<weld::Entry> xEntry, HangulHanjaEditDictDialog* pParent)
1099  : m_pParent(pParent)
1100  , m_pPrev(nullptr)
1101  , m_pNext(nullptr)
1102  , m_pScrollBar(nullptr)
1103  , m_xEntry(std::move(xEntry))
1104  {
1105  m_xEntry->connect_key_press(LINK(this, SuggestionEdit, KeyInputHdl));
1106  }
1107 
1108  IMPL_LINK(SuggestionEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
1109  {
1110  bool bHandled = false;
1111 
1112  const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
1113  sal_uInt16 nMod = rKeyCode.GetModifier();
1114  sal_uInt16 nCode = rKeyCode.GetCode();
1115  if( nCode == KEY_TAB && ( !nMod || KEY_SHIFT == nMod ) )
1116  {
1117  bool bUp = KEY_SHIFT == nMod;
1118  if( ShouldScroll( bUp ) )
1119  {
1120  DoJump( bUp );
1121  m_xEntry->select_region(0, -1);
1122  // Tab-travel doesn't really happen, so emulate it by setting a selection manually
1123  bHandled = true;
1124  }
1125  }
1126  else if( KEY_UP == nCode || KEY_DOWN == nCode )
1127  {
1128  bool bUp = KEY_UP == nCode;
1129  if( ShouldScroll( bUp ) )
1130  {
1131  DoJump( bUp );
1132  bHandled = true;
1133  }
1134  else if( bUp )
1135  {
1136  if( m_pPrev )
1137  {
1138  m_pPrev->grab_focus();
1139  bHandled = true;
1140  }
1141  }
1142  else if( m_pNext )
1143  {
1144  m_pNext->grab_focus();
1145  bHandled = true;
1146  }
1147  }
1148 
1149  return bHandled;
1150  }
1151 
1153  {
1154  m_pScrollBar = pScrollBar;
1155  m_pPrev = pPrev;
1156  m_pNext = pNext;
1157  }
1158 
1159  namespace
1160  {
1161  bool GetConversions( const Reference< XConversionDictionary >& _xDict,
1162  const OUString& _rOrg,
1163  Sequence< OUString >& _rEntries )
1164  {
1165  bool bRet = false;
1166  if( _xDict.is() && !_rOrg.isEmpty() )
1167  {
1168  try
1169  {
1170  _rEntries = _xDict->getConversions( _rOrg,
1171  0,
1172  _rOrg.getLength(),
1173  ConversionDirection_FROM_LEFT,
1174  css::i18n::TextConversionOption::NONE );
1175  bRet = _rEntries.hasElements();
1176  }
1177  catch( const IllegalArgumentException& )
1178  {
1179  }
1180  }
1181 
1182  return bRet;
1183  }
1184  }
1185 
1187  {
1188  UpdateScrollbar();
1189  }
1190 
1192  {
1193  m_bModifiedOriginal = true;
1194  m_aOriginal = comphelper::string::stripEnd( m_xOriginalLB->get_active_text(), ' ' );
1195 
1196  UpdateSuggestions();
1197  UpdateButtonStates();
1198  }
1199 
1200  IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl1, weld::Entry&, rEdit, void )
1201  {
1202  EditModify( &rEdit, 0 );
1203  }
1204 
1205  IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl2, weld::Entry&, rEdit, void )
1206  {
1207  EditModify( &rEdit, 1 );
1208  }
1209 
1210  IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl3, weld::Entry&, rEdit, void )
1211  {
1212  EditModify( &rEdit, 2 );
1213  }
1214 
1215  IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl4, weld::Entry&, rEdit, void )
1216  {
1217  EditModify( &rEdit, 3 );
1218  }
1219 
1221  {
1222  InitEditDictDialog( m_xBookLB->get_active() );
1223  }
1224 
1226  {
1227  DBG_ASSERT( m_xSuggestions, "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..." );
1228  Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
1229  if( xDict.is() && m_xSuggestions )
1230  {
1231  //delete old entry
1232  bool bRemovedSomething = DeleteEntryFromDictionary( xDict );
1233 
1234  OUString aLeft( m_aOriginal );
1235  const OUString* pRight = m_xSuggestions->First();
1236  bool bAddedSomething = false;
1237  while( pRight )
1238  {
1239  try
1240  {
1241  //add new entry
1242  xDict->addEntry( aLeft, *pRight );
1243  bAddedSomething = true;
1244  }
1245  catch( const IllegalArgumentException& )
1246  {
1247  }
1248  catch( const ElementExistException& )
1249  {
1250  }
1251 
1252  pRight = m_xSuggestions->Next();
1253  }
1254 
1255  if( bAddedSomething || bRemovedSomething )
1256  InitEditDictDialog( m_nCurrentDict );
1257  }
1258  else
1259  {
1260  SAL_INFO( "cui.dialogs", "dictionary faded away..." );
1261  }
1262  }
1263 
1264  bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( const Reference< XConversionDictionary >& xDict )
1265  {
1266  bool bRemovedSomething = false;
1267  if( xDict.is() )
1268  {
1269  OUString aOrg( m_aOriginal );
1271  GetConversions( xDict, m_aOriginal, aEntries );
1272 
1273  sal_uInt32 n = aEntries.getLength();
1274  OUString* pEntry = aEntries.getArray();
1275  while( n )
1276  {
1277  try
1278  {
1279  xDict->removeEntry( aOrg, *pEntry );
1280  bRemovedSomething = true;
1281  }
1282  catch( const NoSuchElementException& )
1283  { // can not be...
1284  }
1285 
1286  ++pEntry;
1287  --n;
1288  }
1289  }
1290  return bRemovedSomething;
1291  }
1292 
1294  {
1295  if( DeleteEntryFromDictionary( m_rDictList[ m_nCurrentDict ] ) )
1296  {
1297  m_aOriginal.clear();
1298  m_bModifiedOriginal = true;
1299  InitEditDictDialog( m_nCurrentDict );
1300  }
1301  }
1302 
1304  {
1305  if( m_xSuggestions )
1306  m_xSuggestions->Clear();
1307 
1308  if( m_nCurrentDict != nSelDict )
1309  {
1310  m_nCurrentDict = nSelDict;
1311  m_aOriginal.clear();
1312  m_bModifiedOriginal = true;
1313  }
1314 
1315  UpdateOriginalLB();
1316 
1317  m_xOriginalLB->set_entry_text( !m_aOriginal.isEmpty() ? m_aOriginal : m_aEditHintText);
1318  m_xOriginalLB->select_entry_region(0, -1);
1319  m_xOriginalLB->grab_focus();
1320 
1323  }
1324 
1326  {
1327  m_xOriginalLB->clear();
1328  Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ];
1329  if( xDict.is() )
1330  {
1331  Sequence< OUString > aEntries = xDict->getConversionEntries( ConversionDirection_FROM_LEFT );
1332  sal_uInt32 n = aEntries.getLength();
1333  OUString* pEntry = aEntries.getArray();
1334  while( n )
1335  {
1336  m_xOriginalLB->append_text( *pEntry );
1337 
1338  ++pEntry;
1339  --n;
1340  }
1341  }
1342  else
1343  {
1344  SAL_INFO( "cui.dialogs", "dictionary faded away..." );
1345  }
1346  }
1347 
1349  {
1350  bool bHaveValidOriginalString = !m_aOriginal.isEmpty() && m_aOriginal != m_aEditHintText;
1351  bool bNew = bHaveValidOriginalString && m_xSuggestions && m_xSuggestions->GetCount() > 0;
1352  bNew = bNew && ( m_bModifiedSuggestions || m_bModifiedOriginal );
1353 
1354  m_xNewPB->set_sensitive( bNew );
1355  m_xDeletePB->set_sensitive(!m_bModifiedOriginal && bHaveValidOriginalString);
1356  }
1357 
1359  {
1361  bool bFound = GetConversions( m_rDictList[ m_nCurrentDict ], m_aOriginal, aEntries );
1362  if( bFound )
1363  {
1364  m_bModifiedOriginal = false;
1365 
1366  if( m_xSuggestions )
1367  m_xSuggestions->Clear();
1368 
1369  //fill found entries into boxes
1370  sal_uInt32 nCnt = aEntries.getLength();
1371  if( nCnt )
1372  {
1373  if( !m_xSuggestions )
1374  m_xSuggestions.reset(new SuggestionList);
1375 
1376  const OUString* pSugg = aEntries.getConstArray();
1377  sal_uInt32 n = 0;
1378  while( nCnt )
1379  {
1380  m_xSuggestions->Set( pSugg[ n ], sal_uInt16( n ) );
1381  ++n;
1382  --nCnt;
1383  }
1384  }
1385  m_bModifiedSuggestions = false;
1386  }
1387 
1388  m_xScrollSB->vadjustment_set_value( 0 );
1389  UpdateScrollbar(); // will force edits to be filled new
1390  }
1391 
1392  void HangulHanjaEditDictDialog::SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum)
1393  {
1394  OUString aStr;
1395  if( m_xSuggestions )
1396  {
1397  aStr = m_xSuggestions->Get(nEntryNum);
1398  }
1399 
1400  rEdit.set_text(aStr);
1401  }
1402 
1404  {
1405  m_bModifiedSuggestions = true;
1406 
1407  OUString aTxt( pEdit->get_text() );
1408  sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset;
1409  if( aTxt.isEmpty() )
1410  {
1411  //reset suggestion
1412  if( m_xSuggestions )
1413  m_xSuggestions->Reset( nEntryNum );
1414  }
1415  else
1416  {
1417  //set suggestion
1418  if( !m_xSuggestions )
1419  m_xSuggestions.reset(new SuggestionList);
1420  m_xSuggestions->Set( aTxt, nEntryNum );
1421  }
1422 
1424  }
1425 
1427  : GenericDialogController(pParent, "cui/ui/hangulhanjaeditdictdialog.ui", "HangulHanjaEditDictDialog")
1428  , m_aEditHintText ( CuiResId(RID_SVXSTR_EDITHINT) )
1429  , m_rDictList ( _rDictList )
1430  , m_nCurrentDict ( 0xFFFFFFFF )
1431  , m_nTopPos ( 0 )
1432  , m_bModifiedSuggestions ( false )
1433  , m_bModifiedOriginal ( false )
1434  , m_xBookLB(m_xBuilder->weld_combo_box("book"))
1435  , m_xOriginalLB(m_xBuilder->weld_combo_box("original"))
1436  , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry("edit1"), this))
1437  , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry("edit2"), this))
1438  , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry("edit3"), this))
1439  , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry("edit4"), this))
1440  , m_xContents(m_xBuilder->weld_widget("box"))
1441  , m_xScrollSB(m_xBuilder->weld_scrolled_window("scrollbar"))
1442  , m_xNewPB(m_xBuilder->weld_button("new"))
1443  , m_xDeletePB(m_xBuilder->weld_button("delete"))
1444  {
1445  m_xScrollSB->set_user_managed_scrolling();
1446 
1447  Size aSize(m_xContents->get_preferred_size());
1448  m_xScrollSB->set_size_request(-1, aSize.Height());
1449 
1450  m_xEdit1->init( m_xScrollSB.get(), nullptr, m_xEdit2.get() );
1451  m_xEdit2->init( m_xScrollSB.get(), m_xEdit1.get(), m_xEdit3.get() );
1452  m_xEdit3->init( m_xScrollSB.get(), m_xEdit2.get(), m_xEdit4.get() );
1453  m_xEdit4->init( m_xScrollSB.get(), m_xEdit3.get(), nullptr );
1454 
1455  m_xOriginalLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, OriginalModifyHdl ) );
1456 
1457  m_xNewPB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, NewPBPushHdl ) );
1458  m_xNewPB->set_sensitive( false );
1459 
1460  m_xDeletePB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, DeletePBPushHdl ) );
1461  m_xDeletePB->set_sensitive( false );
1462 
1463  static_assert(MAXNUM_SUGGESTIONS >= 5, "number of suggestions should not under-run the value of 5");
1464 
1465  // 4 here, because we have 4 edits / page
1466  m_xScrollSB->vadjustment_configure(0, 0, MAXNUM_SUGGESTIONS, 1, 4, 4);
1467  m_xScrollSB->connect_vadjustment_changed(LINK(this, HangulHanjaEditDictDialog, ScrollHdl));
1468 
1469  m_xEdit1->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl1 ) );
1470  m_xEdit2->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl2 ) );
1471  m_xEdit3->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl3 ) );
1472  m_xEdit4->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl4 ) );
1473 
1474  m_xBookLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, BookLBSelectHdl ) );
1475  sal_uInt32 nDictCnt = m_rDictList.size();
1476  for( sal_uInt32 n = 0 ; n < nDictCnt ; ++n )
1477  {
1478  Reference< XConversionDictionary > xDic( m_rDictList[n] );
1479  OUString aName;
1480  if( xDic.is() )
1481  aName = xDic->getName();
1482  m_xBookLB->append_text( aName );
1483  }
1484  m_xBookLB->set_active(nSelDict);
1485 
1486  InitEditDictDialog(nSelDict);
1487  }
1488 
1490  {
1491  }
1492 
1494  {
1495  sal_uInt16 nPos = m_xScrollSB->vadjustment_get_value();
1496  m_nTopPos = nPos;
1497 
1498  SetEditText( *m_xEdit1, nPos++ );
1499  SetEditText( *m_xEdit2, nPos++ );
1500  SetEditText( *m_xEdit3, nPos++ );
1501  SetEditText( *m_xEdit4, nPos );
1502  }
1503 }
1504 
1505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
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
long GetWidth() const
std::unique_ptr< weld::Button > m_xFind
OString stripEnd(const OString &rIn, sal_Char c)
#define UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES
long GetHeight() const
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)
std::unique_ptr< RubyRadioButton > m_xHanjaAbove
const OUString * First()
#define KEY_TAB
std::unique_ptr< weld::Entry > m_xEntry
Reference< XControl > m_xControl
const tools::Rectangle & GetRect() const
std::unique_ptr< weld::Widget > m_xContents
long Height() const
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)
IMPL_LINK_NOARG(ClassificationDialog, OnAsyncExpandHdl, void *, void)
std::unique_ptr< weld::CheckButton > m_xHanjaOnly
void DisplayListBox(bool bDisplayListBox)
#define KEY_SHIFT
#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)
bool get_active() const
TRISTATE_TRUE
virtual bool get_active() const =0
std::vector< css::uno::Reference< css::linguistic2::XConversionDictionary > > HHDictList
virtual ~HangulHanjaOptionsDialog() override
HangulHanjaEditDictDialog(weld::Window *pParent, HHDictList &rDictList, sal_uInt32 nSelDict)
sal_uInt16 GetCount() const
void SetCurrentString(const OUString &_rNewString, const css::uno::Sequence< OUString > &_rSuggestions, bool _bOriginatesFromDocument)
void Move(long nHorzMoveDelta, long nVertMoveDelta)
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
long Right() 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
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
long Top() 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:31
OUString GetEntry(sal_uInt16 nPos) const
void Set(const OUString &_rElement, sal_uInt16 _nNumOfElement)
SuggestionDisplay(weld::Builder &rBuilder)
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)
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
int i
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 SetRight(long v)
void SetOptionsChangedHdl(const Link< LinkParamNone *, void > &_rHdl)
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
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:30
sal_uInt16 GetItemId() const
const OUString & Get(sal_uInt16 _nNumOfElement) const
void * GetItemData(sal_uInt16 nItemId) 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)
#define KEY_DOWN
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)
void SetFontHeight(long nHeight)
virtual short run()
Reference< XComponentContext > getProcessComponentContext()
std::unique_ptr< weld::TreeView > m_xListBox
virtual ~HangulHanjaNewDictDialog() override
const OUString * Next()
long Left() const
FILE * init(int, char **)
ScopedVclPtr< VirtualDevice > m_xVirDev
std::unique_ptr< SuggestionList > m_xSuggestions
OUString m_sPrimaryText
std::unique_ptr< weld::Entry > m_xDictNameED
std::unique_ptr< weld::CheckButton > m_xShowrecentlyfirstCB
#define UPH_IS_IGNORE_POST_POSITIONAL_WORD
VirtualDevice * get() const
ScXMLEditAttributeMap::Entry const aEntries[]
void SetLeft(long v)
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
std::unique_ptr< weld::CheckButton > m_xIgnorepostCB
std::unique_ptr< weld::TreeView > m_xDictsLB
void Push(PushFlags nFlags=PushFlags::ALL)
void setWidth(long nWidth)
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)
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
#define MAXNUM_SUGGESTIONS
std::vector< OUString > m_vElements
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
HangulHanjaEditDictDialog * m_pParent
#define KEY_UP
void setHeight(long nHeight)
HangulHanjaOptionsDialog(weld::Window *pParent)