bump product version to 5.0.4.1
[LibreOffice.git] / cui / source / dialogs / hlmarkwn.cxx
blob9add30bc15b5167c4f8adc25bbe99d31fbf18610
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
28 // UNO-Stuff
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"
41 #include <cuires.hrc>
42 #include "hlmarkwn.hxx"
43 #include "hltpbase.hxx"
45 using namespace ::com::sun::star;
47 /*************************************************************************
49 |* Userdata-struct for tree-entries
51 |************************************************************************/
53 struct TargetData
55 OUString aUStrLinkname;
56 bool bIsTarget;
58 TargetData (const OUString& aUStrLName, bool bTarget)
59 : bIsTarget(bTarget)
61 if (bIsTarget)
62 aUStrLinkname = aUStrLName;
66 //# #
67 //# Tree-Window #
68 //# #
69 SvxHlmarkTreeLBox::SvxHlmarkTreeLBox(vcl::Window* pParent, WinBits nStyle)
70 : SvTreeListBox(pParent, nStyle)
71 , mpParentWnd(NULL)
73 SetNodeDefaultImages();
76 SvxHlmarkTreeLBox::~SvxHlmarkTreeLBox()
78 disposeOnce();
81 void SvxHlmarkTreeLBox::dispose()
83 mpParentWnd.clear();
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);
107 else
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 );
119 break;
120 case LERR_DOCNOTOPEN :
121 aStrMessage = CUI_RESSTR( RID_SVXSTR_HYPDLG_ERR_LERR_DOCNOTOPEN );
122 break;
125 rRenderContext.DrawText(aDrawRect, aStrMessage, DrawTextFlags::Left | DrawTextFlags::MultiLine | DrawTextFlags::WordBreak);
130 //# #
131 //# Window-Class #
132 //# #
135 /*************************************************************************
137 |* Constructor / Destructor
139 |************************************************************************/
140 SvxHlinkDlgMarkWnd::SvxHlinkDlgMarkWnd( SvxHyperlinkTabPageBase *pParent )
141 : ModalDialog(pParent, "HyperlinkMark", "cui/ui/hyperlinkmarkdialog.ui")
142 , mbUserMoved(false)
143 , mpParent(pParent)
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()
163 disposeOnce();
166 void SvxHlinkDlgMarkWnd::dispose()
168 ClearTree();
169 mpBtApply.clear();
170 mpBtClose.clear();
171 mpLbTree.clear();
172 mpParent.clear();
173 ModalDialog::dispose();
176 /*************************************************************************
178 |* Set an errorstatus
180 |************************************************************************/
181 sal_uInt16 SvxHlinkDlgMarkWnd::SetError( sal_uInt16 nError)
183 sal_uInt16 nOldError = mnError;
184 mnError = nError;
186 if( mnError != LERR_NOERROR )
187 ClearTree();
189 mpLbTree->Invalidate();
191 return nOldError;
194 /*************************************************************************
196 |* Move window
198 |************************************************************************/
200 bool SvxHlinkDlgMarkWnd::MoveTo ( Point aNewPos )
202 if ( !mbUserMoved )
204 bool bOldStatus = mbUserMoved;
205 SetPosPixel ( aNewPos );
206 mbUserMoved = bOldStatus;
209 return mbUserMoved;
212 void SvxHlinkDlgMarkWnd::Move ()
214 Window::Move();
216 if ( IsReallyVisible() )
217 mbUserMoved = true;
220 bool SvxHlinkDlgMarkWnd::ConnectToDialog( bool bDoit )
222 bool bOldStatus = mbUserMoved;
224 mbUserMoved = !bDoit;
226 return bOldStatus;
229 namespace
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())
237 return;
238 while (pEntry)
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);
249 break;
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)
299 OUString aUStrURL;
301 EnterWait();
303 ClearTree();
305 sal_Int32 nPos = aStrURL.indexOf('#');
307 if (nPos != 0)
308 aUStrURL = aStrURL;
310 if (!RefreshFromDoc(aUStrURL))
311 mpLbTree->Invalidate();
313 bool bSelectedEntry = false;
315 if ( nPos != -1 )
317 OUString aStrMark = aStrURL.copy(nPos+1);
318 bSelectedEntry = SelectEntry(aStrMark);
321 if (!bSelectedEntry)
322 RestoreLastSelection();
324 LeaveWait();
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() )
344 // load from url
345 uno::Reference< frame::XComponentLoader > xLoader( xDesktop, uno::UNO_QUERY );
346 if( xLoader.is() )
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& )
365 else
367 // the component with user focus ( current document )
368 xComp = xDesktop->getCurrentComponent();
371 if( xComp.is() )
373 uno::Reference< document::XLinkTargetSupplier > xLTS( xComp, uno::UNO_QUERY );
375 if( xLTS.is() )
377 if( FillTree( xLTS->getLinks() ) == 0 )
378 mnError = LERR_NOENTRIES;
380 else
381 mnError = LERR_DOCNOTOPEN;
383 if ( !aURL.isEmpty() )
384 xComp->dispose();
386 else
388 if( !aURL.isEmpty() )
389 mnError=LERR_DOCNOTOPEN;
391 return (mnError==0);
393 /*************************************************************************
395 |* Fill Tree-Control
397 |************************************************************************/
399 int SvxHlinkDlgMarkWnd::FillTree( uno::Reference< container::XNameAccess > xLinks, SvTreeListEntry* pParentEntry )
401 int nEntries=0;
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++ )
412 uno::Any aAny;
413 OUString aLink( *pNames++ );
415 bool bError = false;
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
424 bError = true;
426 if(bError)
427 continue;
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 );
441 // is it a target ?
442 uno::Reference< lang::XServiceInfo > xSI( xTarget, uno::UNO_QUERY );
443 bool bIsTarget = xSI->supportsService( aProp_LinkTarget );
445 // create userdata
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 );
454 if( aXBitmap.is() )
456 Image aBmp( VCLUnoHelper::GetBitmap( aXBitmap ).GetBitmap(), aMaskColor );
457 // insert Displayname into treelist with bitmaps
458 pEntry = mpLbTree->InsertEntry ( aStrDisplayname,
459 aBmp, aBmp,
460 pParentEntry,
461 false, TREELIST_APPEND,
462 (void*)pData );
463 nEntries++;
465 else
467 // insert Displayname into treelist without bitmaps
468 pEntry = mpLbTree->InsertEntry ( aStrDisplayname,
469 pParentEntry,
470 false, TREELIST_APPEND,
471 (void*)pData );
472 nEntries++;
475 catch(const com::sun::star::uno::Exception&)
477 // insert Displayname into treelist without bitmaps
478 pEntry = mpLbTree->InsertEntry ( aStrDisplayname,
479 pParentEntry,
480 false, TREELIST_APPEND,
481 (void*)pData );
482 nEntries++;
485 uno::Reference< document::XLinkTargetSupplier > xLTS( xTarget, uno::UNO_QUERY );
486 if( xLTS.is() )
487 nEntries += FillTree( xLTS->getLinks(), pEntry );
489 catch(const com::sun::star::uno::Exception&)
495 return nEntries;
498 /*************************************************************************
500 |* Clear Tree
502 |************************************************************************/
504 void SvxHlinkDlgMarkWnd::ClearTree()
506 SvTreeListEntry* pEntry = mpLbTree->First();
508 while ( pEntry )
510 TargetData* pUserData = static_cast<TargetData *>(pEntry->GetUserData());
511 delete pUserData;
513 pEntry = mpLbTree->Next( pEntry );
516 mpLbTree->Clear();
519 /*************************************************************************
521 |* Find Entry for String
523 |************************************************************************/
525 SvTreeListEntry* SvxHlinkDlgMarkWnd::FindEntry (const OUString& aStrName)
527 bool bFound=false;
528 SvTreeListEntry* pEntry = mpLbTree->First();
530 while ( pEntry && !bFound )
532 TargetData* pUserData = static_cast<TargetData *>(pEntry->GetUserData ());
533 if (aStrName == pUserData->aUStrLinkname)
534 bFound = true;
535 else
536 pEntry = mpLbTree->Next( pEntry );
539 return pEntry;
542 /*************************************************************************
544 |* Select Entry
546 |************************************************************************/
548 bool SvxHlinkDlgMarkWnd::SelectEntry(const OUString& aStrMark)
550 SvTreeListEntry* pEntry = FindEntry(aStrMark);
551 if (!pEntry)
552 return false;
553 mpLbTree->Select(pEntry);
554 mpLbTree->MakeVisible (pEntry);
555 return true;
558 /*************************************************************************
560 |* Click on Apply-Button / Doubleclick on item in tree
562 |************************************************************************/
564 IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl)
566 SvTreeListEntry* pEntry = mpLbTree->GetCurEntry();
568 if ( pEntry )
570 TargetData *pData = static_cast<TargetData *>(pEntry->GetUserData());
572 if ( pData->bIsTarget )
574 mpParent->SetMarkStr(pData->aUStrLinkname);
578 return 0L;
581 /*************************************************************************
583 |* Click on Close-Button
585 |************************************************************************/
587 IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl)
589 SvTreeListEntry* pEntry = mpLbTree->GetCurEntry();
590 if ( pEntry )
592 TargetData* pUserData = static_cast<TargetData *>(pEntry->GetUserData());
593 OUString sLastSelectedMark = pUserData->aUStrLinkname;
595 std::deque<OUString> aLastSelectedPath;
596 if (pEntry)
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());
602 while (pEntry)
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);
615 // write
616 SvtViewOptions aViewSettings( E_DIALOG, TG_SETTING_MANAGER );
617 aViewSettings.SetUserData( aSettings );
620 Close();
622 return 0L;
625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */