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
);
73 //prepare the Host port
78 sHostPort
+= ":" + OUString::number( aURL
.GetPort() );
81 OUString sUser
= aURL
.GetUser( INetURLObject::DecodeMechanism::NONE
);
82 OUString sPath
= aURL
.GetURLPath(INetURLObject::DecodeMechanism::WithCharset
);
83 OUString sRootPath
= INetURLObject::GetScheme( aURL
.GetProtocol() )
85 + ( sUser
.isEmpty() ? OUString() : "@" )
89 int nSegments
= aURL
.getSegmentCount();
90 unsigned int nPos
= 0;
92 bool bClear
= ( m_eMode
== SvtBreadcrumbMode::ONLY_CURRENT_PATH
);
95 m_aSegments
[0]->m_xLink
->set_label( m_sRootName
);
96 m_aSegments
[0]->m_xLink
->set_sensitive(true);
97 m_aSegments
[0]->m_xLink
->set_uri(sRootPath
);
98 m_aUris
[m_aSegments
[0]->m_xLink
.get()] = sRootPath
;
100 // fill the other fields
102 for( unsigned int i
= 1; i
< static_cast<unsigned int>(nSegments
) + 1; i
++ )
104 if( i
>= m_aSegments
.size() )
107 unsigned int nEnd
= sPath
.indexOf( '/', nPos
+ 1 );
108 OUString sLabel
= sPath
.copy( nPos
+ 1, nEnd
- nPos
- 1 );
110 if( m_eMode
== SvtBreadcrumbMode::ALL_VISITED
)
112 if( m_aSegments
[i
]->m_xLink
->get_label() != sLabel
)
116 m_aSegments
[i
]->m_xLink
->set_label( sLabel
);
117 m_aUris
[m_aSegments
[i
]->m_xLink
.get()] = sRootPath
+ sPath
.copy(0, nEnd
);
118 m_aSegments
[i
]->m_xLink
->hide();
119 m_aSegments
[i
]->m_xLink
->set_sensitive(true);
121 m_aSegments
[i
]->m_xSeparator
->hide();
126 // clear unused fields
127 for (size_t i
= nSegments
+ 1; i
< m_aSegments
.size(); i
++ )
130 m_aSegments
[i
]->m_xLink
->set_label( "" );
132 m_aSegments
[i
]->m_xLink
->hide();
133 m_aSegments
[i
]->m_xSeparator
->hide();
134 m_aSegments
[i
]->m_xLink
->set_sensitive(true);
138 unsigned int nSeparatorWidth
= m_aSegments
[0]->m_xSeparator
->get_preferred_size().Width();
139 unsigned int nCurrentWidth
= 0;
140 unsigned int nLastVisible
= nSegments
;
142 bool bRight
= ( m_eMode
== SvtBreadcrumbMode::ALL_VISITED
);
147 while( bLeft
|| bRight
)
149 if( nSegments
- i
== -1 )
154 unsigned int nIndex
= nSegments
- i
;
156 if( showField( nIndex
, m_nMaxWidth
- nCurrentWidth
) )
158 nCurrentWidth
+= m_aSegments
[nIndex
]->m_xLink
->get_preferred_size().Width()
159 + nSeparatorWidth
+ 2*SPACING
;
166 m_aSegments
[0]->m_xLink
->set_label("...");
167 m_aSegments
[0]->m_xLink
->set_sensitive(false);
173 if( nSegments
+ i
== static_cast<int>(m_aSegments
.size()) )
176 if( i
!= 0 && bRight
)
178 unsigned int nIndex
= nSegments
+ i
;
180 if( m_aSegments
[nIndex
]->m_xLink
->get_label().isEmpty() )
184 else if( showField( nIndex
, m_nMaxWidth
- nCurrentWidth
) )
186 nCurrentWidth
+= m_aSegments
[nIndex
]->m_xLink
->get_preferred_size().Width()
187 + nSeparatorWidth
+ 3*SPACING
;
188 nLastVisible
= nIndex
;
199 // current dir should be inactive
200 m_aSegments
[nSegments
]->m_xLink
->set_sensitive(false);
202 // hide last separator
203 m_aSegments
[nLastVisible
]->m_xSeparator
->hide();
206 void Breadcrumb::SetMode( SvtBreadcrumbMode eMode
)
211 void Breadcrumb::appendField()
213 m_aSegments
.emplace_back(std::make_unique
<BreadcrumbPath
>(m_pParent
));
214 size_t nIndex
= m_aSegments
.size() - 1;
215 m_aSegments
[nIndex
]->m_xLink
->hide();
216 m_aSegments
[nIndex
]->m_xLink
->connect_activate_link(LINK(this, Breadcrumb
, ClickLinkHdl
));
217 m_aSegments
[nIndex
]->m_xSeparator
->set_label( ">" );
218 m_aSegments
[nIndex
]->m_xSeparator
->hide();
221 bool Breadcrumb::showField( unsigned int nIndex
, unsigned int nWidthMax
)
223 m_aSegments
[nIndex
]->m_xLink
->show();
224 m_aSegments
[nIndex
]->m_xSeparator
->show();
226 unsigned int nSeparatorWidth
= m_aSegments
[0]->m_xSeparator
->get_preferred_size().Width();
227 unsigned int nWidth
= m_aSegments
[nIndex
]->m_xLink
->get_preferred_size().Width()
228 + nSeparatorWidth
+ 3*SPACING
;
230 if( nWidth
> nWidthMax
)
234 m_aSegments
[nIndex
]->m_xLink
->hide();
235 m_aSegments
[nIndex
]->m_xSeparator
->hide();
244 IMPL_LINK(Breadcrumb
, ClickLinkHdl
, weld::LinkButton
&, rLink
, bool)
246 m_sClickedURL
= m_aUris
[&rLink
];
247 return m_aClickHdl
.Call(this);
250 BreadcrumbPath::BreadcrumbPath(weld::Container
* pContainer
)
251 : m_xBuilder(Application::CreateBuilder(pContainer
, "fps/ui/breadcrumb.ui"))
252 , m_xContainer(m_xBuilder
->weld_container("container"))
253 , m_xLink(m_xBuilder
->weld_link_button("link"))
254 , m_xSeparator(m_xBuilder
->weld_label("label"))
258 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */