Skip to content

Implement rulers (#306) #385

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 25, 2021
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
19 changes: 18 additions & 1 deletion editor/src/document/document_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,9 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
}
.into(),
);
let root_layerdata = self.layerdata(&[]);

let scale = 0.5 + ASYMPTOTIC_EFFECT + self.layerdata(&[]).scale * SCALE_EFFECT;
let scale = 0.5 + ASYMPTOTIC_EFFECT + root_layerdata.scale * SCALE_EFFECT;
let viewport_size = ipp.viewport_bounds.size();
let viewport_mid = ipp.viewport_bounds.center();
let [bounds1, bounds2] = self.graphene_document.visible_layers_bounding_box().unwrap_or([viewport_mid; 2]);
Expand All @@ -634,6 +635,13 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
let scrollbar_position = DVec2::splat(0.5) - (bounds1.lerp(bounds2, 0.5) - viewport_mid) / (bounds_length - viewport_size);
let scrollbar_multiplier = bounds_length - viewport_size;
let scrollbar_size = viewport_size / bounds_length;

let log = root_layerdata.scale.log2();
let mut ruler_inverval = if log < 0. { 100. * 2_f64.powf(-log.ceil()) } else { 100. / 2_f64.powf(log.ceil()) };
let ruler_spacing = ruler_inverval * root_layerdata.scale;

let ruler_origin = self.graphene_document.root.transform.transform_point2(DVec2::ZERO);

responses.push_back(
FrontendMessage::UpdateScrollbars {
position: scrollbar_position.into(),
Expand All @@ -642,6 +650,15 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
}
.into(),
);

responses.push_back(
FrontendMessage::UpdateRulers {
origin: ruler_origin.into(),
spacing: ruler_spacing,
interval: ruler_inverval,
}
.into(),
);
}

