Skip to content
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
59a040e
feat(ContextMenu): New multiple context menu system
SpliiT May 18, 2026
f65c0df
Adaptative background
SpliiT May 18, 2026
c346207
test adapt
SpliiT May 18, 2026
443dee0
card order labels
SpliiT May 19, 2026
4866d3e
clean code
SpliiT May 19, 2026
9031ff5
Apply prepare changes
SpliiT May 19, 2026
3d5f541
oxcgo
SpliiT May 19, 2026
f962cdb
split responsabilities
SpliiT May 19, 2026
7182428
Apply prepare changes
SpliiT May 19, 2026
a8c95a9
rm useless ref
SpliiT May 19, 2026
34d041d
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
SpliiT May 19, 2026
cc67efa
rm useless imports
SpliiT May 19, 2026
7c8bde4
Apply prepare changes
SpliiT May 19, 2026
73583a2
isOverToolbar
SpliiT May 19, 2026
a3857f1
Merge branch 'feat/SelectMenu' of https://github.com/Geode-solutions/…
SpliiT May 19, 2026
999e1ee
oxlint
SpliiT May 19, 2026
3f3aded
Apply prepare changes
SpliiT May 19, 2026
7c1bc45
color button
SpliiT May 19, 2026
c4fcff4
Merge branch 'feat/SelectMenu' of https://github.com/Geode-solutions/…
SpliiT May 19, 2026
6f8d4ef
oxc fix
SpliiT May 19, 2026
437af35
center button
SpliiT May 19, 2026
1c0e474
name troncate
SpliiT May 19, 2026
3f55026
Apply prepare changes
SpliiT May 19, 2026
a2932c1
opacity
SpliiT May 20, 2026
5b19ee5
Merge branch 'feat/SelectMenu' of https://github.com/Geode-solutions/…
SpliiT May 20, 2026
7be4dec
Apply prepare changes
SpliiT May 20, 2026
ed07f72
rename
SpliiT May 20, 2026
377c7e6
Merge branch 'feat/SelectMenu' of https://github.com/Geode-solutions/…
SpliiT May 20, 2026
52d39df
fix projects
SpliiT May 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/components/ViewToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ const camera_options = computed(() => [
</script>

<template>
<v-container :class="[$style.floatToolbar, 'pa-0']" width="auto">
<v-container :class="[$style.floatToolbar, 'pa-0', 'view-toolbar']" width="auto">
<v-row v-for="camera_option in camera_options" :key="camera_option.icon" dense>
<v-col>
<v-menu v-if="camera_option.menu" location="start" :close-on-content-click="false">
Expand Down
119 changes: 119 additions & 0 deletions app/components/Viewer/ContextMenu/CenterButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<script setup>
import { useAdaptiveStyles } from "@ogw_front/composables/use_adaptive_styles";
import { useMenuStore } from "@ogw_front/stores/menu";

const { isOverTreeview, isOverToolbar } = defineProps({
isOverTreeview: { type: Boolean, required: true },
isOverToolbar: { type: Boolean, default: false },
});

const emit = defineEmits(["drag", "click"]);

const ADAPTIVE_BLUR_VAL = "15px";
const ADAPTIVE_OPACITY_VAL = 0.85;
const ADAPTIVE_BRIGHTNESS_VAL = 1.15;
const dragThreshold = 3;

const menuStore = useMenuStore();

const centerButtonCoords = computed(() => {
const size = 52;
return {
x: menuStore.containerLeft + menuStore.menuX - size / 2,
y: menuStore.containerTop + menuStore.menuY - size / 2,
width: size,
height: size,
};
});

const { adaptiveStyles } = useAdaptiveStyles(centerButtonCoords, {
minOpacity: 0.15,
maxOpacity: 1,
});

const computedItemStyles = computed(() => {
if (isOverTreeview || isOverToolbar) {
return {
"--adaptive-blur": ADAPTIVE_BLUR_VAL,
"--adaptive-opacity": ADAPTIVE_OPACITY_VAL,
"--adaptive-brightness": ADAPTIVE_BRIGHTNESS_VAL,
};
}
return adaptiveStyles.value;
});

let dragMoved = false;
let dragStartClientX = 0;
let dragStartClientY = 0;

function onMouseDown(event) {
dragMoved = false;
dragStartClientX = event.clientX;
dragStartClientY = event.clientY;
emit("drag", event);
}

function onMouseUp(event) {
const deltaX = event.clientX - dragStartClientX;
const deltaY = event.clientY - dragStartClientY;
if (Math.hypot(deltaX, deltaY) > dragThreshold) {
dragMoved = true;
}
}

function onCenterClick(event) {
event.stopPropagation();
if (!dragMoved) {
emit("click", event);
}
}
</script>

<template>
<v-btn
icon
variant="outlined"
class="central-selector-btn elevation-6"
style="width: 52px; height: 52px; z-index: 5"
:style="computedItemStyles"
@mousedown="onMouseDown"
@mouseup="onMouseUp"
@click.stop="onCenterClick"
>
<v-icon icon="mdi-information-outline" size="28" color="primary" style="pointer-events: none" />
</v-btn>
</template>

<style scoped>
.central-selector-btn {
background: transparent !important;
border: 2px solid rgba(var(--v-theme-primary), 0.35) !important;
position: relative;
overflow: hidden;
transition: all 0.2s ease;
}

.central-selector-btn::before {
content: "";
position: absolute;
inset: 0;
background: rgba(255, 255, 255, var(--adaptive-opacity));
backdrop-filter: blur(var(--adaptive-blur)) brightness(var(--adaptive-brightness));
-webkit-backdrop-filter: blur(var(--adaptive-blur)) brightness(var(--adaptive-brightness));
z-index: 0;
pointer-events: none;
border-radius: inherit;
transition:
background-color 0.2s ease,
backdrop-filter 0.2s ease;
}

.central-selector-btn:hover {
transform: scale(1.08);
border-color: rgba(var(--v-theme-primary), 0.85) !important;
}

.central-selector-btn:hover::before {
background: rgba(255, 255, 255, calc(var(--adaptive-opacity, 0.15) + 0.15));
}
</style>
86 changes: 86 additions & 0 deletions app/components/Viewer/ContextMenu/CircularItems.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<script setup>
import { useMenuStore } from "@ogw_front/stores/menu";

const { menuItems, id, metaData, menuItemCount } = defineProps({
menuItems: { type: Array, required: true },
id: { type: String, required: true },
metaData: { type: Object, required: true },
menuItemCount: { type: Number, required: true },
});

const RADIUS = 80;
const Z_INDEX_ACTIVE_ITEM = 10;
const Z_INDEX_BASE_ITEM = 1;
const FULL_ANGLE = 360;
const ANGLE_45 = 45;
const ANGLE_135 = 135;
const ANGLE_225 = 225;
const ANGLE_315 = 315;

const menuStore = useMenuStore();

function getItemStyle(index) {
const angle = (index / menuItemCount) * 2 * Math.PI;
return {
transform: `translate(${Math.cos(angle) * RADIUS}px, ${Math.sin(angle) * RADIUS}px)`,
transition: "opacity 0.2s ease, transform 0.2s ease",
position: "absolute",
zIndex: menuStore.active_item_index === index ? Z_INDEX_ACTIVE_ITEM : Z_INDEX_BASE_ITEM,
};
}

function getTooltipLocation(index) {
const angle = (index / menuItemCount) * FULL_ANGLE;
if (angle < ANGLE_45 || angle >= ANGLE_315) {
return "right";
}
if (angle >= ANGLE_45 && angle < ANGLE_135) {
return "top";
}
if (angle >= ANGLE_135 && angle < ANGLE_225) {
return "left";
}
return "bottom";
}

function getTooltipOrigin(index) {
const angle = (index / menuItemCount) * FULL_ANGLE;
if (angle < ANGLE_45 || angle >= ANGLE_315) {
return "left";
}
if (angle >= ANGLE_45 && angle < ANGLE_135) {
return "bottom";
}
if (angle >= ANGLE_135 && angle < ANGLE_225) {
return "right";
}
return "top";
}
</script>

<template>
<component
v-for="(item, index) in menuItems"
:is="item"
:key="index"
:index="index"
:itemProps="{
id: id,
meta_data: metaData,
tooltip_location: getTooltipLocation(index),
tooltip_origin: getTooltipOrigin(index),
totalItems: menuItemCount,
}"
class="menu-item-wrapper"
:style="getItemStyle(index)"
@mousedown.stop
/>
</template>

<style scoped>
.menu-item-wrapper {
position: absolute;
transform-origin: center;
will-change: transform, opacity;
}
</style>
Loading
Loading