/* * This file is part of TREB. * * TREB is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any * later version. * * TREB is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along * with TREB. If not, see . * * Copyright 2022-2026 trebco, llc. * info@treb.app * */ import type { Sheet } from './sheet'; /** * we spend a lot of time looking up sheets by name, or id, or * sometimes index. it makes sense to have a class that can * support all of these, ideally without looping. * * we just have to make sure that no one is assigning to the * array, or we'll lose track. * * also there are some operations -- rename, in particular -- that * require updating indexes. * * * FIXME: new file (1 class per file) */ export class SheetCollection { /** * returns a read-only copy of the list. useful for indexing or * functional-style calls. it's not actually read-only, but it's a * copy, so changes will be ignored. */ public get list() { return this.sheets_.slice(0); } /** * length of list */ public get length() { return this.sheets_.length; } /** map of (normalized) name -> sheet */ protected names: Map = new Map(); /** map of id -> sheet */ protected ids: Map = new Map(); /** the actual list */ private sheets_: Sheet[] = []; /** * remove any existing sheets and add the passed list. updates indexes. */ public Assign(sheets: Sheet[]) { this.sheets_ = [...sheets]; this.UpdateIndexes(); } /** * add a new sheet to the end of the list (push). updates indexes. */ public Add(sheet: Sheet) { this.sheets_.push(sheet); this.UpdateIndexes(); } /** * wrapper for array splice. updates indexes. */ public Splice(insert_index: number, delete_count: number, ...items: Sheet[]) { this.sheets_.splice(insert_index, delete_count, ...items); this.UpdateIndexes(); } /** * so our new strategy is to add lookup methods first -- then * we can fix the underlying storage implementation. * * NOTE we normalize strings here so you do not need to do it (don't) */ public Find(id: string|number): Sheet|undefined { // console.info('get', typeof id); if (typeof id === 'string') { return this.names.get(id.toLocaleUpperCase()); } else { return this.ids.get(id); } return undefined; } /** get name for sheet with given id */ public Name(id: number): string|undefined { return this.ids.get(id)?.name || undefined; } /** get ID for sheet with given name */ public ID(name: string): number|undefined { return this.names.get(name.toLocaleUpperCase())?.id || undefined; } /** not sure why this is private, makes it a little more complicated */ public UpdateIndexes(): void { this.names.clear(); this.ids.clear(); for (const sheet of this.sheets_) { const uc = sheet.name.toLocaleUpperCase(); this.names.set(uc, sheet); this.ids.set(sheet.id, sheet); } } }