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