update dev300-m58
[ooovba.git] / svx / source / cui / cuifmsearch.cxx
blob4549d9c7b3ff7253a766d385d1c645880c2d120b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cuifmsearch.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #ifdef SVX_DLLIMPLEMENTATION
35 #undef SVX_DLLIMPLEMENTATION
36 #endif
38 #ifndef _SVX_FMRESIDS_HRC
39 #include "fmresids.hrc"
40 #endif // _SVX_FMRESIDS_HRC
41 #include <tools/debug.hxx>
42 #include <vcl/msgbox.hxx>
45 #include <vcl/svapp.hxx>
46 #include <tools/shl.hxx>
47 #include <svx/dialmgr.hxx>
49 #include <sfx2/tabdlg.hxx> //add by CHINA001 for SfxItemSet
50 #include <osl/mutex.hxx>
51 #include <sfx2/app.hxx>
52 #ifndef _SVX_DIALOGS_HRC
53 #include <svx/dialogs.hrc>
54 #endif
55 #include <svtools/filerec.hxx>
56 #include "fmsrcimp.hxx"
57 #include "fmsrccfg.hxx"
59 #ifndef _FMSEARCH_HRC
60 #include "fmsearch.hrc"
61 #endif // _FMSEARCH_HRC
62 #include "cuifmsearch.hxx"
63 #include "srchdlg.hxx"
64 #include <svtools/cjkoptions.hxx>
65 #include <com/sun/star/i18n/TransliterationModules.hpp>
66 #include <comphelper/processfactory.hxx>
68 #include <svx/svxdlg.hxx> //CHINA001
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::i18n;
72 using namespace ::svxform;
73 using namespace ::com::sun::star::sdbc;
74 using namespace ::com::sun::star::util;
76 #define MAX_HISTORY_ENTRIES 50
78 //------------------------------------------------------------------------
79 void FmSearchDialog::initCommon( const Reference< XResultSet >& _rxCursor )
81 // init the engine
82 DBG_ASSERT( m_pSearchEngine, "FmSearchDialog::initCommon: have no engine!" );
83 m_pSearchEngine->SetProgressHandler(LINK(this, FmSearchDialog, OnSearchProgress));
85 // some layout changes according to available CJK options
86 SvtCJKOptions aCJKOptions;
87 if (!aCJKOptions.IsJapaneseFindEnabled())
89 sal_Int32 nUpper = m_cbApprox.GetPosPixel().Y();
90 sal_Int32 nDifference = m_aSoundsLikeCJKSettings.GetPosPixel().Y() - nUpper;
92 // hide the options for the japanese search
93 Control* pFieldsToMove[] = { &m_flState, &m_ftRecordLabel, &m_ftRecord, &m_ftHint };
94 implMoveControls(pFieldsToMove, sizeof(pFieldsToMove)/sizeof(pFieldsToMove[0]), nDifference, &m_flOptions);
96 m_aSoundsLikeCJK.Hide();
97 m_aSoundsLikeCJKSettings.Hide();
100 if (!aCJKOptions.IsCJKFontEnabled())
102 m_aHalfFullFormsCJK.Hide();
104 // never ignore the width (ignoring is expensive) if the option is not available at all
105 // 04.12.2001 - 91973 - fs@openoffice.org
106 m_pSearchEngine->SetIgnoreWidthCJK( sal_False );
109 // some initial record texts
110 m_ftRecord.SetText( String::CreateFromInt32( _rxCursor->getRow() ) );
111 m_pbClose.SetHelpText(String());
114 //------------------------------------------------------------------------
115 FmSearchDialog::FmSearchDialog(Window* pParent, const UniString& sInitialText, const ::std::vector< String >& _rContexts, sal_Int16 nInitialContext,
116 const Link& lnkContextSupplier)
117 :ModalDialog(pParent, SVX_RES(RID_SVXDLG_SEARCHFORM))
118 ,m_flSearchFor (this, SVX_RES(FL_SEARCHFOR))
119 ,m_rbSearchForText (this, SVX_RES(RB_SEARCHFORTEXT))
120 ,m_rbSearchForNull (this, SVX_RES(RB_SEARCHFORNULL))
121 ,m_rbSearchForNotNull (this, SVX_RES(RB_SEARCHFORNOTNULL))
122 ,m_cmbSearchText (this, SVX_RES(CMB_SEARCHTEXT))
123 ,m_flWhere (this, SVX_RES(FL_WHERE))
124 ,m_ftForm (this, SVX_RES(FT_FORM))
125 ,m_lbForm (this, SVX_RES(LB_FORM))
126 ,m_rbAllFields (this, SVX_RES(RB_ALLFIELDS))
127 ,m_rbSingleField (this, SVX_RES(RB_SINGLEFIELD))
128 ,m_lbField (this, SVX_RES(LB_FIELD))
129 ,m_flOptions (this, SVX_RES(FL_OPTIONS))
130 ,m_ftPosition (this, SVX_RES(FT_POSITION))
131 ,m_lbPosition (this, SVX_RES(LB_POSITION))
132 ,m_cbUseFormat (this, SVX_RES(CB_USEFORMATTER))
133 ,m_cbCase (this, SVX_RES(CB_CASE))
134 ,m_cbBackwards (this, SVX_RES(CB_BACKWARD))
135 ,m_cbStartOver (this, SVX_RES(CB_STARTOVER))
136 ,m_cbWildCard (this, SVX_RES(CB_WILDCARD))
137 ,m_cbRegular (this, SVX_RES(CB_REGULAR))
138 ,m_cbApprox (this, SVX_RES(CB_APPROX))
139 ,m_pbApproxSettings (this, SVX_RES(PB_APPROXSETTINGS))
140 ,m_aHalfFullFormsCJK (this, SVX_RES(CB_HALFFULLFORMS))
141 ,m_aSoundsLikeCJK (this, SVX_RES(CB_SOUNDSLIKECJK))
142 ,m_aSoundsLikeCJKSettings (this, SVX_RES(PB_SOUNDSLIKESETTINGS))
143 ,m_flState (this, SVX_RES(FL_STATE))
144 ,m_ftRecordLabel (this, SVX_RES(FT_RECORDLABEL))
145 ,m_ftRecord (this, SVX_RES(FT_RECORD))
146 ,m_ftHint (this, SVX_RES(FT_HINT))
147 ,m_pbSearchAgain (this, SVX_RES(PB_SEARCH))
148 ,m_pbClose (this, SVX_RES(1))
149 ,m_pbHelp (this, SVX_RES(1))
150 ,m_sSearch ( m_pbSearchAgain.GetText() )
151 ,m_sCancel ( Button::GetStandardText( BUTTON_CANCEL ) )
152 ,m_pPreSearchFocus( NULL )
153 ,m_lnkContextSupplier(lnkContextSupplier)
154 ,m_pConfig( NULL )
156 DBG_ASSERT(m_lnkContextSupplier.IsSet(), "FmSearchDialog::FmSearchDialog : have no ContextSupplier !");
158 // erst mal die Informationen fuer den initialen Kontext
159 FmSearchContext fmscInitial;
160 fmscInitial.nContext = nInitialContext;
161 m_lnkContextSupplier.Call(&fmscInitial);
162 DBG_ASSERT(fmscInitial.xCursor.is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !");
163 DBG_ASSERT(fmscInitial.strUsedFields.GetTokenCount(';') == (xub_StrLen)fmscInitial.arrFields.size(),
164 "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplied !");
165 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
166 for (sal_Int32 i=0; i<(sal_Int32)fmscInitial.arrFields.size(); ++i)
167 DBG_ASSERT(fmscInitial.arrFields.at(i).is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !");
168 #endif // (OSL_DEBUG_LEVEL > 1) || DBG_UTIL
170 for ( ::std::vector< String >::const_iterator context = _rContexts.begin();
171 context != _rContexts.end();
172 ++context
175 m_arrContextFields.push_back(String());
176 m_lbForm.InsertEntry(*context);
178 m_lbForm.SelectEntryPos(nInitialContext);
180 m_lbForm.SetSelectHdl(LINK(this, FmSearchDialog, OnContextSelection));
182 if (m_arrContextFields.size() == 1)
183 { // remove the context selection listbox and rearrange the controls accordingly
184 sal_Int32 nUpper = m_lbForm.GetPosPixel().Y();
185 sal_Int32 nDifference = m_rbAllFields.GetPosPixel().Y() - nUpper;
187 // move all controls below the affected ones up
188 Control* pFieldsToMove[] = { &m_rbAllFields, &m_rbSingleField, &m_lbField, &m_flOptions, &m_ftPosition, &m_lbPosition,
189 &m_cbUseFormat, &m_cbCase, &m_cbBackwards, &m_cbStartOver, &m_cbWildCard, &m_cbRegular, &m_cbApprox,
190 &m_pbApproxSettings, &m_aHalfFullFormsCJK, &m_aSoundsLikeCJK, &m_aSoundsLikeCJKSettings,
191 &m_flState, &m_ftRecordLabel, &m_ftRecord, &m_ftHint };
193 implMoveControls(pFieldsToMove, sizeof(pFieldsToMove)/sizeof(pFieldsToMove[0]), nDifference, &m_flWhere);
195 Point pt = m_rbAllFields.GetPosPixel();
196 pt.X() = m_ftForm.GetPosPixel().X();
197 m_rbAllFields.SetPosPixel( pt );
198 pt = m_rbSingleField.GetPosPixel();
199 pt.X() = m_ftForm.GetPosPixel().X();
200 m_rbSingleField.SetPosPixel( pt );
202 // hide dispensable controls
203 m_ftForm.Hide();
204 m_lbForm.Hide();
207 m_pSearchEngine = new FmSearchEngine(
208 ::comphelper::getProcessServiceFactory(), fmscInitial.xCursor, fmscInitial.strUsedFields, fmscInitial.arrFields, SM_ALLOWSCHEDULE );
209 initCommon( fmscInitial.xCursor );
211 if (fmscInitial.sFieldDisplayNames.Len() != 0)
212 { // use the display names if supplied
213 DBG_ASSERT(fmscInitial.sFieldDisplayNames.GetTokenCount() == fmscInitial.strUsedFields.GetTokenCount(),
214 "FmSearchDialog::FmSearchDialog : invalid initial context description !");
215 Init(fmscInitial.sFieldDisplayNames, sInitialText);
217 else
218 Init(fmscInitial.strUsedFields, sInitialText);
221 //------------------------------------------------------------------------
222 void FmSearchDialog::implMoveControls(
223 Control** _ppControls,
224 sal_Int32 _nControls,
225 sal_Int32 _nUp,
226 Control* /*_pToResize*/)
228 for (sal_Int32 i=0; i<_nControls; ++i)
230 Point pt = _ppControls[i]->GetPosPixel();
231 pt.Y() -= _nUp;
232 _ppControls[i]->SetPosPixel(pt);
235 // resize myself
236 Size sz = GetSizePixel();
237 sz.Height() -= _nUp;
238 SetSizePixel(sz);
241 //------------------------------------------------------------------------
242 FmSearchDialog::~FmSearchDialog()
244 if (m_aDelayedPaint.IsActive())
245 m_aDelayedPaint.Stop();
247 SaveParams();
249 if (m_pConfig)
251 delete m_pConfig;
252 m_pConfig = NULL;
255 delete m_pSearchEngine;
258 //------------------------------------------------------------------------
259 void FmSearchDialog::Init(const UniString& strVisibleFields, const UniString& sInitialText)
261 // die Initialisierung all der Controls
262 m_rbSearchForText.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
263 m_rbSearchForNull.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
264 m_rbSearchForNotNull.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
266 m_rbAllFields.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
267 m_rbSingleField.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
269 m_pbSearchAgain.SetClickHdl(LINK(this, FmSearchDialog, OnClickedSearchAgain));
270 m_pbApproxSettings.SetClickHdl(LINK(this, FmSearchDialog, OnClickedSpecialSettings));
271 m_aSoundsLikeCJKSettings.SetClickHdl(LINK(this, FmSearchDialog, OnClickedSpecialSettings));
273 m_lbPosition.SetSelectHdl(LINK(this, FmSearchDialog, OnPositionSelected));
274 m_lbField.SetSelectHdl(LINK(this, FmSearchDialog, OnFieldSelected));
276 m_cmbSearchText.SetModifyHdl(LINK(this, FmSearchDialog, OnSearchTextModified));
277 m_cmbSearchText.EnableAutocomplete(sal_False);
279 m_cbUseFormat.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
280 m_cbBackwards.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
281 m_cbStartOver.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
282 m_cbCase.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
283 m_cbWildCard.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
284 m_cbRegular.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
285 m_cbApprox.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
286 m_aHalfFullFormsCJK.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
287 m_aSoundsLikeCJK.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
289 // die Listboxen fuellen
290 // die Methoden des Feldvergleiches
291 USHORT nResIds[] = {
292 RID_STR_SEARCH_ANYWHERE,
293 RID_STR_SEARCH_BEGINNING,
294 RID_STR_SEARCH_END,
295 RID_STR_SEARCH_WHOLE
297 for ( size_t i=0; i<sizeof(nResIds)/sizeof(nResIds[0]); ++i )
298 m_lbPosition.InsertEntry( String( SVX_RES( nResIds[i] ) ) );
299 m_lbPosition.SelectEntryPos(MATCHING_ANYWHERE);
301 // die Feld-Listbox
302 for (USHORT i=0; i<strVisibleFields.GetTokenCount(';'); ++i)
303 m_lbField.InsertEntry(strVisibleFields.GetToken(i, ';'));
306 m_pConfig = new FmSearchConfigItem;
307 LoadParams();
309 m_cmbSearchText.SetText(sInitialText);
310 // wenn die Edit-Zeile den Text veraendert hat (weil er zum Beispiel Steuerzeichen enthielt, wie das bei Memofeldern der Fall
311 // sein kann), nehme ich einen leeren UniString
312 UniString sRealSetText = m_cmbSearchText.GetText();
313 if (!sRealSetText.Equals(sInitialText))
314 m_cmbSearchText.SetText(UniString());
315 LINK(this, FmSearchDialog, OnSearchTextModified).Call(&m_cmbSearchText);
317 // initial die ganzen UI-Elemente fuer die Suche an
318 m_aDelayedPaint.SetTimeoutHdl(LINK(this, FmSearchDialog, OnDelayedPaint));
319 m_aDelayedPaint.SetTimeout(500);
320 EnableSearchUI(sal_True);
322 if ( m_rbSearchForText.IsChecked() )
323 m_cmbSearchText.GrabFocus();
325 FreeResource();
328 //------------------------------------------------------------------------
329 sal_Bool FmSearchDialog::Close()
331 // Wenn der Close-Button disabled ist und man im Dialog ESC drueckt, dann wird irgendwo vom Frame trotzdem Close aufgerufen,
332 // was ich allerdings nicht will, wenn ich gerade mitten in einer (eventuell in einem extra Thread laufenden) Suche bin
333 if (!m_pbClose.IsEnabled())
334 return sal_False;
335 return ModalDialog::Close();
338 //------------------------------------------------------------------------
339 IMPL_LINK(FmSearchDialog, OnClickedFieldRadios, Button*, pButton)
341 if ((pButton == &m_rbSearchForText) || (pButton == &m_rbSearchForNull) || (pButton == &m_rbSearchForNotNull))
343 EnableSearchForDependees(sal_True);
345 else
346 // die Feldlistbox entsprechend en- oder disablen
347 if (pButton == &m_rbSingleField)
349 m_lbField.Enable();
350 m_pSearchEngine->RebuildUsedFields(m_lbField.GetSelectEntryPos());
352 else
354 m_lbField.Disable();
355 m_pSearchEngine->RebuildUsedFields(-1);
358 return 0;
361 //------------------------------------------------------------------------
362 IMPL_LINK(FmSearchDialog, OnClickedSearchAgain, Button*, EMPTYARG)
364 if (m_pbClose.IsEnabled())
365 { // der Button hat die Funktion 'Suchen'
366 UniString strThisRoundText = m_cmbSearchText.GetText();
367 // zur History dazu
368 m_cmbSearchText.RemoveEntry(strThisRoundText);
369 m_cmbSearchText.InsertEntry(strThisRoundText, 0);
370 // das Remove/Insert stellt a) sicher, dass der UniString nicht zweimal auftaucht, b), dass die zuletzt gesuchten Strings am
371 // Anfang stehen
372 // und die Listenlaenge beschraenken
373 while (m_cmbSearchText.GetEntryCount() > MAX_HISTORY_ENTRIES)
374 m_cmbSearchText.RemoveEntry(m_cmbSearchText.GetEntryCount()-1);
376 // den 'Ueberlauf'-Hint rausnehmen
377 m_ftHint.SetText(UniString());
378 m_ftHint.Invalidate();
380 if (m_cbStartOver.IsChecked())
382 m_cbStartOver.Check(sal_False);
383 EnableSearchUI(sal_False);
384 if (m_rbSearchForText.IsChecked())
385 m_pSearchEngine->StartOver(strThisRoundText);
386 else
387 m_pSearchEngine->StartOverSpecial(m_rbSearchForNull.IsChecked());
389 else
391 EnableSearchUI(sal_False);
392 if (m_rbSearchForText.IsChecked())
393 m_pSearchEngine->SearchNext(strThisRoundText);
394 else
395 m_pSearchEngine->SearchNextSpecial(m_rbSearchForNull.IsChecked());
398 else
399 { // der Button hat die Fukntion 'Abbrechen'
400 DBG_ASSERT(m_pSearchEngine->GetSearchMode() != SM_BRUTE, "FmSearchDialog, OnClickedSearchAgain : falscher Modus !");
401 // der CancelButton wird normalerweise nur disabled, wenn ich in einem Thread oder mit Reschedule arbeite
402 m_pSearchEngine->CancelSearch();
403 // mein ProgressHandler wird gerufen, wenn es wirklich zu Ende ist, das hier war nur eine Anforderung
405 return 0;
408 //------------------------------------------------------------------------
409 IMPL_LINK(FmSearchDialog, OnClickedSpecialSettings, Button*, pButton )
411 if (&m_pbApproxSettings == pButton)
413 AbstractSvxSearchSimilarityDialog* pDlg = NULL;
415 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
416 if ( pFact )
417 pDlg = pFact->CreateSvxSearchSimilarityDialog( this, m_pSearchEngine->GetLevRelaxed(), m_pSearchEngine->GetLevOther(),
418 m_pSearchEngine->GetLevShorter(), m_pSearchEngine->GetLevLonger() );
419 DBG_ASSERT( pDlg, "FmSearchDialog, OnClickedSpecialSettings: could not load the dialog!" );
421 if ( pDlg && pDlg->Execute() == RET_OK )
423 m_pSearchEngine->SetLevRelaxed( pDlg->IsRelaxed() );
424 m_pSearchEngine->SetLevOther( pDlg->GetOther() );
425 m_pSearchEngine->SetLevShorter(pDlg->GetShorter() );
426 m_pSearchEngine->SetLevLonger( pDlg->GetLonger() );
428 delete pDlg;
430 else if (&m_aSoundsLikeCJKSettings == pButton)
432 SfxItemSet aSet( SFX_APP()->GetPool() );
433 //CHINA001 SvxJSearchOptionsDialog aDlg( this, aSet, RID_SVXPAGE_JSEARCH_OPTIONS, m_pSearchEngine->GetTransliterationFlags() );
434 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
435 if(pFact)
437 AbstractSvxJSearchOptionsDialog* aDlg = pFact->CreateSvxJSearchOptionsDialog( this, aSet, RID_SVXPAGE_JSEARCH_OPTIONS, m_pSearchEngine->GetTransliterationFlags(), RID_SVXPAGE_JSEARCH_OPTIONS );
438 DBG_ASSERT(aDlg, "Dialogdiet fail!");//CHINA001
439 aDlg->Execute(); //CHINA001 aDlg.Execute();
442 INT32 nFlags = aDlg->GetTransliterationFlags(); //CHINA001 INT32 nFlags = aDlg.GetTransliterationFlags();
443 m_pSearchEngine->SetTransliterationFlags(nFlags);
445 m_cbCase.Check(m_pSearchEngine->GetCaseSensitive());
446 OnCheckBoxToggled( &m_cbCase );
447 m_aHalfFullFormsCJK.Check( !m_pSearchEngine->GetIgnoreWidthCJK() );
448 OnCheckBoxToggled( &m_aHalfFullFormsCJK );
449 delete aDlg; //add for CHINA001
453 return 0;
456 //------------------------------------------------------------------------
457 IMPL_LINK(FmSearchDialog, OnSearchTextModified, ComboBox*, EMPTYARG)
459 if ((m_cmbSearchText.GetText().Len() != 0) || !m_rbSearchForText.IsChecked())
460 m_pbSearchAgain.Enable();
461 else
462 m_pbSearchAgain.Disable();
464 m_pSearchEngine->InvalidatePreviousLoc();
465 return 0;
468 //------------------------------------------------------------------------
469 IMPL_LINK(FmSearchDialog, OnPositionSelected, ListBox*, pBox)
471 (void) pBox; // avoid warning
472 DBG_ASSERT(pBox->GetSelectEntryCount() == 1, "FmSearchDialog::OnMethodSelected : unerwartet : nicht genau ein Eintrag selektiert !");
474 m_pSearchEngine->SetPosition(m_lbPosition.GetSelectEntryPos());
475 return 0;
478 //------------------------------------------------------------------------
479 IMPL_LINK(FmSearchDialog, OnFieldSelected, ListBox*, pBox)
481 (void) pBox; // avoid warning
482 DBG_ASSERT(pBox->GetSelectEntryCount() == 1, "FmSearchDialog::OnFieldSelected : unerwartet : nicht genau ein Eintrag selektiert !");
484 m_pSearchEngine->RebuildUsedFields(m_rbAllFields.IsChecked() ? -1 : (sal_Int16)m_lbField.GetSelectEntryPos());
485 // ruft auch m_pSearchEngine->InvalidatePreviousLoc auf
487 sal_Int32 nCurrentContext = m_lbForm.GetSelectEntryPos();
488 if (nCurrentContext != LISTBOX_ENTRY_NOTFOUND)
489 m_arrContextFields[nCurrentContext] = UniString(m_lbField.GetSelectEntry());
490 return 0;
493 //------------------------------------------------------------------------
494 IMPL_LINK(FmSearchDialog, OnCheckBoxToggled, CheckBox*, pBox)
496 sal_Bool bChecked = pBox->IsChecked();
498 // Formatter oder case -> an die Engine weiterreichen
499 if (pBox == &m_cbUseFormat)
500 m_pSearchEngine->SetFormatterUsing(bChecked);
501 else if (pBox == &m_cbCase)
502 m_pSearchEngine->SetCaseSensitive(bChecked);
503 // Richtung -> weiterreichen und Checkbox-Text fuer StartOver neu setzen
504 else if (pBox == &m_cbBackwards)
506 m_cbStartOver.SetText( String( SVX_RES( bChecked ? RID_STR_FROM_BOTTOM : RID_STR_FROM_TOP ) ) );
507 m_pSearchEngine->SetDirection(!bChecked);
509 // Aehnlichkeitssuche oder regulaerer Ausdruck
510 else if ((pBox == &m_cbApprox) || (pBox == &m_cbRegular) || (pBox == &m_cbWildCard))
512 // die beiden jeweils anderen Boxes disablen oder enablen
513 CheckBox* pBoxes[] = { &m_cbWildCard, &m_cbRegular, &m_cbApprox };
514 for (sal_uInt32 i=0; i<sizeof(pBoxes)/sizeof(CheckBox*); ++i)
516 if (pBoxes[i] != pBox)
518 if (bChecked)
519 pBoxes[i]->Disable();
520 else
521 pBoxes[i]->Enable();
525 // an die Engine weiterreichen
526 m_pSearchEngine->SetWildcard(m_cbWildCard.IsEnabled() ? m_cbWildCard.IsChecked() : sal_False);
527 m_pSearchEngine->SetRegular(m_cbRegular.IsEnabled() ? m_cbRegular.IsChecked() : sal_False);
528 m_pSearchEngine->SetLevenshtein(m_cbApprox.IsEnabled() ? m_cbApprox.IsChecked() : sal_False);
529 // (Boxes, die disabled sind, muessen als sal_False an die Engine gehen)
531 // die Position-Listbox anpassen (ist bei Wildcard-Suche nicht erlaubt)
532 if (pBox == &m_cbWildCard)
534 if (bChecked)
536 m_ftPosition.Disable();
537 m_lbPosition.Disable();
539 else
541 m_ftPosition.Enable();
542 m_lbPosition.Enable();
546 // und den Button fuer die Aehnlichkeitssuche
547 if (pBox == &m_cbApprox)
549 if (bChecked)
550 m_pbApproxSettings.Enable();
551 else
552 m_pbApproxSettings.Disable();
555 else if (pBox == &m_aHalfFullFormsCJK)
557 // forward to the search engine
558 m_pSearchEngine->SetIgnoreWidthCJK( !bChecked );
560 else if (pBox == &m_aSoundsLikeCJK)
562 m_aSoundsLikeCJKSettings.Enable(bChecked);
564 // two other buttons which depend on this one
565 sal_Bool bEnable = ( m_rbSearchForText.IsChecked()
566 && !m_aSoundsLikeCJK.IsChecked()
568 || !SvtCJKOptions().IsJapaneseFindEnabled();
569 m_cbCase.Enable(bEnable);
570 m_aHalfFullFormsCJK.Enable(bEnable);
572 // forward to the search engine
573 m_pSearchEngine->SetTransliteration( bChecked );
576 return 0;
579 //------------------------------------------------------------------------
580 void FmSearchDialog::InitContext(sal_Int16 nContext)
582 FmSearchContext fmscContext;
583 fmscContext.nContext = nContext;
585 #ifdef DBG_UTIL
586 sal_uInt32 nResult =
587 #endif
588 m_lnkContextSupplier.Call(&fmscContext);
589 DBG_ASSERT(nResult > 0, "FmSearchDialog::InitContext : ContextSupplier didn't give me any controls !");
591 // packen wir zuerst die Feld-Namen in die entsprechende Listbox
592 m_lbField.Clear();
594 if (fmscContext.sFieldDisplayNames.Len() != 0)
596 // use the display names if supplied
597 DBG_ASSERT(fmscContext.sFieldDisplayNames.GetTokenCount() == fmscContext.strUsedFields.GetTokenCount(),
598 "FmSearchDialog::InitContext : invalid context description supplied !");
599 for (xub_StrLen i=0; i<fmscContext.sFieldDisplayNames.GetTokenCount(); ++i)
600 m_lbField.InsertEntry(fmscContext.sFieldDisplayNames.GetToken(i));
602 else
603 // else use the field names
604 for (xub_StrLen i=0; i<fmscContext.strUsedFields.GetTokenCount(); ++i)
605 m_lbField.InsertEntry(fmscContext.strUsedFields.GetToken(i));
607 if (nContext < (sal_Int32)m_arrContextFields.size() && m_arrContextFields[nContext].Len())
609 m_lbField.SelectEntry(m_arrContextFields[nContext]);
611 else
613 m_lbField.SelectEntryPos(0);
614 if (m_rbSingleField.IsChecked() && (m_lbField.GetEntryCount() > 1))
615 m_lbField.GrabFocus();
618 // dann geben wir der Engine Bescheid
619 m_pSearchEngine->SwitchToContext(fmscContext.xCursor, fmscContext.strUsedFields, fmscContext.arrFields,
620 m_rbAllFields.IsChecked() ? -1 : 0);
622 // und die Position des neuen Cursors anzeigen
623 m_ftRecord.SetText(String::CreateFromInt32(fmscContext.xCursor->getRow()));
626 //------------------------------------------------------------------------
627 IMPL_LINK( FmSearchDialog, OnContextSelection, ListBox*, pBox)
629 InitContext(pBox->GetSelectEntryPos());
630 return 0L;
633 //------------------------------------------------------------------------
634 void FmSearchDialog::EnableSearchUI(sal_Bool bEnable)
636 // wenn die Controls disabled werden sollen, schalte ich mal eben kurz ihr Paint aus und verzoegert wieder an
637 if (!bEnable)
638 EnableControlPaint(sal_False);
639 else
640 { // beim Enablen teste ich, ob der Timer fuer das delayed paint aktiv ist und stoppe ihn wenn noetig
641 if (m_aDelayedPaint.IsActive())
642 m_aDelayedPaint.Stop();
644 // (das ganze geht unten noch weiter)
645 // diese kleine Verrenkung fuehrt hoffentlich dazu, dass es nicht flackert, wenn man die SearchUI schnell hintereinander
646 // aus- und wieder einschaltet (wie das bei einem kurzen Suchvorgang zwangslaeufig der Fall ist)
648 if ( !bEnable )
650 // if one of my children has the focus, remember it
651 // 104332 - 2002-10-17 - fs@openoffice.org
652 Window* pFocusWindow = Application::GetFocusWindow( );
653 if ( pFocusWindow && IsChild( pFocusWindow ) )
654 m_pPreSearchFocus = pFocusWindow;
655 else
656 m_pPreSearchFocus = NULL;
659 // der Suchen-Button hat einen Doppelfunktion, seinen Text entsprechend anpassen
660 String sButtonText( bEnable ? m_sSearch : m_sCancel );
661 m_pbSearchAgain.SetText( sButtonText );
663 // jetzt Controls en- oder disablen
664 if (m_pSearchEngine->GetSearchMode() != SM_BRUTE)
666 m_flSearchFor.Enable (bEnable);
667 m_rbSearchForText.Enable (bEnable);
668 m_rbSearchForNull.Enable (bEnable);
669 m_rbSearchForNotNull.Enable (bEnable);
670 m_flWhere.Enable (bEnable);
671 m_ftForm.Enable (bEnable);
672 m_lbForm.Enable (bEnable);
673 m_rbAllFields.Enable (bEnable);
674 m_rbSingleField.Enable (bEnable);
675 m_lbField.Enable (bEnable && m_rbSingleField.IsChecked());
676 m_flOptions.Enable (bEnable);
677 m_cbBackwards.Enable (bEnable);
678 m_cbStartOver.Enable (bEnable);
679 m_pbClose.Enable (bEnable);
680 EnableSearchForDependees (bEnable);
682 if ( !bEnable )
683 { // this means we're preparing for starting a search
684 // In this case, EnableSearchForDependees disabled the search button
685 // But as we're about to use it for cancelling the search, we really need to enable it, again
686 // 07.12.2001 - 95246 - fs@openoffice.org
687 m_pbSearchAgain.Enable( sal_True );
691 // und den Rest fuer das delayed paint
692 if (!bEnable)
693 m_aDelayedPaint.Start();
694 else
695 EnableControlPaint(sal_True);
697 if ( bEnable )
698 { // restore focus
699 // 104332 - 2002-10-17 - fs@openoffice.org
700 if ( m_pPreSearchFocus )
702 m_pPreSearchFocus->GrabFocus();
703 if ( WINDOW_EDIT == m_pPreSearchFocus->GetType() )
705 Edit* pEdit = static_cast< Edit* >( m_pPreSearchFocus );
706 pEdit->SetSelection( Selection( 0, pEdit->GetText().Len() ) );
709 m_pPreSearchFocus = NULL;
714 //------------------------------------------------------------------------
715 void FmSearchDialog::EnableSearchForDependees(sal_Bool bEnable)
717 sal_Bool bSearchingForText = m_rbSearchForText.IsChecked();
718 m_pbSearchAgain.Enable(bEnable && (!bSearchingForText || (m_cmbSearchText.GetText().Len() != 0)));
720 bEnable = bEnable && bSearchingForText;
722 sal_Bool bEnableRedundants = !m_aSoundsLikeCJK.IsChecked() || !SvtCJKOptions().IsJapaneseFindEnabled();
724 m_cmbSearchText.Enable (bEnable);
725 m_ftPosition.Enable (bEnable && !m_cbWildCard.IsChecked());
726 m_cbWildCard.Enable (bEnable && !m_cbRegular.IsChecked() && !m_cbApprox.IsChecked());
727 m_cbRegular.Enable (bEnable && !m_cbWildCard.IsChecked() && !m_cbApprox.IsChecked());
728 m_cbApprox.Enable (bEnable && !m_cbWildCard.IsChecked() && !m_cbRegular.IsChecked());
729 m_pbApproxSettings.Enable (bEnable && m_cbApprox.IsChecked());
730 m_aHalfFullFormsCJK.Enable (bEnable && bEnableRedundants);
731 m_aSoundsLikeCJK.Enable (bEnable);
732 m_aSoundsLikeCJKSettings.Enable (bEnable && m_aSoundsLikeCJK.IsChecked());
733 m_lbPosition.Enable (bEnable && !m_cbWildCard.IsChecked());
734 m_cbUseFormat.Enable (bEnable);
735 m_cbCase.Enable (bEnable && bEnableRedundants);
738 //------------------------------------------------------------------------
739 void FmSearchDialog::EnableControlPaint(sal_Bool bEnable)
741 Control* pAffectedControls[] = { &m_flSearchFor, &m_rbSearchForText, &m_cmbSearchText, &m_rbSearchForNull, &m_rbSearchForNotNull,
742 &m_rbSearchForText, &m_flWhere, &m_rbAllFields, &m_rbSingleField, &m_lbField, &m_flOptions, &m_ftPosition, &m_lbPosition,
743 &m_cbUseFormat, &m_cbCase, &m_cbBackwards, &m_cbStartOver, &m_cbWildCard, &m_cbRegular, &m_cbApprox, &m_pbApproxSettings,
744 &m_pbSearchAgain, &m_pbClose };
746 if (!bEnable)
747 for (sal_uInt32 i=0; i<sizeof(pAffectedControls)/sizeof(pAffectedControls[0]); ++i)
749 pAffectedControls[i]->SetUpdateMode(bEnable);
750 pAffectedControls[i]->EnablePaint(bEnable);
752 else
753 for (sal_uInt32 i=0; i<sizeof(pAffectedControls)/sizeof(pAffectedControls[0]); ++i)
755 pAffectedControls[i]->EnablePaint(bEnable);
756 pAffectedControls[i]->SetUpdateMode(bEnable);
760 //------------------------------------------------------------------------
761 IMPL_LINK(FmSearchDialog, OnDelayedPaint, void*, EMPTYARG)
763 EnableControlPaint(sal_True);
764 return 0L;
767 //------------------------------------------------------------------------
768 void FmSearchDialog::OnFound(const ::com::sun::star::uno::Any& aCursorPos, sal_Int16 nFieldPos)
770 FmFoundRecordInformation friInfo;
771 friInfo.nContext = m_lbForm.GetSelectEntryPos();
772 // wenn ich keine Suche in Kontexten mache, steht hier was ungueltiges drin, aber dann ist es auch egal
773 friInfo.aPosition = aCursorPos;
774 if (m_rbAllFields.IsChecked())
775 friInfo.nFieldPos = nFieldPos;
776 else
777 friInfo.nFieldPos = m_lbField.GetSelectEntryPos();
778 // das setzt natuerlich voraus, dass ich wirklich in dem Feld gesucht habe, dass in der Listbox ausgewaehlt ist,
779 // genau das wird auch in RebuildUsedFields sichergestellt
781 // dem Handler Bescheid sagen
782 m_lnkFoundHandler.Call(&friInfo);
784 // und wieder Focus auf mich
785 m_cmbSearchText.GrabFocus();
788 //------------------------------------------------------------------------
789 IMPL_LINK(FmSearchDialog, OnSearchProgress, FmSearchProgress*, pProgress)
791 ::vos::OGuard aGuard( Application::GetSolarMutex() );
792 // diese eine Methode Thread-sicher machen (das ist ein Overkill, die ganze restliche Applikation dafuer zu blockieren,
793 // aber im Augenblick haben wir kein anderes Sicherheitskonpzept)
795 switch (pProgress->aSearchState)
797 case FmSearchProgress::STATE_PROGRESS:
798 if (pProgress->bOverflow)
800 String sHint( SVX_RES( m_cbBackwards.IsChecked() ? RID_STR_OVERFLOW_BACKWARD : RID_STR_OVERFLOW_FORWARD ) );
801 m_ftHint.SetText( sHint );
802 m_ftHint.Invalidate();
805 m_ftRecord.SetText(String::CreateFromInt32(1 + pProgress->nCurrentRecord));
806 m_ftRecord.Invalidate();
807 break;
809 case FmSearchProgress::STATE_PROGRESS_COUNTING:
810 m_ftHint.SetText(SVX_RESSTR(RID_STR_SEARCH_COUNTING));
811 m_ftHint.Invalidate();
813 m_ftRecord.SetText(String::CreateFromInt32(pProgress->nCurrentRecord));
814 m_ftRecord.Invalidate();
815 break;
817 case FmSearchProgress::STATE_SUCCESSFULL:
818 OnFound(pProgress->aBookmark, (sal_Int16)pProgress->nFieldIndex);
819 EnableSearchUI(sal_True);
820 break;
822 case FmSearchProgress::STATE_ERROR:
823 case FmSearchProgress::STATE_NOTHINGFOUND:
825 sal_uInt16 nErrorId = (FmSearchProgress::STATE_ERROR == pProgress->aSearchState)
826 ? RID_SVXERR_SEARCH_GENERAL_ERROR
827 : RID_SVXERR_SEARCH_NORECORD;
828 ErrorBox(this, SVX_RES(nErrorId)).Execute();
830 // KEIN break !
831 case FmSearchProgress::STATE_CANCELED:
832 EnableSearchUI(sal_True);
833 if (m_lnkCanceledNotFoundHdl.IsSet())
835 FmFoundRecordInformation friInfo;
836 friInfo.nContext = m_lbForm.GetSelectEntryPos();
837 // wenn ich keine Suche in Kontexten mache, steht hier was ungueltiges drin, aber dann ist es auch egal
838 friInfo.aPosition = pProgress->aBookmark;
839 m_lnkCanceledNotFoundHdl.Call(&friInfo);
841 break;
844 m_ftRecord.SetText(String::CreateFromInt32(1 + pProgress->nCurrentRecord));
846 return 0L;
849 //------------------------------------------------------------------------
850 void FmSearchDialog::LoadParams()
852 FmSearchParams aParams(m_pConfig->getParams());
854 const ::rtl::OUString* pHistory = aParams.aHistory.getConstArray();
855 const ::rtl::OUString* pHistoryEnd = pHistory + aParams.aHistory.getLength();
856 for (; pHistory != pHistoryEnd; ++pHistory)
857 m_cmbSearchText.InsertEntry( *pHistory );
859 // die Einstellungen nehme ich an meinen UI-Elementen vor und rufe dann einfach den entsprechenden Change-Handler auf,
860 // dadurch werden die Daten an die SearchEngine weitergereicht und alle abhaengigen Enstellungen vorgenommen
862 // aktuelles Feld
863 sal_uInt16 nInitialField = m_lbField.GetEntryPos( String( aParams.sSingleSearchField ) );
864 if (nInitialField == COMBOBOX_ENTRY_NOTFOUND)
865 nInitialField = 0;
866 m_lbField.SelectEntryPos(nInitialField);
867 LINK(this, FmSearchDialog, OnFieldSelected).Call(&m_lbField);
868 // alle/einzelnes Feld (NACH dem Selektieren des Feldes, da OnClickedFieldRadios dort einen gueltigen Eintrag erwartet)
869 if (aParams.bAllFields)
871 m_rbSingleField.Check(sal_False);
872 m_rbAllFields.Check(sal_True);
873 LINK(this, FmSearchDialog, OnClickedFieldRadios).Call(&m_rbAllFields);
874 // OnClickedFieldRadios ruft auch um RebuildUsedFields
876 else
878 m_rbAllFields.Check(sal_False);
879 m_rbSingleField.Check(sal_True);
880 LINK(this, FmSearchDialog, OnClickedFieldRadios).Call(&m_rbSingleField);
883 // Position im Feld
884 m_lbPosition.SelectEntryPos(aParams.nPosition);
885 LINK(this, FmSearchDialog, OnPositionSelected).Call(&m_lbPosition);
887 // Feld-Formatierung/Case-Sensitivitaet/Richtung
888 m_cbUseFormat.Check(aParams.bUseFormatter);
889 m_cbCase.Check( aParams.isCaseSensitive() );
890 m_cbBackwards.Check(aParams.bBackwards);
891 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbUseFormat);
892 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbCase);
893 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbBackwards);
895 m_aHalfFullFormsCJK.Check( !aParams.isIgnoreWidthCJK( ) ); // BEWARE: this checkbox has a inverse semantics!
896 m_aSoundsLikeCJK.Check( aParams.bSoundsLikeCJK );
897 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_aHalfFullFormsCJK);
898 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_aSoundsLikeCJK);
900 // die drei Checkboxen fuer spezielle Sucharten
901 // erst mal alle ruecksetzen
902 m_cbWildCard.Check(sal_False);
903 m_cbRegular.Check(sal_False);
904 m_cbApprox.Check(sal_False);
905 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbWildCard);
906 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbRegular);
907 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbApprox);
909 // dann die richtige setzen
910 CheckBox* pToCheck = NULL;
911 if (aParams.bWildcard)
912 pToCheck = &m_cbWildCard;
913 if (aParams.bRegular)
914 pToCheck = &m_cbRegular;
915 if (aParams.bApproxSearch)
916 pToCheck = &m_cbApprox;
917 if (aParams.bSoundsLikeCJK)
918 pToCheck = &m_aSoundsLikeCJK;
919 if (pToCheck)
921 pToCheck->Check(sal_True);
922 LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(pToCheck);
925 // die Levenshtein-Parameter direkt an der SearchEngine setzen
926 m_pSearchEngine->SetLevRelaxed(aParams.bLevRelaxed);
927 m_pSearchEngine->SetLevOther(aParams.nLevOther);
928 m_pSearchEngine->SetLevShorter(aParams.nLevShorter);
929 m_pSearchEngine->SetLevLonger(aParams.nLevLonger);
931 m_pSearchEngine->SetTransliterationFlags( aParams.getTransliterationFlags( ) );
933 m_rbSearchForText.Check(sal_False);
934 m_rbSearchForNull.Check(sal_False);
935 m_rbSearchForNotNull.Check(sal_False);
936 switch (aParams.nSearchForType)
938 case 1: m_rbSearchForNull.Check(sal_True); break;
939 case 2: m_rbSearchForNotNull.Check(sal_True); break;
940 default: m_rbSearchForText.Check(sal_True); break;
942 LINK(this, FmSearchDialog, OnClickedFieldRadios).Call(&m_rbSearchForText);
945 //------------------------------------------------------------------------
946 void FmSearchDialog::SaveParams() const
948 if (!m_pConfig)
949 return;
951 FmSearchParams aCurrentSettings;
953 aCurrentSettings.aHistory.realloc( m_cmbSearchText.GetEntryCount() );
954 ::rtl::OUString* pHistory = aCurrentSettings.aHistory.getArray();
955 for (sal_uInt16 i=0; i<m_cmbSearchText.GetEntryCount(); ++i, ++pHistory)
956 *pHistory = m_cmbSearchText.GetEntry(i);
958 aCurrentSettings.sSingleSearchField = m_lbField.GetSelectEntry();
959 aCurrentSettings.bAllFields = m_rbAllFields.IsChecked();
960 aCurrentSettings.nPosition = m_pSearchEngine->GetPosition();
961 aCurrentSettings.bUseFormatter = m_pSearchEngine->GetFormatterUsing();
962 aCurrentSettings.setCaseSensitive ( m_pSearchEngine->GetCaseSensitive() );
963 aCurrentSettings.bBackwards = !m_pSearchEngine->GetDirection();
964 aCurrentSettings.bWildcard = m_pSearchEngine->GetWildcard();
965 aCurrentSettings.bRegular = m_pSearchEngine->GetRegular();
966 aCurrentSettings.bApproxSearch = m_pSearchEngine->GetLevenshtein();
967 aCurrentSettings.bLevRelaxed = m_pSearchEngine->GetLevRelaxed();
968 aCurrentSettings.nLevOther = m_pSearchEngine->GetLevOther();
969 aCurrentSettings.nLevShorter = m_pSearchEngine->GetLevShorter();
970 aCurrentSettings.nLevLonger = m_pSearchEngine->GetLevLonger();
972 aCurrentSettings.bSoundsLikeCJK = m_pSearchEngine->GetTransliteration();
973 aCurrentSettings.setTransliterationFlags ( m_pSearchEngine->GetTransliterationFlags() );
975 if (m_rbSearchForNull.IsChecked())
976 aCurrentSettings.nSearchForType = 1;
977 else if (m_rbSearchForNotNull.IsChecked())
978 aCurrentSettings.nSearchForType = 2;
979 else
980 aCurrentSettings.nSearchForType = 0;
982 m_pConfig->setParams( aCurrentSettings );