Skip to content

Commit

Permalink
Merge pull request #52 from TDT4290-group-4/48-make-sidebar-more-intu…
Browse files Browse the repository at this point in the history
…itive

48 make sidebar more intuitive
  • Loading branch information
kleinc authored Nov 3, 2025
2 parents c138179 + 1d5c5de commit 0016d6d
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 45 deletions.
87 changes: 57 additions & 30 deletions src/AnnotationControl/annotationPanel.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ img.button-icon[src$='/annotation.svg'] {
padding: 8px;
border-radius: 4px;
border: 1px solid #404a50;
background: #2f383d;
color: #cfd5d8;
background: #636262;
color: #636262;
font-family: inherit;
font-size: 12px;
line-height: 1.3;
Expand All @@ -44,10 +44,6 @@ img.button-icon[src$='/annotation.svg'] {
margin-top: 6px;
}

.annotation-add-button {
margin: 10px 0;
}

.annotation-empty {
opacity: 0.6;
padding: 10px;
Expand Down Expand Up @@ -350,37 +346,68 @@ img.button-icon[src$='/annotation.svg'] {
flex: 0 0 18px;
}

.pv-menu-list_annotations-panel {
display: flex;
flex-direction: column;
align-items: center;
overflow: hidden;
}

/* Add button */
.annotation-add-button {
background: linear-gradient(180deg, #f6f6f6 0%, #e9e9e9 100%);
color: #222;
padding: 8px 16px;
min-width: 140px;
height: 38px;
display: block;
margin: 12px auto;
border-radius: 6px;
width: 80%;
margin: 20px 0 10px;
padding: 10px 10px;
font-size: 13px;
font-weight: 700;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.6) inset;
border: 1px solid #cfcfcf;
font-weight: 500;
background-color: #636262;
color: #ffffff;
border: 1px solid #555;
border-radius: 4px;
cursor: pointer;
text-align: center;
}
.annotation-add-button .add-label {
color: #222;
font-weight: 700;
transition:
background-color 0.2s ease,
transform 0.1s ease;
}

.annotation-add-button:hover {
background: linear-gradient(180deg, #f3f3f3 0%, #e2e2e2 100%);
border-color: #bfbfbf;
background-color: #8f8f8f;
}
.annotation-add-button:active {
transform: translateY(1px);
background: linear-gradient(180deg, #e9e9e9 0%, #dbdbdb 100%);
box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.06);

#labelToggleContainer {
margin: 8px 0 6px;
padding-left: 4px;
}
.annotation-add-button:focus {
outline: 2px solid rgba(100, 100, 100, 0.12);
outline-offset: 2px;
#labelToggleContainer .labels-legend {
font-size: 13px;
color: #ddd;
margin-bottom: 4px;
}

.toggle-group {
display: flex;
width: 265px;
border: 1px solid black;
border-radius: 4px;
overflow: hidden;
}
.toggle-group button {
flex: 1;
padding: 6px 15px;
background: #a7a9aa;
color: #3d3c3c;
border: 0;
cursor: pointer;
font-weight: 300;
transition: background 0.2s;
}

.toggle-group button:not(:last-child) {
border-right: 1px solid #555;
}

.toggle-group button.active {
background: #c7c9ca;
color: #000;
}
55 changes: 54 additions & 1 deletion src/AnnotationControl/annotationPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function initAnnotationsPanel(viewer) {
header.appendChild(headerSpan)

const panel = document.createElement('div')
panel.className = 'pv-menu-list annotations-panel'
panel.className = 'pv-menu-list_annotations-panel'

const listContainerDiv = document.createElement('div')
listContainerDiv.id = 'annotations_list'
Expand Down Expand Up @@ -68,6 +68,47 @@ export function initAnnotationsPanel(viewer) {
targetContainer = panel.querySelector('#annotations_list')
}
}

// --- Add Show/Hide labels toggle group ---
const panelEl =
targetContainer.closest('.pv-menu-list_annotations-panel') ||
targetContainer.parentElement

if (!panelEl.querySelector('#labelToggleContainer')) {
const controls = document.createElement('div')
controls.id = 'labelToggleContainer'
controls.innerHTML = `
<p class="labels-legend">Show/Hide saved locations</p>
<div class="toggle-group">
<button id="showLabelsBtn" class="active">Show</button>
<button id="hideLabelsBtn">Hide</button>
</div>
`
// Insert before list of annotations
panelEl.insertBefore(controls, targetContainer)

// show/hide all annotations
const setLabelsVisible = (visible) => {
const cont = document.getElementById('potree_annotation_container')
if (cont) cont.style.display = visible ? '' : 'none'
}

const showBtn = controls.querySelector('#showLabelsBtn')
const hideBtn = controls.querySelector('#hideLabelsBtn')

showBtn.addEventListener('click', () => {
setLabelsVisible(true)
showBtn.classList.add('active')
hideBtn.classList.remove('active')
})

hideBtn.addEventListener('click', () => {
setLabelsVisible(false)
hideBtn.classList.add('active')
showBtn.classList.remove('active')
})
}

if (!targetContainer) {
console.warn(
'Annotations list container not found and dynamic injection failed'
Expand Down Expand Up @@ -947,6 +988,18 @@ export function initAnnotationsPanel(viewer) {
annotationHeader.nextElementSibling.style.display = ''
}
}
// Ensure annotation labels are shown when starting to add a location.
// The "Show" button will be shown as active and reveals Potree's annotation container.
try {
const showBtn = document.getElementById('showLabelsBtn')
const hideBtn = document.getElementById('hideLabelsBtn')
if (showBtn) showBtn.classList.add('active')
if (hideBtn) hideBtn.classList.remove('active')
const cont = document.getElementById('potree_annotation_container')
if (cont) cont.style.display = ''
} catch (e) {
console.warn('Could not enable annotation labels on add', e)
}
// Capture current camera view (position) at the moment the user clicks Add
let camPos = null
try {
Expand Down
25 changes: 18 additions & 7 deletions src/Filter/filter.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#doAcceptedFiltering {
display: flex;
width: 100%;
justify-content: center;
margin: 6px 0 10px;
padding: 10px 10px;
font-size: 13px;
Expand Down Expand Up @@ -102,22 +103,32 @@
align-items: center;
margin: 3px 0;
font-size: 13px;
color: #ddd; /* visible text */
color: #ddd;
}

/* Color boxes */
/* Color boxes → now circles */
#accepted_legend .legend-color {
width: 16px;
height: 16px;
border: 1px solid #777;
margin-right: 8px;
border-radius: 2px;
width: 20px;
height: 8px;
border-radius: 4px; /* pill shape */
margin-left: 6px;
}

#accepted_legend .legend-color.accepted {
background-color: #fff;
border: #0008;
box-shadow: 0 0 4px 1px #fff8;
}

#accepted_legend .legend-color.not-accepted {
background-color: #000;
box-shadow: 0 0 4px 1px #fff8;
}

#gradient_repeat_option fieldset {
margin: 15px 0px 12px 0px !important;
}

#gradient_repeat_option fieldset legend {
margin: 0px 0px 5px 0px !important;
}
12 changes: 10 additions & 2 deletions src/Filter/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ function ensureElevationButton(hooks) {
btn.type = 'button'
btn.textContent = 'Activate elevation control'
btn.addEventListener('click', () => {
const elevBtn = byId('btnDoElevationControl')
const accBtn = byId('doAcceptedFiltering')
if (elevBtn) elevBtn.style.display = 'none'
if (accBtn) accBtn.style.display = ''
switchMode('elevation', hooks?.onActivateElevation, hooks)
})
btns.appendChild(btn)
Expand Down Expand Up @@ -283,6 +287,10 @@ function ensureAcceptedButton(hooks) {
btn.type = 'button'
btn.textContent = 'Activate accepted filter'
btn.addEventListener('click', () => {
const accBtn = byId('doAcceptedFiltering')
const elevBtn = byId('btnDoElevationControl')
if (accBtn) accBtn.style.display = 'none'
if (elevBtn) elevBtn.style.display = ''
switchMode('accepted', hooks?.onActivateAccepted, hooks)
})
btns.appendChild(btn)
Expand All @@ -303,12 +311,12 @@ function ensureAcceptedLegend() {
legend.style.display = 'none'
legend.innerHTML = `
<div class="legend-row">
<span>Accepted points displayed as: </span>
<div class="legend-color accepted"></div>
<span>Accepted points</span>
</div>
<div class="legend-row">
<span>Not accepted points displayed as: </span>
<div class="legend-color not-accepted"></div>
<span>Not accepted points</span>
</div>
`
list.appendChild(legend)
Expand Down
29 changes: 29 additions & 0 deletions src/MeasurementControl/measurementsPanel.css
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,32 @@
border-top: 1px solid #303a3f;
padding-top: 10px;
}

.tool-with-label {
display: flex;
flex-direction: row;
align-items: center;
margin-top: 10px;
cursor: pointer;
border-radius: 4px;
padding: 4px;
}
.tool-with-label:hover {
box-shadow: 0 0 5px #fff8;
}

.tool-with-label:hover img {
filter: brightness(1.7);
}

.tool-with-label:hover .tool-label {
color: #fff;
}

.tool-label {
font-size: 14px;
margin-top: 2px;
margin-left: 4px;
color: #aaa;
pointer-events: none;
}
41 changes: 40 additions & 1 deletion src/MeasurementControl/measurementsPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function initMeasurementsPanel(viewer) {
panel.appendChild(toolsHostDiv)
panel.appendChild(listContainerDiv)
// Insert before filters/tools if possible, else append at end
const tools = document.getElementById('menu_tools')
const tools = document.getElementById('menu_appearance')
if (tools) {
menu.insertBefore(panel, tools)
menu.insertBefore(header, panel)
Expand Down Expand Up @@ -650,6 +650,45 @@ export function initMeasurementsPanel(viewer) {
toolsHost.appendChild(existingTools)
}

// After tools are moved into `toolsHost`
const toolDescriptions = {
'angle.png': 'Measure angle',
'point.svg': 'Inspect point',
'distance.svg': 'Measure distance',
'height.svg': 'Measure height',
'circle.svg': 'Circle',
'azimuth.svg': 'Azimuth',
'area.svg': 'Area',
'volume.svg': 'Volume',
'sphere_distances.svg': 'Sphere volume',
'profile.svg': '2D height profile',
'reset_tools.svg': 'Remove all'
}

const toolIcons = existingTools.querySelectorAll('img')
toolIcons.forEach((img) => {
const src = img.getAttribute('src')
const file = src.split('/').pop() // extract icon name
const baseName = file.replace(/\.[^/.]+$/, '')

if (toolDescriptions[file]) {
const wrapper = document.createElement('div')
wrapper.className = 'tool-with-label'
wrapper.id = `tool-wrapper-${baseName}`

wrapper.addEventListener('click', () => img.click())

img.parentNode.insertBefore(wrapper, img)
wrapper.appendChild(img)

const label = document.createElement('span')
label.className = 'tool-label'
label.textContent = toolDescriptions[file]
label.id = `label-${file.replace(/\.[^/.]+$/, '')}`
wrapper.appendChild(label)
}
})

// Move measurement options UI into our tools host
if (toolsHost) {
const measOptions = document.getElementById('measurement_options_show')
Expand Down
5 changes: 1 addition & 4 deletions src/potreeViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,7 @@ export async function createPotreeViewer(

viewer.loadGUI(() => {
viewer.setLanguage('en')
$('#menu_appearance').next().show()
$('#menu_tools').next().show()
$('#menu_scene').next().show()
$('#menu_filters').next().show()
$('#menu_filters').remove()
viewer.toggleSidebar()

// Store the last used elevation gradient
Expand Down

0 comments on commit 0016d6d

Please sign in to comment.