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