NudgeSelectedLayers(x, y) => {
Expand Down
1 change: 1 addition & 0 deletions editor/src/frontend/frontend_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum FrontendMessage {
UpdateLayer { path: Path, data: LayerPanelEntry },
UpdateCanvas { document: String },
UpdateScrollbars { position: (f64, f64), size: (f64, f64), multiplier: (f64, f64) },
UpdateRulers { origin: (f64, f64), spacing: f64, interval: f64 },
ExportDocument { document: String, name: String },
SaveDocument { document: String, name: String },
OpenDocumentBrowse,
Expand Down
18 changes: 15 additions & 3 deletions frontend/src/components/panels/Document.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@
</LayoutCol>
<LayoutCol :class="'viewport'">
<LayoutRow :class="'bar-area'">
<CanvasRuler :origin="0" :majorMarkSpacing="100" :direction="RulerDirection.Horizontal" :class="'top-ruler'" />
<CanvasRuler :origin="rulerOrigin.x" :majorMarkSpacing="rulerSpacing" :numberInterval="rulerInterval" :direction="RulerDirection.Horizontal" :class="'top-ruler'" />
</LayoutRow>
<LayoutRow :class="'canvas-area'">
<LayoutCol :class="'bar-area'">
<CanvasRuler :origin="0" :majorMarkSpacing="100" :direction="RulerDirection.Vertical" />
<CanvasRuler :origin="rulerOrigin.y" :majorMarkSpacing="rulerSpacing" :numberInterval="rulerInterval" :direction="RulerDirection.Vertical" />
</LayoutCol>
<LayoutCol :class="'canvas-area'">
<div class="canvas" ref="canvas">
Expand Down Expand Up @@ -224,7 +224,7 @@
<script lang="ts">
import { defineComponent } from "vue";

import { ResponseType, registerResponseHandler, Response, UpdateCanvas, UpdateScrollbars, SetActiveTool, SetCanvasZoom, SetCanvasRotation } from "@/utilities/response-handler";
import { ResponseType, registerResponseHandler, Response, UpdateCanvas, UpdateScrollbars, UpdateRulers, SetActiveTool, SetCanvasZoom, SetCanvasRotation } from "@/utilities/response-handler";
import { SeparatorDirection, SeparatorType } from "@/components/widgets/widgets";
import { comingSoon } from "@/utilities/errors";
import { panicProxy } from "@/utilities/panic-proxy";
Expand Down Expand Up @@ -329,6 +329,15 @@ export default defineComponent({
}
});

registerResponseHandler(ResponseType.UpdateRulers, (responseData: Response) => {
const updateData = responseData as UpdateRulers;
if (updateData) {
this.rulerOrigin = updateData.origin;
this.rulerSpacing = updateData.spacing;
this.rulerInterval = updateData.interval;
}
});

registerResponseHandler(ResponseType.SetActiveTool, (responseData: Response) => {
const toolData = responseData as SetActiveTool;
if (toolData) {
Expand Down Expand Up @@ -374,6 +383,9 @@ export default defineComponent({
scrollbarPos: { x: 0.5, y: 0.5 },
scrollbarSize: { x: 0.5, y: 0.5 },
scrollbarMultiplier: { x: 0, y: 0 },
rulerOrigin: { x: 0, y: 0 },
rulerSpacing: 100,
rulerInterval: 100,
IncrementBehavior,
IncrementDirection,
MenuDirection,
Expand Down
24 changes: 17 additions & 7 deletions frontend/src/components/widgets/rulers/CanvasRuler.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,17 @@ export enum RulerDirection {
"Vertical" = "Vertical",
}

// Apparently the modulo operator in js does not work properly.
const mod = (n: number, m: number) => {
const remain = n % m;
return Math.floor(remain >= 0 ? remain : remain + m);
};

export default defineComponent({
props: {
direction: { type: String as PropType<RulerDirection>, default: RulerDirection.Vertical },
origin: { type: Number, required: true },
numberInterval: { type: Number, required: true },
majorMarkSpacing: { type: Number, required: true },
mediumDivisions: { type: Number, default: 5 },
minorDivisions: { type: Number, default: 2 },
Expand All @@ -68,9 +75,8 @@ export default defineComponent({
const isVertical = this.direction === RulerDirection.Vertical;
const lineDirection = isVertical ? "H" : "V";

const offsetStart = this.origin % this.majorMarkSpacing;
const phasingShift = offsetStart < this.majorMarkSpacing ? this.majorMarkSpacing : 0;
const shiftedOffsetStart = offsetStart - phasingShift;
const offsetStart = mod(this.origin, this.majorMarkSpacing);
const shiftedOffsetStart = offsetStart - this.majorMarkSpacing;

const divisions = this.majorMarkSpacing / this.mediumDivisions / this.minorDivisions;
const majorMarksFrequency = this.mediumDivisions * this.minorDivisions;
Expand All @@ -94,11 +100,13 @@ export default defineComponent({
svgTexts(): {} {
const isVertical = this.direction === RulerDirection.Vertical;

const offsetStart = this.origin % this.majorMarkSpacing;
const phasingShift = offsetStart < this.majorMarkSpacing ? this.majorMarkSpacing : 0;
const shiftedOffsetStart = offsetStart - phasingShift;
const offsetStart = mod(this.origin, this.majorMarkSpacing);
const shiftedOffsetStart = offsetStart - this.majorMarkSpacing;

const svgTextCoordinates = [];

let text = (Math.ceil(-this.origin / this.majorMarkSpacing) - 1) * this.numberInterval;

for (let location = shiftedOffsetStart; location < this.rulerLength; location += this.majorMarkSpacing) {
const destination = Math.round(location);
const x = isVertical ? 9 : destination + 2;
Expand All @@ -107,7 +115,9 @@ export default defineComponent({
let transform = `translate(${x} ${y})`;
if (isVertical) transform += " rotate(270)";

svgTextCoordinates.push({ transform, text: location });
svgTextCoordinates.push({ transform, text });

text += this.numberInterval;
}

return svgTextCoordinates;
Expand Down
28 changes: 27 additions & 1 deletion frontend/src/utilities/response-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const state = reactive({
export enum ResponseType {
UpdateCanvas = "UpdateCanvas",
UpdateScrollbars = "UpdateScrollbars",
UpdateRulers = "UpdateRulers",
ExportDocument = "ExportDocument",
SaveDocument = "SaveDocument",
OpenDocumentBrowse = "OpenDocumentBrowse",
Expand Down Expand Up @@ -67,6 +68,8 @@ function parseResponse(responseType: string, data: any): Response {
return newUpdateCanvas(data.UpdateCanvas);
case "UpdateScrollbars":
return newUpdateScrollbars(data.UpdateScrollbars);
case "UpdateRulers":
return newUpdateRulers(data.UpdateRulers);
case "UpdateLayer":
return newUpdateLayer(data.UpdateLayer);
case "SetCanvasZoom":
Expand Down Expand Up @@ -94,7 +97,17 @@ function parseResponse(responseType: string, data: any): Response {
}
}

export type Response = SetActiveTool | UpdateCanvas | UpdateScrollbars | UpdateLayer | DocumentChanged | DisplayFolderTreeStructure | UpdateWorkingColors | SetCanvasZoom | SetCanvasRotation;
export type Response =
| SetActiveTool
| UpdateCanvas
| UpdateScrollbars
| UpdateRulers
| UpdateLayer
| DocumentChanged
| DisplayFolderTreeStructure
| UpdateWorkingColors
| SetCanvasZoom
| SetCanvasRotation;

export interface UpdateOpenDocumentsList {
open_documents: Array<string>;
Expand Down Expand Up @@ -204,6 +217,19 @@ function newUpdateScrollbars(input: any): UpdateScrollbars {
};
}

export interface UpdateRulers {
origin: { x: number; y: number };
spacing: number;
interval: number;
}
function newUpdateRulers(input: any): UpdateRulers {
return {
origin: { x: input.origin[0], y: input.origin[1] },
spacing: input.spacing,
interval: input.interval,
};
}

export interface ExportDocument {
document: string;
name: string;
Expand Down