1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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 #include <vcl/builderfactory.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/sequence.hxx>
31 #include <com/sun/star/awt/XBitmap.hpp>
32 #include <com/sun/star/frame/Desktop.hpp>
33 #include <com/sun/star/frame/XComponentLoader.hpp>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/document/XLinkTargetSupplier.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <toolkit/helper/vclunohelper.hxx>
39 #include "svtools/treelistentry.hxx"
42 #include "hlmarkwn.hxx"
43 #include "hltpbase.hxx"
45 using namespace ::com::sun::star
;
47 /*************************************************************************
49 |* Userdata-struct for tree-entries
51 |************************************************************************/
55 OUString aUStrLinkname
;
58 TargetData (const OUString
& aUStrLName
, bool bTarget
)
62 aUStrLinkname
= aUStrLName
;
69 SvxHlmarkTreeLBox::SvxHlmarkTreeLBox(vcl::Window
* pParent
, WinBits nStyle
)
70 : SvTreeListBox(pParent
, nStyle
)
73 SetNodeDefaultImages();
76 SvxHlmarkTreeLBox::~SvxHlmarkTreeLBox()
81 void SvxHlmarkTreeLBox::dispose()
84 SvTreeListBox::dispose();
87 VCL_BUILDER_DECL_FACTORY(SvxHlmarkTreeLBox
)
89 WinBits nWinStyle
= WB_TABSTOP
;
90 OString sBorder
= VclBuilder::extractCustomProperty(rMap
);
91 if (!sBorder
.isEmpty())
92 nWinStyle
|= WB_BORDER
;
93 rRet
= VclPtr
<SvxHlmarkTreeLBox
>::Create(pParent
, nWinStyle
);
96 Size
SvxHlmarkTreeLBox::GetOptimalSize() const
98 return LogicToPixel(Size(103, 162), MAP_APPFONT
);
101 void SvxHlmarkTreeLBox::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRect
)
103 if (!mpParentWnd
|| mpParentWnd
->mnError
== LERR_NOERROR
)
105 SvTreeListBox::Paint(rRenderContext
, rRect
);
109 Erase(rRenderContext
);
111 Rectangle
aDrawRect(Point( 0, 0 ), GetSizePixel());
113 OUString aStrMessage
;
115 switch (mpParentWnd
->mnError
)
117 case LERR_NOENTRIES
:
118 aStrMessage
= CUI_RESSTR( RID_SVXSTR_HYPDLG_ERR_LERR_NOENTRIES
);
120 case LERR_DOCNOTOPEN
:
121 aStrMessage
= CUI_RESSTR( RID_SVXSTR_HYPDLG_ERR_LERR_DOCNOTOPEN
);
125 rRenderContext
.DrawText(aDrawRect
, aStrMessage
, DrawTextFlags::Left
| DrawTextFlags::MultiLine
| DrawTextFlags::WordBreak
);
135 /*************************************************************************
137 |* Constructor / Destructor
139 |************************************************************************/
140 SvxHlinkDlgMarkWnd::SvxHlinkDlgMarkWnd( SvxHyperlinkTabPageBase
*pParent
)
141 : ModalDialog(pParent
, "HyperlinkMark", "cui/ui/hyperlinkmarkdialog.ui")
144 , mnError(LERR_NOERROR
)
146 get(mpBtApply
, "apply");
147 get(mpBtClose
, "close");
148 get(mpLbTree
, "TreeListBox");
149 mpLbTree
->SetParentWnd(this);
151 mpBtApply
->SetClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd
, ClickApplyHdl_Impl
) );
152 mpBtClose
->SetClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd
, ClickCloseHdl_Impl
) );
153 mpLbTree
->SetDoubleClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd
, ClickApplyHdl_Impl
) );
155 // add lines to the Tree-ListBox
156 mpLbTree
->SetStyle( mpLbTree
->GetStyle() | WB_TABSTOP
| WB_BORDER
| WB_HASLINES
|
157 WB_HASBUTTONS
| //WB_HASLINESATROOT |
158 WB_HSCROLL
| WB_HASBUTTONSATROOT
);
161 SvxHlinkDlgMarkWnd::~SvxHlinkDlgMarkWnd()
166 void SvxHlinkDlgMarkWnd::dispose()
173 ModalDialog::dispose();
176 /*************************************************************************
178 |* Set an errorstatus
180 |************************************************************************/
181 sal_uInt16
SvxHlinkDlgMarkWnd::SetError( sal_uInt16 nError
)
183 sal_uInt16 nOldError
= mnError
;
186 if( mnError
!= LERR_NOERROR
)
189 mpLbTree
->Invalidate();
194 /*************************************************************************
198 |************************************************************************/
200 bool SvxHlinkDlgMarkWnd::MoveTo ( Point aNewPos
)
204 bool bOldStatus
= mbUserMoved
;
205 SetPosPixel ( aNewPos
);
206 mbUserMoved
= bOldStatus
;
212 void SvxHlinkDlgMarkWnd::Move ()
216 if ( IsReallyVisible() )
220 bool SvxHlinkDlgMarkWnd::ConnectToDialog( bool bDoit
)
222 bool bOldStatus
= mbUserMoved
;
224 mbUserMoved
= !bDoit
;
231 void SelectPath(SvTreeListEntry
*pEntry
, SvxHlmarkTreeLBox
&rLbTree
,
232 std::deque
<OUString
> &rLastSelectedPath
)
234 OUString
sTitle(rLastSelectedPath
.front());
235 rLastSelectedPath
.pop_front();
236 if (sTitle
.isEmpty())
240 if (sTitle
== rLbTree
.GetEntryText(pEntry
))
242 rLbTree
.Select(pEntry
);
243 rLbTree
.MakeVisible(pEntry
);
244 if (!rLastSelectedPath
.empty())
246 rLbTree
.Expand(pEntry
);
247 SelectPath(rLbTree
.FirstChild(pEntry
), rLbTree
, rLastSelectedPath
);
251 pEntry
= SvTreeListBox::NextSibling(pEntry
);
256 #define TG_SETTING_MANAGER "TargetInDocument"
257 #define TG_SETTING_LASTMARK "LastSelectedMark"
258 #define TG_SETTING_LASTPATH "LastSelectedPath"
260 void SvxHlinkDlgMarkWnd::RestoreLastSelection()
262 bool bSelectedEntry
= false;
264 OUString sLastSelectedMark
;
265 std::deque
<OUString
> aLastSelectedPath
;
266 SvtViewOptions
aViewSettings( E_DIALOG
, TG_SETTING_MANAGER
);
267 if (aViewSettings
.Exists())
269 //Maybe we might want to have some sort of mru list and keep a mapping
270 //per document, rather than the current reuse of "the last thing
271 //selected, regardless of the document"
272 aViewSettings
.GetUserItem(TG_SETTING_LASTMARK
) >>= sLastSelectedMark
;
273 uno::Sequence
<OUString
> aTmp
;
274 aViewSettings
.GetUserItem(TG_SETTING_LASTPATH
) >>= aTmp
;
275 aLastSelectedPath
= comphelper::sequenceToContainer
< std::deque
<OUString
> >(aTmp
);
277 //fallback to previous entry selected the last
278 //time we executed this dialog. First see if
279 //the exact mark exists and re-use that
280 if (!sLastSelectedMark
.isEmpty())
281 bSelectedEntry
= SelectEntry(sLastSelectedMark
);
282 //Otherwise just select the closest path available
283 //now to what was available at dialog close time
284 if (!bSelectedEntry
&& !aLastSelectedPath
.empty())
286 std::deque
<OUString
> aTmpSelectedPath(aLastSelectedPath
);
287 SelectPath(mpLbTree
->First(), *mpLbTree
, aTmpSelectedPath
);
291 /*************************************************************************
293 |* Interface to refresh tree
295 |************************************************************************/
297 void SvxHlinkDlgMarkWnd::RefreshTree (const OUString
& aStrURL
)
305 sal_Int32 nPos
= aStrURL
.indexOf('#');
310 if (!RefreshFromDoc(aUStrURL
))
311 mpLbTree
->Invalidate();
313 bool bSelectedEntry
= false;
317 OUString aStrMark
= aStrURL
.copy(nPos
+1);
318 bSelectedEntry
= SelectEntry(aStrMark
);
322 RestoreLastSelection();
326 maStrLastURL
= aStrURL
;
329 /*************************************************************************
331 |* get links from document
333 |************************************************************************/
335 bool SvxHlinkDlgMarkWnd::RefreshFromDoc(const OUString
& aURL
)
337 mnError
= LERR_NOERROR
;
339 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( ::comphelper::getProcessComponentContext() );
340 uno::Reference
< lang::XComponent
> xComp
;
342 if( !aURL
.isEmpty() )
345 uno::Reference
< frame::XComponentLoader
> xLoader( xDesktop
, uno::UNO_QUERY
);
350 uno::Sequence
< beans::PropertyValue
> aArg(1);
351 aArg
.getArray()[0].Name
= "Hidden";
352 aArg
.getArray()[0].Value
<<= true;
353 xComp
= xLoader
->loadComponentFromURL( aURL
, OUString( "_blank" ), 0, aArg
);
355 catch( const io::IOException
& )
359 catch( const lang::IllegalArgumentException
& )
367 // the component with user focus ( current document )
368 xComp
= xDesktop
->getCurrentComponent();
373 uno::Reference
< document::XLinkTargetSupplier
> xLTS( xComp
, uno::UNO_QUERY
);
377 if( FillTree( xLTS
->getLinks() ) == 0 )
378 mnError
= LERR_NOENTRIES
;
381 mnError
= LERR_DOCNOTOPEN
;
383 if ( !aURL
.isEmpty() )
388 if( !aURL
.isEmpty() )
389 mnError
=LERR_DOCNOTOPEN
;
393 /*************************************************************************
397 |************************************************************************/
399 int SvxHlinkDlgMarkWnd::FillTree( uno::Reference
< container::XNameAccess
> xLinks
, SvTreeListEntry
* pParentEntry
)
402 const uno::Sequence
< OUString
> aNames( xLinks
->getElementNames() );
403 const sal_uLong nLinks
= aNames
.getLength();
404 const OUString
* pNames
= aNames
.getConstArray();
406 Color
aMaskColor( COL_LIGHTMAGENTA
);
407 const OUString
aProp_LinkDisplayName( "LinkDisplayName" );
408 const OUString
aProp_LinkTarget( "com.sun.star.document.LinkTarget" );
409 const OUString
aProp_LinkDisplayBitmap( "LinkDisplayBitmap" );
410 for( sal_uLong i
= 0; i
< nLinks
; i
++ )
413 OUString
aLink( *pNames
++ );
418 aAny
= xLinks
->getByName( aLink
);
420 catch(const uno::Exception
&)
422 // if the name of the target was invalid (like empty headings)
423 // no object can be provided
429 uno::Reference
< beans::XPropertySet
> xTarget
;
431 if( aAny
>>= xTarget
)
435 // get name to display
436 aAny
= xTarget
->getPropertyValue( aProp_LinkDisplayName
);
437 OUString aDisplayName
;
438 aAny
>>= aDisplayName
;
439 OUString
aStrDisplayname ( aDisplayName
);
442 uno::Reference
< lang::XServiceInfo
> xSI( xTarget
, uno::UNO_QUERY
);
443 bool bIsTarget
= xSI
->supportsService( aProp_LinkTarget
);
446 TargetData
*pData
= new TargetData ( aLink
, bIsTarget
);
448 SvTreeListEntry
* pEntry
;
452 // get bitmap for the tree-entry
453 uno::Reference
< awt::XBitmap
> aXBitmap( xTarget
->getPropertyValue( aProp_LinkDisplayBitmap
), uno::UNO_QUERY
);
456 Image
aBmp( VCLUnoHelper::GetBitmap( aXBitmap
).GetBitmap(), aMaskColor
);
457 // insert Displayname into treelist with bitmaps
458 pEntry
= mpLbTree
->InsertEntry ( aStrDisplayname
,
461 false, TREELIST_APPEND
,
467 // insert Displayname into treelist without bitmaps
468 pEntry
= mpLbTree
->InsertEntry ( aStrDisplayname
,
470 false, TREELIST_APPEND
,
475 catch(const com::sun::star::uno::Exception
&)
477 // insert Displayname into treelist without bitmaps
478 pEntry
= mpLbTree
->InsertEntry ( aStrDisplayname
,
480 false, TREELIST_APPEND
,
485 uno::Reference
< document::XLinkTargetSupplier
> xLTS( xTarget
, uno::UNO_QUERY
);
487 nEntries
+= FillTree( xLTS
->getLinks(), pEntry
);
489 catch(const com::sun::star::uno::Exception
&)
498 /*************************************************************************
502 |************************************************************************/
504 void SvxHlinkDlgMarkWnd::ClearTree()
506 SvTreeListEntry
* pEntry
= mpLbTree
->First();
510 TargetData
* pUserData
= static_cast<TargetData
*>(pEntry
->GetUserData());
513 pEntry
= mpLbTree
->Next( pEntry
);
519 /*************************************************************************
521 |* Find Entry for String
523 |************************************************************************/
525 SvTreeListEntry
* SvxHlinkDlgMarkWnd::FindEntry (const OUString
& aStrName
)
528 SvTreeListEntry
* pEntry
= mpLbTree
->First();
530 while ( pEntry
&& !bFound
)
532 TargetData
* pUserData
= static_cast<TargetData
*>(pEntry
->GetUserData ());
533 if (aStrName
== pUserData
->aUStrLinkname
)
536 pEntry
= mpLbTree
->Next( pEntry
);
542 /*************************************************************************
546 |************************************************************************/
548 bool SvxHlinkDlgMarkWnd::SelectEntry(const OUString
& aStrMark
)
550 SvTreeListEntry
* pEntry
= FindEntry(aStrMark
);
553 mpLbTree
->Select(pEntry
);
554 mpLbTree
->MakeVisible (pEntry
);
558 /*************************************************************************
560 |* Click on Apply-Button / Doubleclick on item in tree
562 |************************************************************************/
564 IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd
, ClickApplyHdl_Impl
)
566 SvTreeListEntry
* pEntry
= mpLbTree
->GetCurEntry();
570 TargetData
*pData
= static_cast<TargetData
*>(pEntry
->GetUserData());
572 if ( pData
->bIsTarget
)
574 mpParent
->SetMarkStr(pData
->aUStrLinkname
);
581 /*************************************************************************
583 |* Click on Close-Button
585 |************************************************************************/
587 IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd
, ClickCloseHdl_Impl
)
589 SvTreeListEntry
* pEntry
= mpLbTree
->GetCurEntry();
592 TargetData
* pUserData
= static_cast<TargetData
*>(pEntry
->GetUserData());
593 OUString sLastSelectedMark
= pUserData
->aUStrLinkname
;
595 std::deque
<OUString
> aLastSelectedPath
;
598 //If the bottommost entry is expanded but nothing
599 //underneath it is selected leave a dummy entry
600 if (mpLbTree
->IsExpanded(pEntry
))
601 aLastSelectedPath
.push_front(OUString());
604 aLastSelectedPath
.push_front(mpLbTree
->GetEntryText(pEntry
));
605 pEntry
= mpLbTree
->GetParent(pEntry
);
609 uno::Sequence
< beans::NamedValue
> aSettings(2);
610 aSettings
[0].Name
= TG_SETTING_LASTMARK
;
611 aSettings
[0].Value
<<= sLastSelectedMark
;
612 aSettings
[1].Name
= TG_SETTING_LASTPATH
;
613 aSettings
[1].Value
<<= comphelper::containerToSequence
<OUString
>(aLastSelectedPath
);
616 SvtViewOptions
aViewSettings( E_DIALOG
, TG_SETTING_MANAGER
);
617 aViewSettings
.SetUserData( aSettings
);
625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */