Line data Source code
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 <dialmgr.hxx>
21 : #include <sfx2/docfile.hxx>
22 : #include <unotools/viewoptions.hxx>
23 : #include <vcl/svapp.hxx>
24 : #include <vcl/settings.hxx>
25 : #include <vcl/wrkwin.hxx>
26 :
27 : // UNO-Stuff
28 : #include <comphelper/processfactory.hxx>
29 : #include <comphelper/sequence.hxx>
30 : #include <com/sun/star/awt/XBitmap.hpp>
31 : #include <com/sun/star/frame/Desktop.hpp>
32 : #include <com/sun/star/frame/XComponentLoader.hpp>
33 : #include <com/sun/star/beans/PropertyValue.hpp>
34 : #include <com/sun/star/document/XLinkTargetSupplier.hpp>
35 : #include <com/sun/star/beans/XPropertySet.hpp>
36 :
37 : #include <toolkit/helper/vclunohelper.hxx>
38 : #include "svtools/treelistentry.hxx"
39 :
40 : #include <cuires.hrc>
41 : #include "hlmarkwn.hrc"
42 : #include "hlmarkwn.hxx"
43 : #include "hltpbase.hxx"
44 :
45 : using namespace ::com::sun::star;
46 : using namespace ::rtl;
47 :
48 : /*************************************************************************
49 : |*
50 : |* Userdata-struct for tree-entries
51 : |*
52 : |************************************************************************/
53 :
54 0 : struct TargetData
55 : {
56 : OUString aUStrLinkname;
57 : bool bIsTarget;
58 :
59 0 : TargetData (const OUString& aUStrLName, bool bTarget)
60 0 : : bIsTarget(bTarget)
61 : {
62 0 : if (bIsTarget)
63 0 : aUStrLinkname = aUStrLName;
64 0 : }
65 : };
66 :
67 :
68 :
69 : //# #
70 : //# Tree-Window #
71 : //# #
72 :
73 :
74 0 : SvxHlmarkTreeLBox::SvxHlmarkTreeLBox( Window* pParent, const ResId& rResId )
75 : : SvTreeListBox ( pParent, rResId ),
76 0 : mpParentWnd ( (SvxHlinkDlgMarkWnd*) pParent )
77 : {
78 0 : SetNodeDefaultImages();
79 0 : }
80 :
81 0 : void SvxHlmarkTreeLBox::Paint( const Rectangle& rRect )
82 : {
83 0 : if( mpParentWnd->mnError == LERR_NOERROR )
84 : {
85 0 : SvTreeListBox::Paint(rRect);
86 : }
87 : else
88 : {
89 0 : Erase();
90 :
91 0 : Rectangle aDrawRect( Point( 0, 0 ), GetSizePixel() );
92 :
93 0 : OUString aStrMessage;
94 :
95 0 : switch( mpParentWnd->mnError )
96 : {
97 : case LERR_NOENTRIES :
98 0 : aStrMessage = CUI_RESSTR( RID_SVXSTR_HYPDLG_ERR_LERR_NOENTRIES );
99 0 : break;
100 : case LERR_DOCNOTOPEN :
101 0 : aStrMessage = CUI_RESSTR( RID_SVXSTR_HYPDLG_ERR_LERR_DOCNOTOPEN );
102 0 : break;
103 : }
104 :
105 0 : DrawText( aDrawRect, aStrMessage, TEXT_DRAW_LEFT | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
106 : }
107 :
108 0 : }
109 :
110 :
111 : //# #
112 : //# Window-Class #
113 : //# #
114 :
115 :
116 : /*************************************************************************
117 : |*
118 : |* Contructor / Destructor
119 : |*
120 : |************************************************************************/
121 :
122 0 : SvxHlinkDlgMarkWnd::SvxHlinkDlgMarkWnd( SvxHyperlinkTabPageBase *pParent )
123 0 : : ModalDialog( (Window*)pParent, CUI_RES ( RID_SVXFLOAT_HYPERLINK_MARKWND ) ),
124 0 : maBtApply( this, CUI_RES (BT_APPLY) ),
125 0 : maBtClose( this, CUI_RES (BT_CLOSE) ),
126 0 : maLbTree ( this, CUI_RES (TLB_MARK) ),
127 : mbUserMoved ( sal_False ),
128 : mpParent ( pParent ),
129 0 : mnError ( LERR_NOERROR )
130 : {
131 0 : FreeResource();
132 :
133 0 : maBtApply.SetClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl ) );
134 0 : maBtClose.SetClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl ) );
135 0 : maLbTree.SetDoubleClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl ) );
136 :
137 : // add lines to the Tree-ListBox
138 0 : maLbTree.SetStyle( maLbTree.GetStyle() | WB_TABSTOP | WB_BORDER | WB_HASLINES |
139 : WB_HASBUTTONS | //WB_HASLINESATROOT |
140 0 : WB_HSCROLL | WB_HASBUTTONSATROOT );
141 :
142 0 : maLbTree.SetAccessibleName(CUI_RES(STR_MARK_TREE));
143 0 : }
144 :
145 0 : SvxHlinkDlgMarkWnd::~SvxHlinkDlgMarkWnd()
146 : {
147 0 : ClearTree();
148 0 : }
149 :
150 : /*************************************************************************
151 : |*
152 : |* Set an errorstatus
153 : |*
154 : |************************************************************************/
155 :
156 0 : sal_uInt16 SvxHlinkDlgMarkWnd::SetError( sal_uInt16 nError)
157 : {
158 0 : sal_uInt16 nOldError = mnError;
159 0 : mnError = nError;
160 :
161 0 : if( mnError != LERR_NOERROR )
162 0 : ClearTree();
163 :
164 0 : maLbTree.Invalidate();
165 :
166 0 : return nOldError;
167 : }
168 :
169 : /*************************************************************************
170 : |*
171 : |* Move window
172 : |*
173 : |************************************************************************/
174 :
175 0 : sal_Bool SvxHlinkDlgMarkWnd::MoveTo ( Point aNewPos )
176 : {
177 0 : if ( !mbUserMoved )
178 : {
179 0 : sal_Bool bOldStatus = mbUserMoved;
180 0 : SetPosPixel ( aNewPos );
181 0 : mbUserMoved = bOldStatus;
182 : }
183 :
184 0 : return mbUserMoved;
185 : }
186 :
187 0 : void SvxHlinkDlgMarkWnd::Move ()
188 : {
189 0 : Window::Move();
190 :
191 0 : if ( IsReallyVisible() )
192 0 : mbUserMoved = sal_True;
193 0 : }
194 :
195 0 : sal_Bool SvxHlinkDlgMarkWnd::ConnectToDialog( sal_Bool bDoit )
196 : {
197 0 : sal_Bool bOldStatus = mbUserMoved;
198 :
199 0 : mbUserMoved = !bDoit;
200 :
201 0 : return bOldStatus;
202 : }
203 :
204 : namespace
205 : {
206 0 : void SelectPath(SvTreeListEntry *pEntry, SvxHlmarkTreeLBox &rLbTree,
207 : std::deque<OUString> &rLastSelectedPath)
208 : {
209 0 : OUString sTitle(rLastSelectedPath.front());
210 0 : rLastSelectedPath.pop_front();
211 0 : if (sTitle.isEmpty())
212 0 : return;
213 0 : while (pEntry)
214 : {
215 0 : if (sTitle == rLbTree.GetEntryText(pEntry))
216 : {
217 0 : rLbTree.Select(pEntry);
218 0 : rLbTree.MakeVisible(pEntry);
219 0 : if (!rLastSelectedPath.empty())
220 : {
221 0 : rLbTree.Expand(pEntry);
222 0 : SelectPath(rLbTree.FirstChild(pEntry), rLbTree, rLastSelectedPath);
223 : }
224 0 : break;
225 : }
226 0 : pEntry = rLbTree.NextSibling(pEntry);
227 0 : }
228 : }
229 : }
230 :
231 : #define TG_SETTING_MANAGER "TargetInDocument"
232 : #define TG_SETTING_LASTMARK "LastSelectedMark"
233 : #define TG_SETTING_LASTPATH "LastSelectedPath"
234 :
235 0 : void SvxHlinkDlgMarkWnd::RestoreLastSelection()
236 : {
237 0 : bool bSelectedEntry = false;
238 :
239 0 : OUString sLastSelectedMark;
240 0 : std::deque<OUString> aLastSelectedPath;
241 0 : SvtViewOptions aViewSettings( E_DIALOG, TG_SETTING_MANAGER );
242 0 : if (aViewSettings.Exists())
243 : {
244 : //Maybe we might want to have some sort of mru list and keep a mapping
245 : //per document, rather than the current reuse of "the last thing
246 : //selected, regardless of the document"
247 0 : aViewSettings.GetUserItem(TG_SETTING_LASTMARK) >>= sLastSelectedMark;
248 0 : uno::Sequence<OUString> aTmp;
249 0 : aViewSettings.GetUserItem(TG_SETTING_LASTPATH) >>= aTmp;
250 0 : aLastSelectedPath = comphelper::sequenceToContainer< std::deque<OUString> >(aTmp);
251 : }
252 : //fallback to previous entry selected the last
253 : //time we executed this dialog. First see if
254 : //the exact mark exists and re-use that
255 0 : if (!sLastSelectedMark.isEmpty())
256 0 : bSelectedEntry = SelectEntry(sLastSelectedMark);
257 : //Otherwise just select the closest path available
258 : //now to what was available at dialog close time
259 0 : if (!bSelectedEntry && !aLastSelectedPath.empty())
260 : {
261 0 : std::deque<OUString> aTmpSelectedPath(aLastSelectedPath);
262 0 : SelectPath(maLbTree.First(), maLbTree, aTmpSelectedPath);
263 0 : }
264 0 : }
265 :
266 : /*************************************************************************
267 : |*
268 : |* Interface to refresh tree
269 : |*
270 : |************************************************************************/
271 :
272 0 : void SvxHlinkDlgMarkWnd::RefreshTree (const OUString& aStrURL)
273 : {
274 0 : OUString aUStrURL;
275 :
276 0 : EnterWait();
277 :
278 0 : ClearTree();
279 :
280 0 : sal_Int32 nPos = aStrURL.indexOf('#');
281 :
282 0 : if (nPos != 0)
283 0 : aUStrURL = aStrURL;
284 :
285 0 : if (!RefreshFromDoc(aUStrURL))
286 0 : maLbTree.Invalidate();
287 :
288 0 : bool bSelectedEntry = false;
289 :
290 0 : if ( nPos != -1 )
291 : {
292 0 : OUString aStrMark = aStrURL.copy(nPos+1);
293 0 : bSelectedEntry = SelectEntry(aStrMark);
294 : }
295 :
296 0 : if (!bSelectedEntry)
297 0 : RestoreLastSelection();
298 :
299 0 : LeaveWait();
300 :
301 0 : maStrLastURL = aStrURL;
302 0 : }
303 :
304 : /*************************************************************************
305 : |*
306 : |* get links from document
307 : |*
308 : |************************************************************************/
309 :
310 0 : sal_Bool SvxHlinkDlgMarkWnd::RefreshFromDoc(const OUString& aURL)
311 : {
312 0 : mnError = LERR_NOERROR;
313 :
314 0 : uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( ::comphelper::getProcessComponentContext() );
315 0 : uno::Reference< lang::XComponent > xComp;
316 :
317 0 : if( !aURL.isEmpty() )
318 : {
319 : // load from url
320 0 : uno::Reference< frame::XComponentLoader > xLoader( xDesktop, uno::UNO_QUERY );
321 0 : if( xLoader.is() )
322 : {
323 : try
324 : {
325 0 : uno::Sequence< beans::PropertyValue > aArg(1);
326 0 : aArg.getArray()[0].Name = "Hidden";
327 0 : aArg.getArray()[0].Value <<= (sal_Bool) sal_True;
328 0 : xComp = xLoader->loadComponentFromURL( aURL, OUString( "_blank" ), 0, aArg );
329 : }
330 0 : catch( const io::IOException& )
331 : {
332 :
333 : }
334 0 : catch( const lang::IllegalArgumentException& )
335 : {
336 :
337 : }
338 0 : }
339 : }
340 : else
341 : {
342 : // the component with user focus ( current document )
343 0 : xComp = xDesktop->getCurrentComponent();
344 : }
345 :
346 0 : if( xComp.is() )
347 : {
348 0 : uno::Reference< document::XLinkTargetSupplier > xLTS( xComp, uno::UNO_QUERY );
349 :
350 0 : if( xLTS.is() )
351 : {
352 0 : if( FillTree( xLTS->getLinks() ) == 0 )
353 0 : mnError = LERR_NOENTRIES;
354 : }
355 : else
356 0 : mnError = LERR_DOCNOTOPEN;
357 :
358 0 : if ( !aURL.isEmpty() )
359 0 : xComp->dispose();
360 : }
361 : else
362 : {
363 0 : if( !aURL.isEmpty() )
364 0 : mnError=LERR_DOCNOTOPEN;
365 : }
366 0 : return (mnError==0);
367 : }
368 : /*************************************************************************
369 : |*
370 : |* Fill Tree-Control
371 : |*
372 : |************************************************************************/
373 :
374 0 : int SvxHlinkDlgMarkWnd::FillTree( uno::Reference< container::XNameAccess > xLinks, SvTreeListEntry* pParentEntry )
375 : {
376 0 : int nEntries=0;
377 0 : const uno::Sequence< OUString > aNames( xLinks->getElementNames() );
378 0 : const sal_uLong nLinks = aNames.getLength();
379 0 : const OUString* pNames = aNames.getConstArray();
380 :
381 0 : Color aMaskColor( COL_LIGHTMAGENTA );
382 0 : const OUString aProp_LinkDisplayName( "LinkDisplayName" );
383 0 : const OUString aProp_LinkTarget( "com.sun.star.document.LinkTarget" );
384 0 : const OUString aProp_LinkDisplayBitmap( "LinkDisplayBitmap" );
385 0 : for( sal_uLong i = 0; i < nLinks; i++ )
386 : {
387 0 : uno::Any aAny;
388 0 : OUString aLink( *pNames++ );
389 :
390 0 : sal_Bool bError = sal_False;
391 : try
392 : {
393 0 : aAny = xLinks->getByName( aLink );
394 : }
395 0 : catch(const uno::Exception&)
396 : {
397 : // if the name of the target was invalid (like empty headings)
398 : // no object can be provided
399 0 : bError = sal_True;
400 : }
401 0 : if(bError)
402 0 : continue;
403 :
404 0 : uno::Reference< beans::XPropertySet > xTarget;
405 :
406 0 : if( aAny >>= xTarget )
407 : {
408 : try
409 : {
410 : // get name to display
411 0 : aAny = xTarget->getPropertyValue( aProp_LinkDisplayName );
412 0 : OUString aDisplayName;
413 0 : aAny >>= aDisplayName;
414 0 : OUString aStrDisplayname ( aDisplayName );
415 :
416 : // is it a target ?
417 0 : uno::Reference< lang::XServiceInfo > xSI( xTarget, uno::UNO_QUERY );
418 0 : sal_Bool bIsTarget = xSI->supportsService( aProp_LinkTarget );
419 :
420 : // create userdata
421 0 : TargetData *pData = new TargetData ( aLink, bIsTarget );
422 :
423 : SvTreeListEntry* pEntry;
424 :
425 : try
426 : {
427 : // get bitmap for the tree-entry
428 0 : uno::Reference< awt::XBitmap > aXBitmap( xTarget->getPropertyValue( aProp_LinkDisplayBitmap ), uno::UNO_QUERY );
429 0 : if( aXBitmap.is() )
430 : {
431 0 : Image aBmp( VCLUnoHelper::GetBitmap( aXBitmap ).GetBitmap(), aMaskColor );
432 : // insert Displayname into treelist with bitmaps
433 : pEntry = maLbTree.InsertEntry ( aStrDisplayname,
434 : aBmp, aBmp,
435 : pParentEntry,
436 : false, TREELIST_APPEND,
437 0 : (void*)pData );
438 0 : nEntries++;
439 : }
440 : else
441 : {
442 : // insert Displayname into treelist without bitmaps
443 : pEntry = maLbTree.InsertEntry ( aStrDisplayname,
444 : pParentEntry,
445 : false, TREELIST_APPEND,
446 0 : (void*)pData );
447 0 : nEntries++;
448 0 : }
449 : }
450 0 : catch(const com::sun::star::uno::Exception&)
451 : {
452 : // insert Displayname into treelist without bitmaps
453 : pEntry = maLbTree.InsertEntry ( aStrDisplayname,
454 : pParentEntry,
455 : false, TREELIST_APPEND,
456 0 : (void*)pData );
457 0 : nEntries++;
458 : }
459 :
460 0 : uno::Reference< document::XLinkTargetSupplier > xLTS( xTarget, uno::UNO_QUERY );
461 0 : if( xLTS.is() )
462 0 : nEntries += FillTree( xLTS->getLinks(), pEntry );
463 : }
464 0 : catch(const com::sun::star::uno::Exception&)
465 : {
466 : }
467 : }
468 0 : }
469 :
470 0 : return nEntries;
471 : }
472 :
473 : /*************************************************************************
474 : |*
475 : |* Clear Tree
476 : |*
477 : |************************************************************************/
478 :
479 0 : void SvxHlinkDlgMarkWnd::ClearTree()
480 : {
481 0 : SvTreeListEntry* pEntry = maLbTree.First();
482 :
483 0 : while ( pEntry )
484 : {
485 0 : TargetData* pUserData = ( TargetData * ) pEntry->GetUserData();
486 0 : delete pUserData;
487 :
488 0 : pEntry = maLbTree.Next( pEntry );
489 : }
490 :
491 0 : maLbTree.Clear();
492 0 : }
493 :
494 : /*************************************************************************
495 : |*
496 : |* Find Entry for String
497 : |*
498 : |************************************************************************/
499 :
500 0 : SvTreeListEntry* SvxHlinkDlgMarkWnd::FindEntry (const OUString& aStrName)
501 : {
502 0 : sal_Bool bFound=sal_False;
503 0 : SvTreeListEntry* pEntry = maLbTree.First();
504 :
505 0 : while ( pEntry && !bFound )
506 : {
507 0 : TargetData* pUserData = ( TargetData * ) pEntry->GetUserData ();
508 0 : if (aStrName == pUserData->aUStrLinkname)
509 0 : bFound = sal_True;
510 : else
511 0 : pEntry = maLbTree.Next( pEntry );
512 : }
513 :
514 0 : return pEntry;
515 : }
516 :
517 : /*************************************************************************
518 : |*
519 : |* Select Entry
520 : |*
521 : |************************************************************************/
522 :
523 0 : bool SvxHlinkDlgMarkWnd::SelectEntry(const OUString& aStrMark)
524 : {
525 0 : SvTreeListEntry* pEntry = FindEntry(aStrMark);
526 0 : if (!pEntry)
527 0 : return false;
528 0 : maLbTree.Select(pEntry);
529 0 : maLbTree.MakeVisible (pEntry);
530 0 : return true;
531 : }
532 :
533 : /*************************************************************************
534 : |*
535 : |* Click on Apply-Button / Doubleclick on item in tree
536 : |*
537 : |************************************************************************/
538 :
539 0 : IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl)
540 : {
541 0 : SvTreeListEntry* pEntry = maLbTree.GetCurEntry();
542 :
543 0 : if ( pEntry )
544 : {
545 0 : TargetData *pData = ( TargetData * )pEntry->GetUserData();
546 :
547 0 : if ( pData->bIsTarget )
548 : {
549 0 : mpParent->SetMarkStr(pData->aUStrLinkname);
550 : }
551 : }
552 :
553 0 : return( 0L );
554 : }
555 :
556 : /*************************************************************************
557 : |*
558 : |* Click on Close-Button
559 : |*
560 : |************************************************************************/
561 :
562 0 : IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl)
563 : {
564 0 : SvTreeListEntry* pEntry = maLbTree.GetCurEntry();
565 0 : if ( pEntry )
566 : {
567 0 : TargetData* pUserData = (TargetData *) pEntry->GetUserData();
568 0 : OUString sLastSelectedMark = pUserData->aUStrLinkname;
569 :
570 0 : std::deque<OUString> aLastSelectedPath;
571 0 : if (pEntry)
572 : {
573 : //If the bottommost entry is expanded but nothing
574 : //underneath it is selected leave a dummy entry
575 0 : if (maLbTree.IsExpanded(pEntry))
576 0 : aLastSelectedPath.push_front(OUString());
577 0 : while (pEntry)
578 : {
579 0 : aLastSelectedPath.push_front(maLbTree.GetEntryText(pEntry));
580 0 : pEntry = maLbTree.GetParent(pEntry);
581 : }
582 : }
583 :
584 0 : uno::Sequence< beans::NamedValue > aSettings(2);
585 0 : aSettings[0].Name = TG_SETTING_LASTMARK;
586 0 : aSettings[0].Value <<= sLastSelectedMark;
587 0 : aSettings[1].Name = TG_SETTING_LASTPATH;
588 0 : aSettings[1].Value <<= comphelper::containerToSequence<OUString>(aLastSelectedPath);
589 :
590 : // write
591 0 : SvtViewOptions aViewSettings( E_DIALOG, TG_SETTING_MANAGER );
592 0 : aViewSettings.SetUserData( aSettings );
593 : }
594 :
595 0 : Close();
596 :
597 0 : return( 0L );
598 0 : }
599 :
600 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|