bump product version to 6.3.0.0.beta1
[LibreOffice.git] / cui / source / dialogs / hlmarkwn.cxx
blobcada8bde7494424dea4b54aa52ca39f3daace52b
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/NamedValue.hpp>
35 #include <com/sun/star/beans/PropertyValue.hpp>
36 #include <com/sun/star/document/XLinkTargetSupplier.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/io/IOException.hpp>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <vcl/treelistentry.hxx>
43 #include <strings.hrc>
44 #include <hlmarkwn.hxx>
45 #include <hltpbase.hxx>
47 using namespace ::com::sun::star;
49 // Userdata-struct for tree-entries
50 struct TargetData
52 OUString aUStrLinkname;
53 bool bIsTarget;
55 TargetData (const OUString& aUStrLName, bool bTarget)
56 : bIsTarget(bTarget)
58 if (bIsTarget)
59 aUStrLinkname = aUStrLName;
63 // Tree-Window
64 SvxHlmarkTreeLBox::SvxHlmarkTreeLBox(vcl::Window* pParent, WinBits nStyle)
65 : SvTreeListBox(pParent, nStyle)
66 , mpParentWnd(nullptr)
68 SetNodeDefaultImages();
71 SvxHlmarkTreeLBox::~SvxHlmarkTreeLBox()
73 disposeOnce();
76 void SvxHlmarkTreeLBox::dispose()
78 mpParentWnd.clear();
79 SvTreeListBox::dispose();
82 VCL_BUILDER_FACTORY_CONSTRUCTOR(SvxHlmarkTreeLBox, WB_TABSTOP)
84 Size SvxHlmarkTreeLBox::GetOptimalSize() const
86 return LogicToPixel(Size(103, 162), MapMode(MapUnit::MapAppFont));
89 void SvxHlmarkTreeLBox::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect)
91 if (!mpParentWnd || mpParentWnd->mnError == LERR_NOERROR)
93 SvTreeListBox::Paint(rRenderContext, rRect);
95 else
97 Erase(rRenderContext);
99 ::tools::Rectangle aDrawRect(Point( 0, 0 ), GetSizePixel());
101 OUString aStrMessage;
103 switch (mpParentWnd->mnError)
105 case LERR_NOENTRIES :
106 aStrMessage = CuiResId( RID_SVXSTR_HYPDLG_ERR_LERR_NOENTRIES );
107 break;
108 case LERR_DOCNOTOPEN :
109 aStrMessage = CuiResId( RID_SVXSTR_HYPDLG_ERR_LERR_DOCNOTOPEN );
110 break;
113 rRenderContext.DrawText(aDrawRect, aStrMessage, DrawTextFlags::Left
114 | DrawTextFlags::MultiLine | DrawTextFlags::WordBreak);
119 //*** Window-Class ***
120 // Constructor / Destructor
121 SvxHlinkDlgMarkWnd::SvxHlinkDlgMarkWnd( SvxHyperlinkTabPageBase *pParent )
122 : FloatingWindow(pParent, "HyperlinkMark", "cui/ui/hyperlinkmarkdialog.ui")
123 , mbUserMoved(false)
124 , mpParent(pParent)
125 , mnError(LERR_NOERROR)
127 get(mpBtApply, "apply");
128 get(mpBtClose, "close");
129 get(mpLbTree, "TreeListBox");
130 mpLbTree->SetParentWnd(this);
132 mpBtApply->SetClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl ) );
133 mpBtClose->SetClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl ) );
134 mpLbTree->SetDoubleClickHdl ( LINK ( this, SvxHlinkDlgMarkWnd, DoubleClickApplyHdl_Impl ) );
136 // add lines to the Tree-ListBox
137 mpLbTree->SetStyle( mpLbTree->GetStyle() | WB_TABSTOP | WB_BORDER | WB_HASLINES |
138 WB_HASBUTTONS | //WB_HASLINESATROOT |
139 WB_HSCROLL | WB_HASBUTTONSATROOT );
142 SvxHlinkDlgMarkWnd::~SvxHlinkDlgMarkWnd()
144 disposeOnce();
147 void SvxHlinkDlgMarkWnd::dispose()
149 ClearTree();
150 mpBtApply.clear();
151 mpBtClose.clear();
152 mpLbTree.clear();
153 mpParent.clear();
154 FloatingWindow::dispose();
157 // Set an errorstatus
158 sal_uInt16 SvxHlinkDlgMarkWnd::SetError( sal_uInt16 nError)
160 sal_uInt16 nOldError = mnError;
161 mnError = nError;
163 if( mnError != LERR_NOERROR )
164 ClearTree();
166 mpLbTree->Invalidate();
168 return nOldError;
171 // Move window
172 bool SvxHlinkDlgMarkWnd::MoveTo ( Point aNewPos )
174 if ( !mbUserMoved )
176 bool bOldStatus = mbUserMoved;
177 SetPosPixel ( aNewPos );
178 mbUserMoved = bOldStatus;
181 return mbUserMoved;
184 void SvxHlinkDlgMarkWnd::Move ()
186 Window::Move();
188 if ( IsReallyVisible() )
189 mbUserMoved = true;
192 bool SvxHlinkDlgMarkWnd::ConnectToDialog()
194 bool bOldStatus = mbUserMoved;
196 mbUserMoved = true;
198 return bOldStatus;
201 namespace
203 void SelectPath(SvTreeListEntry *pEntry, SvxHlmarkTreeLBox &rLbTree,
204 std::deque<OUString> &rLastSelectedPath)
206 OUString sTitle(rLastSelectedPath.front());
207 rLastSelectedPath.pop_front();
208 if (sTitle.isEmpty())
209 return;
210 while (pEntry)
212 if (sTitle == rLbTree.GetEntryText(pEntry))
214 rLbTree.Select(pEntry);
215 rLbTree.MakeVisible(pEntry);
216 if (!rLastSelectedPath.empty())
218 rLbTree.Expand(pEntry);
219 SelectPath(rLbTree.FirstChild(pEntry), rLbTree, rLastSelectedPath);
221 break;
223 pEntry = pEntry->NextSibling();
228 #define TG_SETTING_MANAGER "TargetInDocument"
229 #define TG_SETTING_LASTMARK "LastSelectedMark"
230 #define TG_SETTING_LASTPATH "LastSelectedPath"
232 void SvxHlinkDlgMarkWnd::RestoreLastSelection()
234 bool bSelectedEntry = false;
236 OUString sLastSelectedMark;
237 std::deque<OUString> aLastSelectedPath;
238 SvtViewOptions aViewSettings( EViewType::Dialog, TG_SETTING_MANAGER );
239 if (aViewSettings.Exists())
241 //Maybe we might want to have some sort of mru list and keep a mapping
242 //per document, rather than the current reuse of "the last thing
243 //selected, regardless of the document"
244 aViewSettings.GetUserItem(TG_SETTING_LASTMARK) >>= sLastSelectedMark;
245 uno::Sequence<OUString> aTmp;
246 aViewSettings.GetUserItem(TG_SETTING_LASTPATH) >>= aTmp;
247 aLastSelectedPath = comphelper::sequenceToContainer< std::deque<OUString> >(aTmp);
249 //fallback to previous entry selected the last time we executed this dialog.
250 //First see if the exact mark exists and re-use that
251 if (!sLastSelectedMark.isEmpty())
252 bSelectedEntry = SelectEntry(sLastSelectedMark);
253 //Otherwise just select the closest path available
254 //now to what was available at dialog close time
255 if (!bSelectedEntry && !aLastSelectedPath.empty())
257 std::deque<OUString> aTmpSelectedPath(aLastSelectedPath);
258 SelectPath(mpLbTree->First(), *mpLbTree, aTmpSelectedPath);
262 // Interface to refresh tree
263 void SvxHlinkDlgMarkWnd::RefreshTree (const OUString& aStrURL)
265 OUString aUStrURL;
267 EnterWait();
269 ClearTree();
271 sal_Int32 nPos = aStrURL.indexOf('#');
273 if (nPos != 0)
274 aUStrURL = aStrURL;
276 if (!RefreshFromDoc(aUStrURL))
277 mpLbTree->Invalidate();
279 bool bSelectedEntry = false;
281 if ( nPos != -1 )
283 OUString aStrMark = aStrURL.copy(nPos+1);
284 bSelectedEntry = SelectEntry(aStrMark);
287 if (!bSelectedEntry)
288 RestoreLastSelection();
290 LeaveWait();
293 // get links from document
294 bool SvxHlinkDlgMarkWnd::RefreshFromDoc(const OUString& aURL)
296 mnError = LERR_NOERROR;
298 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( ::comphelper::getProcessComponentContext() );
299 uno::Reference< lang::XComponent > xComp;
301 if( !aURL.isEmpty() )
303 // load from url
304 uno::Reference< frame::XComponentLoader > xLoader( xDesktop, uno::UNO_QUERY );
305 if( xLoader.is() )
309 uno::Sequence< beans::PropertyValue > aArg(1);
310 aArg.getArray()[0].Name = "Hidden";
311 aArg.getArray()[0].Value <<= true;
312 xComp = xLoader->loadComponentFromURL( aURL, "_blank", 0, aArg );
314 catch( const io::IOException& )
318 catch( const lang::IllegalArgumentException& )
324 else
326 // the component with user focus ( current document )
327 xComp = xDesktop->getCurrentComponent();
330 if( xComp.is() )
332 uno::Reference< document::XLinkTargetSupplier > xLTS( xComp, uno::UNO_QUERY );
334 if( xLTS.is() )
336 if( FillTree( xLTS->getLinks() ) == 0 )
337 mnError = LERR_NOENTRIES;
339 else
340 mnError = LERR_DOCNOTOPEN;
342 if ( !aURL.isEmpty() )
343 xComp->dispose();
345 else
347 if( !aURL.isEmpty() )
348 mnError=LERR_DOCNOTOPEN;
350 return (mnError==0);
353 // Fill Tree-Control
354 int SvxHlinkDlgMarkWnd::FillTree( const uno::Reference< container::XNameAccess >& xLinks, SvTreeListEntry* pParentEntry )
356 int nEntries=0;
357 const uno::Sequence< OUString > aNames( xLinks->getElementNames() );
358 const sal_uLong nLinks = aNames.getLength();
359 const OUString* pNames = aNames.getConstArray();
361 const OUString aProp_LinkDisplayName( "LinkDisplayName" );
362 const OUString aProp_LinkTarget( "com.sun.star.document.LinkTarget" );
363 const OUString aProp_LinkDisplayBitmap( "LinkDisplayBitmap" );
364 for( sal_uLong i = 0; i < nLinks; i++ )
366 uno::Any aAny;
367 OUString aLink( *pNames++ );
369 bool bError = false;
372 aAny = xLinks->getByName( aLink );
374 catch(const uno::Exception&)
376 // if the name of the target was invalid (like empty headings)
377 // no object can be provided
378 bError = true;
380 if(bError)
381 continue;
383 uno::Reference< beans::XPropertySet > xTarget;
385 if( aAny >>= xTarget )
389 // get name to display
390 aAny = xTarget->getPropertyValue( aProp_LinkDisplayName );
391 OUString aDisplayName;
392 aAny >>= aDisplayName;
393 OUString aStrDisplayname ( aDisplayName );
395 // is it a target ?
396 uno::Reference< lang::XServiceInfo > xSI( xTarget, uno::UNO_QUERY );
397 bool bIsTarget = xSI->supportsService( aProp_LinkTarget );
399 // create userdata
400 TargetData *pData = new TargetData ( aLink, bIsTarget );
402 SvTreeListEntry* pEntry;
406 // get bitmap for the tree-entry
407 uno::Reference< awt::XBitmap >
408 aXBitmap( xTarget->getPropertyValue( aProp_LinkDisplayBitmap ), uno::UNO_QUERY );
409 if( aXBitmap.is() )
411 Image aBmp(BitmapEx(VCLUnoHelper::GetBitmap(aXBitmap).GetBitmap(), /*mask*/COL_LIGHTMAGENTA));
412 // insert Displayname into treelist with bitmaps
413 pEntry = mpLbTree->InsertEntry ( aStrDisplayname,
414 aBmp, aBmp,
415 pParentEntry,
416 false, TREELIST_APPEND,
417 static_cast<void*>(pData) );
418 nEntries++;
420 else
422 // insert Displayname into treelist without bitmaps
423 pEntry = mpLbTree->InsertEntry ( aStrDisplayname,
424 pParentEntry,
425 false, TREELIST_APPEND,
426 static_cast<void*>(pData) );
427 nEntries++;
430 catch(const css::uno::Exception&)
432 // insert Displayname into treelist without bitmaps
433 pEntry = mpLbTree->InsertEntry ( aStrDisplayname,
434 pParentEntry,
435 false, TREELIST_APPEND,
436 static_cast<void*>(pData) );
437 nEntries++;
440 uno::Reference< document::XLinkTargetSupplier > xLTS( xTarget, uno::UNO_QUERY );
441 if( xLTS.is() )
442 nEntries += FillTree( xLTS->getLinks(), pEntry );
444 catch(const css::uno::Exception&)
450 return nEntries;
453 // Clear Tree
454 void SvxHlinkDlgMarkWnd::ClearTree()
456 SvTreeListEntry* pEntry = mpLbTree->First();
458 while ( pEntry )
460 TargetData* pUserData = static_cast<TargetData *>(pEntry->GetUserData());
461 delete pUserData;
463 pEntry = mpLbTree->Next( pEntry );
466 mpLbTree->Clear();
469 // Find Entry for String
470 SvTreeListEntry* SvxHlinkDlgMarkWnd::FindEntry (const OUString& aStrName)
472 bool bFound=false;
473 SvTreeListEntry* pEntry = mpLbTree->First();
475 while ( pEntry && !bFound )
477 TargetData* pUserData = static_cast<TargetData *>(pEntry->GetUserData ());
478 if (aStrName == pUserData->aUStrLinkname)
479 bFound = true;
480 else
481 pEntry = mpLbTree->Next( pEntry );
484 return pEntry;
487 // Select Entry
488 bool SvxHlinkDlgMarkWnd::SelectEntry(const OUString& aStrMark)
490 SvTreeListEntry* pEntry = FindEntry(aStrMark);
491 if (!pEntry)
492 return false;
493 mpLbTree->Select(pEntry);
494 mpLbTree->MakeVisible (pEntry);
495 return true;
498 // Click on Apply-Button / Double-click on item in tree
499 IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, DoubleClickApplyHdl_Impl, SvTreeListBox*, bool)
501 ClickApplyHdl_Impl(nullptr);
502 return false;
505 IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl, Button*, void)
507 SvTreeListEntry* pEntry = mpLbTree->GetCurEntry();
509 if ( pEntry )
511 TargetData *pData = static_cast<TargetData *>(pEntry->GetUserData());
513 if ( pData->bIsTarget )
515 mpParent->SetMarkStr(pData->aUStrLinkname);
520 // Click on Close-Button
521 IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl, Button*, void)
523 SvTreeListEntry* pEntry = mpLbTree->GetCurEntry();
524 if ( pEntry )
526 TargetData* pUserData = static_cast<TargetData *>(pEntry->GetUserData());
527 OUString sLastSelectedMark = pUserData->aUStrLinkname;
529 std::deque<OUString> aLastSelectedPath;
530 if (pEntry)
532 //If the bottommost entry is expanded but nothing
533 //underneath it is selected leave a dummy entry
534 if (mpLbTree->IsExpanded(pEntry))
535 aLastSelectedPath.push_front(OUString());
536 while (pEntry)
538 aLastSelectedPath.push_front(mpLbTree->GetEntryText(pEntry));
539 pEntry = mpLbTree->GetParent(pEntry);
543 uno::Sequence< beans::NamedValue > aSettings
545 { TG_SETTING_LASTMARK, css::uno::Any(sLastSelectedMark) },
546 { TG_SETTING_LASTPATH, css::uno::Any(comphelper::containerToSequence(aLastSelectedPath)) }
549 // write
550 SvtViewOptions aViewSettings( EViewType::Dialog, TG_SETTING_MANAGER );
551 aViewSettings.SetUserData( aSettings );
554 Close();
557 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */