From dcd1bd6d3fba150cd2f819edfb6869fad38af17c Mon Sep 17 00:00:00 2001 From: Kilian Schuettler Date: Sun, 2 Feb 2025 00:06:06 +0100 Subject: [PATCH] All views be rendering big stuff --- src-tauri/src/lib.rs | 136 ++++++++++++----- src-tauri/src/tests.rs | 24 ++- src/components/ContentsView.svelte | 26 +++- src/components/FileView.svelte | 20 +-- src/components/PageList.svelte | 70 --------- src/components/PrimitiveIcon.svelte | 62 ++++---- src/components/PrimitiveView.svelte | 112 ++++++++------ src/components/StreamEditor.svelte | 3 - src/components/TreeNode.svelte | 167 -------------------- src/components/TreeView.svelte | 219 +++++++++++++++++++-------- src/components/XRefTable.svelte | 17 +-- src/models/FileViewState.svelte.ts | 2 +- src/models/PrimitiveView.ts | 15 ++ src/models/TreeViewRequest.svelte.ts | 32 ++-- src/models/TreeViewState.svelte.ts | 155 ++++++++++++++----- tailwind.config.ts | 2 +- 16 files changed, 554 insertions(+), 508 deletions(-) delete mode 100644 src/components/PageList.svelte delete mode 100644 src/components/TreeNode.svelte create mode 100644 src/models/PrimitiveView.ts diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 2997d15..f72b1a5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -7,7 +7,7 @@ use crate::pdf::object::Resolve; use lazy_static::lazy_static; use pdf::file::{File, FileOptions, NoLog, ObjectCache, StreamCache}; -use pdf::object::{Object, ObjectWrite, PlainRef, Stream}; +use pdf::object::{Object, ObjectWrite, PlainRef, Stream, Trace}; use pdf::primitive::Primitive; use pdf::xref::XRef; use regex::Regex; @@ -62,6 +62,19 @@ pub struct PrimitiveModel { pub expanded: bool, } +#[derive(Serialize, Debug, Clone)] +pub struct PrimitiveTreeView { + pub depth: usize, + pub key: String, + pub ptype: String, + pub sub_type: String, + pub value: String, + pub container: bool, + pub expanded: bool, + pub path: Vec, + pub active: bool, +} + #[derive(Serialize, Debug, Clone)] pub struct PathTrace { pub key: String, @@ -83,6 +96,7 @@ pub struct PageModel { pub struct TreeViewRequest { key: String, children: Vec, + expand: bool, } impl TreeViewRequest { @@ -304,32 +318,45 @@ fn resolve_parent(step: Step, file: &CosFile) -> Result<(Primitive, PathTrace), #[tauri::command] fn get_prim_tree_by_path( id: &str, - path: TreeViewRequest, + paths: Vec, session: State>, -) -> Result { +) -> Result, String> { let session_guard = session .lock() .map_err(|_| "Failed to lock the session mutex.".to_string())?; let file = get_file_from_state(id, &session_guard)?; - get_prim_tree_by_path_with_file(path, &file.cos_file) + let results = paths + .into_iter() + .map(|path| get_prim_tree_by_path_with_file(path, &file.cos_file)) + .collect::, String>>()? + .into_iter() + .flatten() + .collect(); + + Ok(results) } fn get_prim_tree_by_path_with_file( node: TreeViewRequest, file: &CosFile, -) -> Result { +) -> Result, String> { let step = node.step()?; let (parent, trace) = resolve_parent(step.clone(), file)?; - let path = vec![trace]; - let mut parent_model = PrimitiveModel::from_primitive_with_children(&parent, path); + let trace = vec![trace]; + let mut parent_model: PrimitiveModel; + if node.expand { + parent_model = PrimitiveModel::from_primitive_with_children(&parent, trace); - for child in node.children.iter() { - expand(child, &mut parent_model, &parent, file)?; + for child in node.children.iter() { + expand(child, &mut parent_model, &parent, file)?; + } + } else { + parent_model = PrimitiveModel::from_primitive(step.get_key(), &parent, trace); } - Ok(parent_model) + Ok(PrimitiveTreeView::flatten(0, parent_model)) } fn expand( @@ -338,20 +365,21 @@ fn expand( parent: &Primitive, file: &CosFile, ) -> Result<(), String> { + if !node.expand { + return Ok(()); + } let step = node.step()?; let prim = resolve_step(parent, &step)?; if let Primitive::Reference(x_ref) = prim { let jump = resolve_xref(x_ref.id, file)?; - // parent_model.ptype = format!("{}-Reference", jump.get_debug_name()); + let mut jump_trace = parent_model.trace.clone(); + jump_trace.push(PathTrace::new(step.get_key(), x_ref.id.to_string())); let mut to_expand = parent_model.get_child(step.get_key()).unwrap(); - to_expand.add_children( - &jump, - append_path_with_jump(step.get_key(), x_ref.id.to_string(), &to_expand.trace), - ); + to_expand.add_children(&jump, &jump_trace); expand_children(node, file, &jump, &mut to_expand)?; } else { let mut to_expand = parent_model.get_child(step.get_key()).unwrap(); - to_expand.add_children(prim, append_path(step.get_key(), &to_expand.trace)); + to_expand.add_children(prim, &to_expand.trace.clone()); expand_children(node, file, prim, &mut to_expand)?; } Ok(()) @@ -426,6 +454,9 @@ fn retrieve_trailer(file: &CosFile) -> Primitive { } fn retrieve_page(page_num: u32, file: &CosFile) -> Result<(Primitive, PathTrace), String> { + if page_num <= 0 { + return Err("Page 0 does not exist, use 1-based index!".to_string()); + } let page_rc = t!(file.get_page(page_num - 1)); let p_ref = page_rc.get_ref().get_inner(); Ok(( @@ -516,12 +547,6 @@ fn get_file_from_state<'a>( .ok_or_else(|| format!("File with id {} does not exist!", id)) } -fn append_path_with_jump(key: String, last_jump: String, path: &Vec) -> Vec { - let mut new_path = path.clone(); - new_path.push(PathTrace::new(key, last_jump)); - new_path -} - fn append_path(key: String, path: &Vec) -> Vec { let mut new_path = path.clone(); let last_jump = new_path.last().unwrap().last_jump.clone(); @@ -541,7 +566,7 @@ impl PrimitiveModel { Primitive::Dictionary(_) => "-".to_string(), Primitive::Array(arr) => PrimitiveModel::format_arr_content(arr), Primitive::Reference(pref) => { - format!("Obj Number: {} Gen Number: {}", pref.id, pref.gen) + format!("Obj Nr: {} Gen Nr: {}", pref.id, pref.gen) } Primitive::Name(name) => name.clone().as_str().to_string(), @@ -595,17 +620,20 @@ impl PrimitiveModel { result } - fn from_primitive_with_children(primitive: &Primitive, path: Vec) -> PrimitiveModel { + fn from_primitive_with_children( + primitive: &Primitive, + trace: Vec, + ) -> PrimitiveModel { let mut model = PrimitiveModel::from_primitive( - path.last().unwrap().key.clone(), + trace.last().unwrap().key.clone(), primitive, - path.clone(), + trace.clone(), ); - model.add_children(primitive, path); + model.add_children(primitive, &trace); model } - fn add_children(&mut self, primitive: &Primitive, path: Vec) { + fn add_children(&mut self, primitive: &Primitive, path: &Vec) { self.expanded = true; match primitive { Primitive::Dictionary(dict) => dict.iter().for_each(|(name, value)| { @@ -619,6 +647,13 @@ impl PrimitiveModel { self.add_child(i.to_string(), obj, append_path(i.to_string(), &path)); }), Primitive::Stream(stream) => { + stream.info.iter().for_each(|(name, value)| { + self.add_child( + name.clone().as_str().to_string(), + value, + append_path(name.clone().as_str().to_string(), &path), + ); + }); self.children.push(PrimitiveModel { key: "Data".to_string(), ptype: "Stream Data".to_string(), @@ -628,13 +663,6 @@ impl PrimitiveModel { trace: append_path("Data".to_string(), &path), expanded: false, }); - stream.info.iter().for_each(|(name, value)| { - self.add_child( - name.clone().as_str().to_string(), - value, - append_path(name.clone().as_str().to_string(), &path), - ); - }) } _ => (), }; @@ -654,6 +682,42 @@ impl PrimitiveModel { fn get_child(&mut self, key: String) -> Option<&mut PrimitiveModel> { self.children.iter_mut().find(|child| child.key == key) } + + fn is_container(&self) -> bool { + self.ptype == "Dictionary" + || self.ptype == "Array" + || self.ptype == "Stream" + || self.ptype == "Reference" + } + fn drain_children(&mut self) -> Vec { + self.children.drain(..).collect() + } +} + +impl PrimitiveTreeView { + fn from_primitive(depth: usize, primitive: PrimitiveModel) -> PrimitiveTreeView { + let is_container = primitive.is_container(); + PrimitiveTreeView { + depth: depth, + key: primitive.key, + ptype: primitive.ptype, + sub_type: primitive.sub_type, + value: primitive.value, + container: is_container, + expanded: primitive.expanded, + path: primitive.trace, + active: true, + } + } + fn flatten(depth: usize, mut primitive: PrimitiveModel) -> Vec { + let mut views: Vec = Vec::new(); + let children = primitive.drain_children(); + views.push(PrimitiveTreeView::from_primitive(depth, primitive)); + children.into_iter().for_each(|child| { + views.extend(PrimitiveTreeView::flatten(depth + 1, child.clone())); + }); + views + } } #[tauri::command] fn get_xref_table(id: &str, session: State>) -> Result { @@ -686,7 +750,7 @@ fn get_xref_table_model_with_file(file: &CosFile) -> Result XRefEntryModel { obj_num: i as u64, - gen_num: *stream_id as u64, + gen_num: 0, obj_type: "Stream".into(), offset: *index as u64, }, diff --git a/src-tauri/src/tests.rs b/src-tauri/src/tests.rs index 01c80e9..2b97670 100644 --- a/src-tauri/src/tests.rs +++ b/src-tauri/src/tests.rs @@ -80,13 +80,26 @@ mod tests { }], }); let root = TreeViewRequest { - key: "/".to_string(), + key: "Trailer".to_string(), children: path, }; let message = format!("Retrieval of {:?}", root); - let prim = timed!(get_prim_tree_by_path_with_file(root, &file), message); - print_node(prim.unwrap(), 0); + let prim = timed!(get_prim_tree_by_path_with_file(root, &file), message).unwrap(); + for ele in prim { + println!( + "{}{} | {} | {} | {:?}", + " ".repeat(ele.depth), + ele.key, + ele.ptype, + ele.value, + ele.path + .iter() + .map(|p| p.key.to_string()) + .collect::>() + .join("/") + ); + } } #[test] fn test_read_by_path() { @@ -94,7 +107,7 @@ mod tests { FileOptions::cached().open(FILE_PATH).unwrap(), "Loading file" ); - let path = "/Root/Pages"; + let path = "/Trailer/Root/Pages"; let message = format!("Retrieval of {:?}", path); let prim = timed!(get_prim_model_by_path_with_file(path, &file), message); @@ -122,9 +135,8 @@ mod tests { "writing trailer" ); let trail_model = PrimitiveModel::from_primitive_with_children( - "Trailer".to_string(), &trail, - vec![PathTrace::new("/".to_string(), "/".to_string())], + vec![PathTrace::new("Trailer".to_string(), "Trailer".to_string())], ); print_node(trail_model, 5); println!("{:?}", file.trailer.info_dict); diff --git a/src/components/ContentsView.svelte b/src/components/ContentsView.svelte index 4d4a8f3..25d49ac 100644 --- a/src/components/ContentsView.svelte +++ b/src/components/ContentsView.svelte @@ -34,21 +34,31 @@ loadContents(path, id); }); - $inspect(contents); function loadContents(path: string | undefined, id: string) { - console.log("Loading contents for", path, id); if (!path || !id) return; invoke("get_contents", { id, path }) .then((result) => { - console.log("Contents loaded", result); contents = result; if (contents && editor) { - const text = contents.parts - .map((part) => part.join("\n")) - .join( - "\n\n%-------------------% EOF %-------------------%\n\n", - ); + let text = ""; + if (contents.parts.length > 1) { + let i = 0; + for (let part of contents.parts) { + text += + "%----------------% Contents[" + + i + + "] %--------------%\n\n"; + for (let line of part) { + text += " " + line + "\n"; + } + text += + "\n%-------------------% EOF %-------------------%\n\n"; + i++; + } + } else { + text = contents.parts[0].join("\n"); + } editor.setValue(text); } }) diff --git a/src/components/FileView.svelte b/src/components/FileView.svelte index cf2f6e0..fa5feca 100644 --- a/src/components/FileView.svelte +++ b/src/components/FileView.svelte @@ -4,13 +4,9 @@ import PrimitiveView from "./PrimitiveView.svelte"; import TreeView from "./TreeView.svelte"; import type FileViewState from "../models/FileViewState.svelte"; - import { createEventDispatcher, onMount } from "svelte"; - import PageList from "./PageList.svelte"; import ContentsView from "./ContentsView.svelte"; - import TreeViewRequest from "../models/TreeViewRequest.svelte"; - import TreeViewState from "../models/TreeViewState.svelte"; import type { PathSelectedEvent } from "../events/PathSelectedEvent"; - TreeViewRequest; + import { onMount } from "svelte"; let { treeShowing, xrefTableShowing, @@ -68,19 +64,7 @@ minSize={treeShowing || pagesShowing ? 2 : 0} maxSize={treeShowing || pagesShowing ? 100 : 0} > - {#if pagesShowing} - - {:else if treeShowing} -
- -
- {/if} + diff --git a/src/components/PageList.svelte b/src/components/PageList.svelte deleted file mode 100644 index 95eb2da..0000000 --- a/src/components/PageList.svelte +++ /dev/null @@ -1,70 +0,0 @@ - - -
-
- {#each pages as page} - - {/each} -
-
- - diff --git a/src/components/PrimitiveIcon.svelte b/src/components/PrimitiveIcon.svelte index a8f7fba..66c28d3 100644 --- a/src/components/PrimitiveIcon.svelte +++ b/src/components/PrimitiveIcon.svelte @@ -1,35 +1,35 @@ - {#if ptype === "Dictionary"} - - {:else if ptype === "Array"} - - {:else if ptype === "Reference"} - - {:else if ptype === "Integer"} - - {:else if ptype === "Number"} - - {:else if ptype === "Boolean"} - - {:else if ptype === "String"} - - {:else if ptype === "Name"} - - {:else if ptype === "Stream Data"} - - {:else} - - {/if} + +{#if ptype === "Dictionary"} + +{:else if ptype === "Array"} + +{:else if ptype === "Reference"} + +{:else if ptype === "Integer"} + +{:else if ptype === "Number"} + +{:else if ptype === "Boolean"} + +{:else if ptype === "String"} + +{:else if ptype === "Name"} + +{:else if ptype === "Stream Data"} + +{:else} + +{/if} + \ No newline at end of file + diff --git a/src/components/PrimitiveView.svelte b/src/components/PrimitiveView.svelte index 613d4c3..8ded865 100644 --- a/src/components/PrimitiveView.svelte +++ b/src/components/PrimitiveView.svelte @@ -5,12 +5,22 @@ import PrimitiveIcon from "./PrimitiveIcon.svelte"; import StreamEditor from "./StreamEditor.svelte"; + const cellH = 29; + const headerOffset = 24; let { fState, height }: { fState: FileViewState; height: number } = $props(); - let bodyHeight = $derived(height - 24); + let fillerHeight: number = $state(0); + + let firstEntry = $state(0); + let lastEntry = $state(100); + let scrollY = $state(0); let prim = $derived(fState.prim); - let showContents = $state(false); - let tableHeight = $state(0); + let entriesToDisplay: Primitive[] = $derived( + prim ? prim.children.slice(firstEntry, lastEntry) : [], + ); + let tableHeight = $derived(prim ? prim.children.length * cellH : 0); + + let bodyHeight = $derived(height - headerOffset); let editorHeight = $derived(Math.max(800, bodyHeight - tableHeight)); $inspect(fState.highlightedPrim); function handlePrimSelect(prim: Primitive) { @@ -25,6 +35,14 @@ } return; } + + function handleScroll(event: Event & { currentTarget: HTMLElement }) { + scrollY = event.currentTarget.scrollTop; + firstEntry = Math.floor(scrollY / cellH); + lastEntry = Math.ceil((scrollY + bodyHeight) / cellH); + + fillerHeight = firstEntry * cellH; + } {#if prim && prim.children && prim.children.length > 0} @@ -41,31 +59,44 @@ -
- - - {#each prim.children as entry} - (fState.highlightedPrim = entry)} - ondblclick={() => handlePrimSelect(entry)} - > - - - - - {/each} - -
-
- -

- {entry.key} -

-
-
{entry.ptype}{entry.value}
+
+
+ + + + {#each entriesToDisplay as entry} + + (fState.highlightedPrim = entry)} + ondblclick={() => handlePrimSelect(entry)} + > + + + + + {/each} + +
+
+ +

+ {entry.key} +

+
+
{entry.ptype}{entry.value}
+
{#if fState.prim?.ptype === "Stream"} diff --git a/src/components/StreamEditor.svelte b/src/components/StreamEditor.svelte index 683f0c1..5e8bd1b 100644 --- a/src/components/StreamEditor.svelte +++ b/src/components/StreamEditor.svelte @@ -33,14 +33,11 @@ loadContents(path, fileId); }); - $inspect(contents); function loadContents(path: string | undefined, id: string) { - console.log("Loading contents for", path, id); if (!path || !id) return; path = path + "/Data"; invoke("get_stream_data", { id, path }) .then((result) => { - console.log("Contents loaded", result); contents = result; if (contents && editor) { editor.setValue(contents); diff --git a/src/components/TreeNode.svelte b/src/components/TreeNode.svelte deleted file mode 100644 index c29a45c..0000000 --- a/src/components/TreeNode.svelte +++ /dev/null @@ -1,167 +0,0 @@ - - -{#if parent_view} - {#each parent_view.children as child} - - {#if child.children.length > 0} - - {/if} - {/each} -{/if} - - diff --git a/src/components/TreeView.svelte b/src/components/TreeView.svelte index 8682063..5f2f943 100644 --- a/src/components/TreeView.svelte +++ b/src/components/TreeView.svelte @@ -1,80 +1,148 @@ -
    - {#if root} -
  • - {/if} -
    - - {root.key} -
    - - {#if active && treeState?.view} - - {/if} -
  • + {/each} +
{/if} - +
diff --git a/src/components/XRefTable.svelte b/src/components/XRefTable.svelte index 058fdcf..4b17d6c 100644 --- a/src/components/XRefTable.svelte +++ b/src/components/XRefTable.svelte @@ -84,10 +84,10 @@ Offset fState.selectXref(undefined)} + onclick={() => fState.selectXref(undefined)} > Trailer 65535 @@ -112,7 +112,7 @@ class={selectedPath === entry.obj_num ? "bg-forge-acc" : "hover:bg-forge-sec"} - ondblclick={() => fState.selectXref(entry)} + onclick={() => fState.selectXref(entry)} > {entry.obj_num} {entry.gen_num} @@ -149,15 +149,4 @@ .scrollContainer { overflow-y: auto; } - .xref-modal { - position: fixed; - right: 0; - top: 0; - bottom: 0; - width: 281px; - background: var(--background-color); - box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1); - z-index: 1000; - overflow-y: auto; - } diff --git a/src/models/FileViewState.svelte.ts b/src/models/FileViewState.svelte.ts index 7dfcfaf..7724be4 100644 --- a/src/models/FileViewState.svelte.ts +++ b/src/models/FileViewState.svelte.ts @@ -55,7 +55,7 @@ export default class FileViewState { } public selectPathHandler(event: PathSelectedEvent) { - console.log("Selecting path", event.detail); + if (event.detail.file_id !== this.file.id) { return; } diff --git a/src/models/PrimitiveView.ts b/src/models/PrimitiveView.ts new file mode 100644 index 0000000..e407344 --- /dev/null +++ b/src/models/PrimitiveView.ts @@ -0,0 +1,15 @@ +import type { Trace } from "./Primitive.svelte"; + +export class PrimitiveView { + constructor( + public depth: number, + public key: string, + public ptype: string, + public sub_type: string, + public value: string, + public container: boolean, + public expanded: boolean, + public path: Trace[], + public active: boolean, + ) { } +} diff --git a/src/models/TreeViewRequest.svelte.ts b/src/models/TreeViewRequest.svelte.ts index a2718c0..f50b290 100644 --- a/src/models/TreeViewRequest.svelte.ts +++ b/src/models/TreeViewRequest.svelte.ts @@ -3,11 +3,12 @@ export default class TreeViewRequest { public key: string; public children: TreeViewRequest[]; public displayName: string; - public active: boolean; + expand: boolean; constructor( key: string, - children: TreeViewRequest[] + children: TreeViewRequest[], + expand: boolean = false, ) { if (key.startsWith("Page")) { this.displayName = "Page " + key.slice(4); @@ -16,13 +17,21 @@ export default class TreeViewRequest { } this.key = key; this.children = children; - this.active = true; + this.expand = expand; } - static TRAILER = new TreeViewRequest("Trailer", [new TreeViewRequest("Root", [])]); + static fromPageCount(pageCount: number) { + let roots = [TreeViewRequest.TRAILER]; + for (let i = 0; i < pageCount; i++) { + roots.push(new TreeViewRequest("Page" + (i + 1), [])); + } + return roots; + } + + static TRAILER = new TreeViewRequest("Trailer", [new TreeViewRequest("Root", [], true)], true); public clone(): TreeViewRequest { - return new TreeViewRequest(this.key, this.children.map(child => child.clone())); + return new TreeViewRequest(this.key, this.children.map(child => child.clone()), this.expand); } public getChild(key: string) { @@ -30,16 +39,17 @@ export default class TreeViewRequest { } public addChild(key: string) { - let child = new TreeViewRequest(key, []) + this.expand = true; + let child = new TreeViewRequest(key, [], true) this.children.push(child); return child; } - public clearChildren() { - this.children = []; - } - public removeChild(key: string) { this.children = this.children.filter(child => child.key !== key); } -} \ No newline at end of file + + public setExpand(expand: boolean) { + this.expand = expand; + } +} diff --git a/src/models/TreeViewState.svelte.ts b/src/models/TreeViewState.svelte.ts index a055603..797452c 100644 --- a/src/models/TreeViewState.svelte.ts +++ b/src/models/TreeViewState.svelte.ts @@ -1,79 +1,164 @@ import { invoke } from "@tauri-apps/api/core"; -import Primitive from "./Primitive.svelte"; import TreeViewRequest from "./TreeViewRequest.svelte"; -import type { PathSelectedEvent } from "../events/PathSelectedEvent"; +import { PrimitiveView } from "./PrimitiveView"; +import type { Trace } from "./Primitive.svelte"; +import type FileViewState from "./FileViewState.svelte"; export default class TreeViewState { - - private root: TreeViewRequest = $state(new TreeViewRequest("Trailer", [new TreeViewRequest("Root", [])])); - public view: Primitive | undefined = $state(); - active: boolean = $state(false); - + private request: TreeViewRequest[]; + private activeRequest: Map = $state(new Map()); + private activeEntries: Map = $state(new Map()); file_id: string; - constructor(file_id: string, root: TreeViewRequest) { - console.log("Creating tree view state", file_id, root); + constructor(file_id: string, fState: FileViewState) { + + this.request = TreeViewRequest.fromPageCount(+fState.file.page_count); + this.activeRequest.set(this.request[0].key, this.request[0]); this.file_id = file_id; - this.root = root; } - public loadTreeView() { - this.setTreeViewRequest(this.getRoot()); + public getEntryCount() { + let count = 0; + this.activeEntries.forEach((value, key) => { + count += value.length - 1; + }); + return this.request.length + count; } - public getRoot(): TreeViewRequest { - return this.root.clone(); + public getEntries(start: number, end: number): PrimitiveView[] { + let i = 0; + let result: PrimitiveView[] = []; + for (let request of this.request) { + if (this.activeEntries.has(request.key)) { + let entries = this.activeEntries.get(request.key); + for (let entry of entries) { + if (i >= start) { + result.push(entry); + } + i += 1; + if (i >= end) { + console.log("end", i, end); + return result; + } + } + } else { + if (i >= start) { + result.push( + new PrimitiveView( + 0, + request.key, + "Dictionary", + "-", + "-", + true, + false, + [{ key: request.key, last_jump: request.key } as Trace], + true, + )) + } + i += 1; + if (i >= end) { + console.log("end", i, end); + return result; + } + } + } + return result; } - public setTreeViewRequest(treeViewRequest: TreeViewRequest) { - console.log("Loading tree view", treeViewRequest); - invoke("get_prim_tree_by_path", { + public toView(request: TreeViewRequest): PrimitiveView { + return new PrimitiveView( + 0, + request.key, + "Dictionary", + "-", + "-", + true, + false, + [{ key: request.key, last_jump: request.key } as Trace], + false, + ); + } + + public async loadTreeView() { + const activeRequests = Array.from(this.activeRequest.values()); + await this.updateTreeViewRequest(activeRequests); + } + + public getRoot(): TreeViewRequest[] { + let _roots: TreeViewRequest[] = []; + this.request.forEach((root) => { + _roots.push(root.clone()); + }); + return _roots; + } + + public async updateTreeViewRequest(treeViewRequests: TreeViewRequest[]) { + + let result = await invoke("get_prim_tree_by_path", { id: this.file_id, - path: treeViewRequest, - }) - .then((result) => { - this.view = new Primitive(result); - this.root = treeViewRequest; - }) - .catch((err) => console.error(err)); + paths: treeViewRequests, + }); + for (let i = 0; i < treeViewRequests.length; i++) { + let request = treeViewRequests[i]; + if (request.expand) { + this.activeRequest.set(request.key, request); + } else { + this.activeRequest.delete(request.key); + } + let prim = result.filter(r => r.path[0].key == request.key); + if (prim) { + this.activeEntries.set(request.key, prim); + } + } } - public expandTree(path: string[]) { + public async expandTree(path: string[]) { if (path.length == 0) { console.error("Empty path"); return; } - console.log("Expanding tree", this.getRoot(), path); - let root = this.getRoot(); + let root = this.activeRequest.get(path[0]); + if (!root) { + root = this.getRoot().find((root) => root.key === path[0]); + if (!root) { + console.error("Root not found for path: " + path); + return; + } + } + root.setExpand(true); let node = root; for (let key of path.slice(1, path.length)) { let _node: TreeViewRequest | undefined = node.getChild(key); if (_node) { + _node.setExpand(true); node = _node; } else { node = node.addChild(key); } } - this.setTreeViewRequest(root); + await this.updateTreeViewRequest([root]); } - public collapseTree(path: string[]) { + public async collapseTree(path: string[]) { + console.log("collapseTree", path); if (path.length == 0) { console.error("Empty path"); return; } - if (path.length == 1) { - this.view = this.view?.withoutChildren(); + let root: TreeViewRequest | undefined = this.activeRequest.get(path[0]); + if (!root) { + console.error("Root not found for path: " + path); return; } - let root: TreeViewRequest = this.root; let node: TreeViewRequest | undefined = root; - for (let key of path.slice(1, path.length - 1)) { + for (let key of path.slice(1, path.length)) { + console.log("collapseTree", key); node = node?.getChild(key); } if (node) { - node.removeChild(path[path.length - 1]); - this.setTreeViewRequest(root); + node.setExpand(false); + await this.updateTreeViewRequest([root]); } } } diff --git a/tailwind.config.ts b/tailwind.config.ts index b4244d4..8646b8e 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -28,7 +28,7 @@ export default { bound: 'rgba(0, 0, 0, 0.29)', text: '#dadada', text_sec: '#838686', - text_hint: '#5adada', + text_hint: '#5cc4c4c2', } } }