Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 src/components/widgets/filesystem/FileSystem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ export default class FileSystem extends Mixins(StateMixin, FilesMixin, ServicesM
{
text: this.$tc('app.general.table.header.extruder_colors'),
value: 'extruder_colors',
visible: false,
visible: isNotDashboard,
cellClass: 'text-no-wrap'
},
{
Expand Down
183 changes: 107 additions & 76 deletions src/components/widgets/gcode-preview/GcodePreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
/>
</svg>
<svg
id="extrusionStart"
id="unretraction"
:width="retractionIconSize"
:height="retractionIconSize"
viewBox="0 0 10 10"
Expand Down Expand Up @@ -148,10 +148,12 @@
class="layer"
>
<path
v-for="(extrusion, tool) in svgPathPrevious.extrusions"
:key="tool"
:stroke="themeIsDark ? 'lightgrey' : '#555'"
:stroke-width="extrusionLineWidth"
stroke-opacity="0.6"
:d="svgPathPrevious.extrusions"
:d="extrusion"
:shape-rendering="shapeRendering"
/>
</g>
Expand All @@ -161,24 +163,29 @@
class="layer"
>
<path
v-for="(extrusion, tool) in svgPathActive.extrusions"
:key="tool"
:stroke="themeIsDark ? 'lightgrey' : '#555'"
:stroke-width="extrusionLineWidth"
stroke-opacity="0.6"
:d="svgPathActive.extrusions"
:d="extrusion"
:shape-rendering="shapeRendering"
/>
</g>
<g
id="currentLayer"
class="layer"
>
<path
v-if="showExtrusions"
:d="svgPathCurrent.extrusions"
:stroke="themeIsDark ? 'white' : 'black'"
:stroke-width="extrusionLineWidth"
:shape-rendering="shapeRendering"
/>
<template v-if="showExtrusions">
<path
v-for="(extrusion, tool) in svgPathCurrent.extrusions"
:key="tool"
:d="extrusion"
:stroke="toolColors[tool]"
:stroke-width="extrusionLineWidth"
:shape-rendering="shapeRendering"
/>
</template>
<path
v-if="showMoves"
:d="svgPathCurrent.moves"
Expand Down Expand Up @@ -210,13 +217,13 @@
</g>

<g
v-if="showRetractions && svgPathCurrent.extrusionStarts.length > 0"
id="extrusionStarts"
v-if="showRetractions && svgPathCurrent.unretractions.length > 0"
id="unretractions"
>
<use
v-for="({x, y}, index) of svgPathCurrent.extrusionStarts"
:key="`extrusion-start-${index + 1}`"
xlink:href="#extrusionStart"
v-for="({x, y}, index) of svgPathCurrent.unretractions"
:key="`unretraction-${index + 1}`"
xlink:href="#unretraction"
:x="x - (retractionIconSize / 2)"
:y="flipY ? y : y - retractionIconSize"
/>
Expand All @@ -229,9 +236,11 @@
class="layer"
>
<path
v-for="(extrusion, key) in svgPathNext.extrusions"
:key="key"
stroke="lightgrey"
stroke-opacity="0.6"
:d="svgPathNext.extrusions"
:d="extrusion"
:stroke-width="extrusionLineWidth"
:shape-rendering="shapeRendering"
/>
Expand All @@ -252,61 +261,72 @@
@touchstart="panzoom?.pause()"
@touchend="panzoom?.resume()"
>
<gcode-preview-button
v-model="followProgress"
icon="$play"
:tooltip="$t('app.gcode.label.follow_progress')"
/>

<gcode-preview-button
v-model="showPreviousLayer"
icon="$previousLayer"
:tooltip="$t('app.gcode.label.show_previous_layer')"
/>

<gcode-preview-button
v-model="showCurrentLayer"
icon="$currentLayer"
:tooltip="$t('app.gcode.label.show_current_layer')"
/>

<gcode-preview-button
v-model="showNextLayer"
icon="$nextLayer"
:tooltip="$t('app.gcode.label.show_next_layer')"
/>

<gcode-preview-button
v-model="showMoves"
icon="$moves"
:tooltip="$t('app.gcode.label.show_moves')"
/>

<gcode-preview-button
v-model="showExtrusions"
icon="$extrusions"
:tooltip="$t('app.gcode.label.show_extrusions')"
/>

<gcode-preview-button
v-model="showRetractions"
icon="$retractions"
:tooltip="$t('app.gcode.label.show_retractions')"
/>

<gcode-preview-button
v-model="showParts"
icon="$parts"
:tooltip="$t('app.gcode.label.show_parts')"
/>

<v-btn
icon
small
@click="autoZoom = !autoZoom"
>
<v-icon>{{ autoZoom ? '$magnifyMinus' : '$magnifyPlus' }}</v-icon>
</v-btn>
<div>
<gcode-preview-button
v-model="followProgress"
icon="$play"
:tooltip="$t('app.gcode.label.follow_progress')"
/>

<gcode-preview-button
v-model="showPreviousLayer"
icon="$previousLayer"
:tooltip="$t('app.gcode.label.show_previous_layer')"
/>

<gcode-preview-button
v-model="showCurrentLayer"
icon="$currentLayer"
:tooltip="$t('app.gcode.label.show_current_layer')"
/>

<gcode-preview-button
v-model="showNextLayer"
icon="$nextLayer"
:tooltip="$t('app.gcode.label.show_next_layer')"
/>

<gcode-preview-button
v-model="showMoves"
icon="$moves"
:tooltip="$t('app.gcode.label.show_moves')"
/>

<gcode-preview-button
v-model="showExtrusions"
icon="$extrusions"
:tooltip="$t('app.gcode.label.show_extrusions')"
/>

<gcode-preview-button
v-model="showRetractions"
icon="$retractions"
:tooltip="$t('app.gcode.label.show_retractions')"
/>

<gcode-preview-button
v-model="showParts"
icon="$parts"
:tooltip="$t('app.gcode.label.show_parts')"
/>

<v-btn
icon
small
@click="autoZoom = !autoZoom"
>
<v-icon>{{ autoZoom ? '$magnifyMinus' : '$magnifyPlus' }}</v-icon>
</v-btn>
</div>
<div v-if="tools.length > 0">
<gcode-preview-tool
v-for="(color, tool) in toolColors"
:key="tool"
:tool="tool"
:color="color"
:active="svgPathCurrent.tool === tool"
/>
</div>
</div>
<div
v-if="file"
Expand All @@ -326,13 +346,15 @@ import type { BBox, Layer, LayerNr, LayerPaths } from '@/store/gcodePreview/type
import AppFocusableContainer from '@/components/ui/AppFocusableContainer.vue'
import ExcludeObjects from '@/components/widgets/exclude-objects/ExcludeObjects.vue'
import GcodePreviewButton from './GcodePreviewButton.vue'
import GcodePreviewTool from './GcodePreviewTool.vue'
import type { AppFile, AppFileWithMeta } from '@/store/files/types'
import type { BedSize } from '@/store/printer/types'

@Component({
components: {
ExcludeObjects,
GcodePreviewButton
GcodePreviewButton,
GcodePreviewTool
}
})
export default class GcodePreview extends Mixins(StateMixin, BrowserMixin) {
Expand Down Expand Up @@ -603,14 +625,15 @@ export default class GcodePreview extends Mixins(StateMixin, BrowserMixin) {

get defaultLayerPaths (): LayerPaths {
return {
extrusions: '',
extrusions: {},
moves: '',
retractions: [],
extrusionStarts: [],
unretractions: [],
toolhead: {
x: 0,
y: 0
}
},
tool: 'T0'
}
}

Expand Down Expand Up @@ -660,10 +683,18 @@ export default class GcodePreview extends Mixins(StateMixin, BrowserMixin) {
return this.$typedGetters['gcodePreview/getPartPaths']
}

get file (): AppFile | undefined {
get file (): AppFile | AppFileWithMeta | null {
return this.$typedState.gcodePreview.file
}

get tools (): number[] {
return this.$typedState.gcodePreview.tools
}

get toolColors (): Record<string, string> {
return this.$typedGetters['gcodePreview/getToolColors']
}

get bounds (): BBox {
return this.$typedGetters['gcodePreview/getBounds']
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/widgets/gcode-preview/GcodePreviewCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ export default class GcodePreviewCard extends Mixins(StateMixin, FilesMixin, Bro
}
}

get file (): AppFile | undefined {
get file (): AppFile | AppFileWithMeta | null {
return this.$typedState.gcodePreview.file
}

Expand All @@ -278,7 +278,7 @@ export default class GcodePreviewCard extends Mixins(StateMixin, FilesMixin, Bro
}

get showParserProgressDialog (): boolean {
return this.file !== undefined && this.parserProgress !== this.file.size
return this.file != null && this.parserProgress !== this.file.size
}

get filePosition (): number {
Expand Down Expand Up @@ -355,7 +355,7 @@ export default class GcodePreviewCard extends Mixins(StateMixin, FilesMixin, Bro
}
}

async loadFile (file: AppFile) {
async loadFile (file: AppFile | AppFileWithMeta) {
try {
const response = await this.getGcode(file)

Expand Down
67 changes: 67 additions & 0 deletions src/components/widgets/gcode-preview/GcodePreviewTool.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<template>
<div
class="gcode-preview-tool"
:class="{
active: active
}"
>
<span
class="extruder-color mr-1"
:style="{
background: color
}"
/>
{{ tool }}
</div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import type { Tool } from '@/store/gcodePreview/types'

@Component({})
export default class GcodePreviewTool extends Vue {
@Prop({ type: String, required: true })
readonly tool!: Tool

@Prop({ type: String, required: true })
readonly color!: string

@Prop({ type: Boolean })
readonly active?: boolean
}
</script>

<style lang="scss" scoped>
@import 'vuetify/src/styles/styles.sass';

@include theme(gcode-preview-tool) using ($material) {
.extruder-color {
border-color: map-deep-get($material, 'text', 'primary');
}
}

.gcode-preview-tool {
display: inline-flex;
border: 1px solid transparent;
border-radius: 6px;
align-items: center;
padding: 0 4px;

&.active {
border-color: map-deep-get($material-dark, 'text', 'primary');

& .extruder-color {
border-color: map-deep-get($material-dark, 'text', 'primary');
Comment on lines +52 to +55
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The active state styling uses hardcoded $material-dark theme variables instead of the dynamic $material variable from the @include theme block. This means the border color won't adapt to the current theme (light/dark). Use map-deep-get($material, 'text', 'primary') instead to match the theme-aware styling on line 40.

Suggested change
border-color: map-deep-get($material-dark, 'text', 'primary');
& .extruder-color {
border-color: map-deep-get($material-dark, 'text', 'primary');
border-color: map-deep-get($material, 'text', 'primary');
& .extruder-color {
border-color: map-deep-get($material, 'text', 'primary');

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's for inverted color, so keep as is.

Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .extruder-color border styling within the active state also uses hardcoded $material-dark instead of the dynamic $material variable. This creates inconsistent theming. Use map-deep-get($material, 'text', 'primary') to match the base styling on line 40.

Suggested change
border-color: map-deep-get($material-dark, 'text', 'primary');
border-color: map-deep-get($material, 'text', 'primary');

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's for inverted color, so keep as is.

}
}
Comment on lines +51 to +57
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The active state always uses $material-dark theme colors regardless of current theme. Should use $material variable (line 38-41 pattern) to respect light/dark theme.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's for inverted color, so keep as is.


& .extruder-color {
width: 15px;
height: 15px;
border-width: 1px;
border-style: solid;
border-radius: 50%;
}
}
</style>
Loading