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/.
10 #include <tools/urlobj.hxx>
11 #include <vcl/svapp.hxx>
12 #include "breadcrumb.hxx"
14 Breadcrumb::Breadcrumb(weld::Container
* pParent
)
16 , m_nMaxWidth(m_pParent
->get_preferred_size().Width())
18 m_pParent
->connect_size_allocate(LINK(this, Breadcrumb
, SizeAllocHdl
));
19 m_eMode
= SvtBreadcrumbMode::ONLY_CURRENT_PATH
;
20 appendField(); // root
23 IMPL_LINK(Breadcrumb
, SizeAllocHdl
, const Size
&, rSize
, void)
25 m_nMaxWidth
= rSize
.Width();
28 Breadcrumb::~Breadcrumb()
30 m_pParent
->connect_size_allocate(Link
<const Size
&, void>());
33 void Breadcrumb::EnableFields( bool bEnable
)
37 INetURLObject
aURL( m_aCurrentURL
);
38 int nSegments
= aURL
.getSegmentCount();
39 m_aSegments
[nSegments
]->m_xLink
->set_sensitive(false);
43 void Breadcrumb::connect_clicked( const Link
<Breadcrumb
*,bool>& rLink
)
48 const OUString
& Breadcrumb::GetHdlURL() const
53 void Breadcrumb::SetRootName( const OUString
& rURL
)
57 // we changed root - clear all fields
58 for (size_t i
= 1; i
< m_aSegments
.size(); ++i
)
60 m_aSegments
[i
]->m_xLink
->set_label("");
62 m_aSegments
[i
]->m_xLink
->hide();
63 m_aSegments
[i
]->m_xSeparator
->hide();
64 m_aSegments
[i
]->m_xLink
->set_sensitive(true);
68 void Breadcrumb::SetURL( const OUString
& rURL
)
71 INetURLObject
aURL(rURL
);
74 bool bClear
= m_eMode
== SvtBreadcrumbMode::ONLY_CURRENT_PATH
;
76 int nSegments
= aURL
.getSegmentCount();
78 size_t nVecSizeRequired
= nSegments
+ 1;
80 while (m_aSegments
.size() < nVecSizeRequired
)
83 // fill the fields under root
84 for (int i
= nSegments
; i
; --i
)
86 OUString sLabel
= aURL
.getName(INetURLObject::LAST_SEGMENT
, true, INetURLObject::DecodeMechanism::WithCharset
);
87 OUString sLink
= aURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
);
89 if (m_eMode
== SvtBreadcrumbMode::ALL_VISITED
)
91 if( m_aSegments
[i
]->m_xLink
->get_label() != sLabel
)
95 m_aSegments
[i
]->m_xLink
->hide();
96 m_aSegments
[i
]->m_xLink
->set_label(sLabel
);
97 m_aSegments
[i
]->m_xLink
->set_sensitive(true);
98 m_aSegments
[i
]->m_xLink
->set_uri(sLink
);
99 m_aUris
[m_aSegments
[i
]->m_xLink
.get()] = sLink
;
101 m_aSegments
[i
]->m_xSeparator
->hide();
103 aURL
.removeSegment();
106 OUString sRootPath
= aURL
.GetMainURL(INetURLObject::DecodeMechanism::WithCharset
);
109 m_aSegments
[0]->m_xLink
->set_label( m_sRootName
);
110 m_aSegments
[0]->m_xLink
->set_sensitive(true);
111 m_aSegments
[0]->m_xLink
->set_uri(sRootPath
);
112 m_aUris
[m_aSegments
[0]->m_xLink
.get()] = sRootPath
;
114 // clear unused fields
115 for (size_t i
= nSegments
+ 1; i
< m_aSegments
.size(); i
++ )
118 m_aSegments
[i
]->m_xLink
->set_label( "" );
120 m_aSegments
[i
]->m_xLink
->hide();
121 m_aSegments
[i
]->m_xSeparator
->hide();
122 m_aSegments
[i
]->m_xLink
->set_sensitive(true);
126 unsigned int nSeparatorWidth
= m_aSegments
[0]->m_xSeparator
->get_preferred_size().Width();
127 unsigned int nCurrentWidth
= 0;
128 unsigned int nLastVisible
= nSegments
;
130 bool bRight
= ( m_eMode
== SvtBreadcrumbMode::ALL_VISITED
);
135 while( bLeft
|| bRight
)
137 if( nSegments
- i
== -1 )
142 unsigned int nIndex
= nSegments
- i
;
144 if( showField( nIndex
, m_nMaxWidth
- nCurrentWidth
) )
146 nCurrentWidth
+= m_aSegments
[nIndex
]->m_xLink
->get_preferred_size().Width()
147 + nSeparatorWidth
+ 2*SPACING
;
154 m_aSegments
[0]->m_xLink
->set_label("...");
155 m_aSegments
[0]->m_xLink
->set_sensitive(false);
161 if( nSegments
+ i
== static_cast<int>(m_aSegments
.size()) )
164 if( i
!= 0 && bRight
)
166 unsigned int nIndex
= nSegments
+ i
;
168 if( m_aSegments
[nIndex
]->m_xLink
->get_label().isEmpty() )
172 else if( showField( nIndex
, m_nMaxWidth
- nCurrentWidth
) )
174 nCurrentWidth
+= m_aSegments
[nIndex
]->m_xLink
->get_preferred_size().Width()
175 + nSeparatorWidth
+ 3*SPACING
;
176 nLastVisible
= nIndex
;
187 // current dir should be inactive
188 m_aSegments
[nSegments
]->m_xLink
->set_sensitive(false);
190 // hide last separator
191 m_aSegments
[nLastVisible
]->m_xSeparator
->hide();
194 void Breadcrumb::SetMode( SvtBreadcrumbMode eMode
)
199 void Breadcrumb::appendField()
201 m_aSegments
.emplace_back(std::make_unique
<BreadcrumbPath
>(m_pParent
));
202 size_t nIndex
= m_aSegments
.size() - 1;
203 m_aSegments
[nIndex
]->m_xLink
->hide();
204 m_aSegments
[nIndex
]->m_xLink
->connect_activate_link(LINK(this, Breadcrumb
, ClickLinkHdl
));
205 m_aSegments
[nIndex
]->m_xSeparator
->set_label( ">" );
206 m_aSegments
[nIndex
]->m_xSeparator
->hide();
209 bool Breadcrumb::showField( unsigned int nIndex
, unsigned int nWidthMax
)
211 m_aSegments
[nIndex
]->m_xLink
->show();
212 m_aSegments
[nIndex
]->m_xSeparator
->show();
214 unsigned int nSeparatorWidth
= m_aSegments
[0]->m_xSeparator
->get_preferred_size().Width();
215 unsigned int nWidth
= m_aSegments
[nIndex
]->m_xLink
->get_preferred_size().Width()
216 + nSeparatorWidth
+ 3*SPACING
;
218 if( nWidth
> nWidthMax
)
222 m_aSegments
[nIndex
]->m_xLink
->hide();
223 m_aSegments
[nIndex
]->m_xSeparator
->hide();
232 IMPL_LINK(Breadcrumb
, ClickLinkHdl
, weld::LinkButton
&, rLink
, bool)
234 m_sClickedURL
= m_aUris
[&rLink
];
235 return m_aClickHdl
.Call(this);
238 BreadcrumbPath::BreadcrumbPath(weld::Container
* pContainer
)
239 : m_xBuilder(Application::CreateBuilder(pContainer
, "fps/ui/breadcrumb.ui"))
240 , m_xContainer(m_xBuilder
->weld_container("container"))
241 , m_xLink(m_xBuilder
->weld_link_button("link"))
242 , m_xSeparator(m_xBuilder
->weld_label("label"))
246 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */