1- import { Plugin , App , WorkspaceLeaf , Notice , Modal } from 'obsidian' ;
1+ import { Plugin , WorkspaceLeaf , Notice } from 'obsidian' ;
22import { getAPI } from 'obsidian-dataview' ;
33import * as PIXI from 'pixi.js' ;
44
5- class ColorPickerModal extends Modal {
6- keyColorMap : Map < string | null , number > ;
7- tableBody : HTMLElement ;
8-
9- constructor ( app : App , keyColorMap : Map < string | null , number > ) {
10- super ( app ) ;
11- this . keyColorMap = keyColorMap ;
12- }
13-
14- onOpen ( ) {
15- const { contentEl} = this ;
16- contentEl . createEl ( 'h2' , { text : 'Key Colors' } ) ;
17-
18- // Add CSS styles
19- const styleEl = contentEl . createEl ( 'style' , { text : `
20- .color-table {
21- width: 100%;
22- border-collapse: collapse;
23- }
24- .color-table th, .color-table td {
25- border: 1px solid #ccc;
26- padding: 8px;
27- text-align: left;
28- }
29- .color-table th {
30- background-color: #f2f2f2;
31- }
32- .color-table tr:hover {
33- background-color: #ddd;
34- }
35- .color-preview {
36- width: 50px;
37- height: 20px;
38- border: 1px solid #ccc;
39- cursor: pointer;
40- }
41- .color-preview-box {
42- display: inline-block;
43- width: 20px;
44- height: 20px;
45- border: 1px solid #000;
46- margin-right: 5px;
47- vertical-align: middle;
48- }
49- ` } ) ;
50-
51- // Create table with styles
52- const table = contentEl . createEl ( 'table' , { cls : 'color-table' } ) ;
53- const thead = table . createEl ( 'thead' ) ;
54- const headerRow = thead . createEl ( 'tr' ) ;
55- headerRow . createEl ( 'th' , { text : 'Key' } ) ;
56- headerRow . createEl ( 'th' , { text : 'Color' } ) ;
57-
58- const tbody = table . createEl ( 'tbody' ) ;
59- this . tableBody = tbody ;
60- this . refreshTable ( ) ;
61- }
62-
63- refreshTable ( ) {
64- this . tableBody . empty ( ) ;
65-
66- this . keyColorMap . forEach ( ( color , key ) => {
67- console . log ( `Key: ${ key } , Color: ${ color } ` ) ; // Debug log
68-
69- const row = this . tableBody . createEl ( 'tr' ) ;
70- row . createEl ( 'td' , { text : key } ) ;
5+ export default class GraphLinkTypesPlugin extends Plugin {
6+ api = getAPI ( ) ;
7+ uniqueKeys = new Set < string > ( ) ;
8+ nodeTextMap = new Map ( ) ; // Store node-text pairs
9+ selectedKey : string | null ;
7110
72- const colorCell = row . createEl ( 'td' ) ;
73- const colorString = ( typeof color === 'number' ) ? color . toString ( 16 ) . padStart ( 6 , '0' ) : color ;
74-
75- // Ensure color is a hex string and set it as background color
76- let colorHex = ( typeof color === 'number' ) ? color . toString ( 16 ) . padStart ( 6 , '0' ) : color ;
7711
78- const colorPreviewBox = colorCell . createEl ( 'div' , {
79- cls : 'color-preview-box' ,
80- } ) ;
8112
82- colorPreviewBox . style . backgroundColor = `#${ colorHex } ` ;
83-
84- // Log the computed style of colorPreviewBox
85- console . log ( colorPreviewBox . style . backgroundColor ) ;
86-
87-
88- const colorText = colorCell . createEl ( 'span' , {
89- text : `#${ colorString } `
90- } ) ;
91-
92- colorPreviewBox . addEventListener ( 'click' , ( ) => {
93- this . openColorPicker ( key ) ;
94- } ) ;
95- } ) ;
96- }
97-
13+ async onload ( ) {
14+ if ( this . api ) {
15+ // Listen for DataView 'index-ready' event
16+ this . registerEvent ( this . app . metadataCache . on ( "dataview:index-ready" , ( ) => {
17+ console . log ( "Dataview index is ready." ) ;
18+ } ) ) ;
9819
99- onClose ( ) {
100- const { contentEl} = this ;
101- contentEl . empty ( ) ;
102- }
20+ // Listen for DataView 'metadata-change' event
21+ this . registerEvent ( this . app . metadataCache . on ( "dataview:metadata-change" ,
22+ ( type , file , oldPath ) => {
23+ console . log ( `Metadata changed in file: ${ file . path } ` ) ;
24+ }
25+ ) ) ;
10326
104- openColorPicker ( key : string | null ) {
105- const colorPickerModal = new Modal ( this . app ) ;
106- colorPickerModal . titleEl . setText ( "Select Color" ) ;
107-
108- const colorInput = colorPickerModal . contentEl . createEl ( 'input' , {
109- type : 'text' ,
110- value : "#ffffff"
111- } ) ;
112-
113- const submitButton = colorPickerModal . contentEl . createEl ( 'button' , {
114- text : 'Apply Color'
115- } ) ;
116-
117- submitButton . addEventListener ( 'click' , ( ) => {
118- const newColor = colorInput . value ;
119-
120- if ( newColor && key ) {
121- const colorInt = parseInt ( newColor . replace ( '#' , '' ) , 16 ) ;
122- this . keyColorMap . set ( key , colorInt ) ;
123- this . refreshTable ( ) ;
124- colorPickerModal . close ( ) ;
125- }
126- } ) ;
127-
128- colorPickerModal . open ( ) ;
129- }
130-
27+ } else {
28+ console . error ( "Dataview plugin is not available." ) ;
29+ }
13130
132- }
31+ this . registerEvent ( this . app . workspace . on ( 'layout-change' , ( ) => {
32+ this . getUniqueMetadataKeys ( ) ;
33+ this . startUpdateLoop ( ) ;
34+ } ) ) ;
13335
134- export default class UniqueMetadataKeysPlugin extends Plugin {
135- api = getAPI ( ) ;
136- keyColorMap = new Map < string | null , number > ( ) ;
137- nodeTextMap = new Map ( ) ; // Store node-text pairs
138- selectedKey : string | null ;
139-
36+
14037
141- onload ( ) {
142- this . addCommand ( {
143- id : 'print-unique-metadata-keys' ,
144- name : 'Print Unique Metadata Keys' ,
145- callback : ( ) => this . printUniqueMetadataKeys ( )
146- } ) ;
14738 this . addCommand ( {
14839 id : 'print-link-type' ,
14940 name : 'Print Link Type' ,
150- callback : ( ) => this . startUpdateLoop ( )
41+ callback : ( ) => this . startUpdateLoop ( 1 )
15142 } ) ;
15243
153- this . printUniqueMetadataKeys ( ) ;
154-
155- // Assume these are your keys
156- const keys = [ 'key1' , 'key2' , 'key3' ] ;
157-
158- this . addRibbonIcon ( 'palette' , 'Choose Colors' , ( ) => {
159- new ColorPickerModal ( this . app , this . keyColorMap ) . open ( ) ;
160- } ) ;
16144 }
16245
163- printUniqueMetadataKeys ( ) {
46+ getUniqueMetadataKeys ( ) {
16447 const allPages = this . api . pages ( '' ) ;
165- const uniqueKeys = new Set < string > ( ) ;
16648
16749 for ( const page of allPages ) {
16850 for ( const [ key , value ] of Object . entries ( page ) ) {
16951 if ( this . isLink ( value ) ) {
170- uniqueKeys . add ( key ) ;
52+ this . uniqueKeys . add ( key ) ;
17153 }
17254 }
17355 }
174- uniqueKeys . delete ( "file" ) ;
175-
176- // Define a list of categorical colors as single integers
177- const colors = [
178- 16343842 , 7260435 , 11226103 , 8810003 , 1997538 ,
179- 11796368 , 9731429 , 16177103 , 15601550 , 7601461 ,
180- 1066150 , 6197085 , 5122908 , 1339852 , 2975129 ,
181- 1364806 , 3203221 , 14122353 , 7027020 , 8280444
182- ] ;
183-
184- // Map each unique key to a color
185- Array . from ( uniqueKeys ) . forEach ( ( key , index ) => {
186- const color = colors [ index % colors . length ] ; // Cycle through colors
187- this . keyColorMap . set ( key , color ) ;
188- } ) ;
189-
190- this . keyColorMap . set ( null , 0 ) ;
191- this . keyColorMap . forEach ( ( color , key ) => console . log ( `${ key } : ${ color } ` ) ) ;
56+ this . uniqueKeys . delete ( "file" ) ;
19257 }
19358
19459
195- getColorForKey ( key : string | null ) : number | undefined {
196- return this . keyColorMap . get ( key ) ;
197- }
19860
19961 getMetadataKeyForLink ( sourceId : string , targetId : string ) : string | null {
20062 const sourcePage = this . api . page ( sourceId ) ;
@@ -215,48 +77,29 @@ export default class UniqueMetadataKeysPlugin extends Plugin {
21577 return typeof value === 'object' && value . hasOwnProperty ( 'path' ) ;
21678 }
21779
218- findGraphLeaf ( ) : WorkspaceLeaf | null {
219- var t = [ ] ;
220- this . app . workspace . iterateAllLeaves ( function ( n ) {
221- n . view && t . push ( n . getDisplayText ( ) )
222- } )
223- console . log ( t ) ;
224- var t = [ ] ;
225- this . app . workspace . iterateAllLeaves ( function ( n ) {
226- n . view && t . push ( n )
227- } )
228- console . log ( t ) ;
229- console . log ( this . app . workspace . getLeavesOfType ( ) )
230- viewType
231-
232-
80+ findGraphLeaf ( ) : WorkspaceLeaf | null {
23381 let graphLeaves = this . app . workspace . getLeavesOfType ( 'graph' ) ;
23482 if ( graphLeaves . length != 1 ) {
235- if ( graphLeaves . length < 1 ) {
236- new Notice ( 'No graph view open' ) ;
237- } else {
238- new Notice ( 'More than one graph view open, please choose an active one' ) ;
239- }
24083 return null ;
24184 }
242- console . log ( graphLeaves [ 0 ] . view . renderer ) ;
243-
244- return graphLeaves [ 0 ]
85+ return graphLeaves [ 0 ]
24586 }
24687
24788 createTextForLink ( renderer , link ) {
24889 const linkString = this . getMetadataKeyForLink ( link . source . id , link . target . id ) ;
24990 if ( linkString === null ) return ;
250- console . log ( this . getColorForKey ( linkString ) )
25191 const textStyle = new PIXI . TextStyle ( {
25292 fontFamily : 'Arial' ,
25393 fontSize : 36 ,
254- fill : this . getColorForKey ( linkString )
94+ fill : 0x00000
25595 } ) ;
25696 const text = new PIXI . Text ( linkString , textStyle ) ;
25797 text . alpha = 0.7 ;
25898 text . anchor . set ( 0.5 , 0.5 ) ;
259- this . nodeTextMap . set ( link , text ) ;
99+ if ( ! this . nodeTextMap . has ( link ) ) {
100+ this . nodeTextMap . set ( link , text ) ;
101+ }
102+
260103 this . updateTextPosition ( renderer , link ) ;
261104 renderer . px . stage . addChild ( text ) ;
262105 }
@@ -273,14 +116,29 @@ export default class UniqueMetadataKeysPlugin extends Plugin {
273116 text . scale . set ( 1 / ( 3 * renderer . nodeScale ) ) ;
274117 }
275118 }
119+
120+ destroyMap ( ) {
121+ if ( this . nodeTextMap . size > 0 ) {
122+ this . nodeTextMap . forEach ( ( text , link ) => {
123+ if ( text !== null ) {
124+ renderer . px . stage . removeChild ( text ) ; // Remove the text from the PIXI container
125+ text . destroy ( ) ; // Destroy the text object
126+ }
127+ this . nodeTextMap . delete ( link ) ;
128+ } ) ;
129+ }
130+ }
276131
277- startUpdateLoop ( ) {
132+ startUpdateLoop ( verbosity : number = 0 ) {
278133 const graphLeaf = this . findGraphLeaf ( ) ;
279134 if ( graphLeaf === null ) {
280- console . log ( "Graph leaf not found." ) ;
135+ if ( verbosity > 0 ) {
136+ new Notice ( "No graph or multiple graphs present." )
137+ }
281138 return ;
282139 }
283140 const renderer = graphLeaf . view . renderer ;
141+ // this.destroyMap();
284142 const links = renderer . links ;
285143 links . forEach ( link => this . createTextForLink ( renderer , link ) ) ;
286144 requestAnimationFrame ( this . updatePositions . bind ( this ) ) ;
@@ -289,27 +147,16 @@ export default class UniqueMetadataKeysPlugin extends Plugin {
289147 updatePositions ( ) {
290148 const graphLeaf = this . findGraphLeaf ( ) ;
291149 if ( graphLeaf === null ) {
292- console . log ( "Graph leaf not found." ) ;
293150 return ;
294151 }
295152 const renderer = graphLeaf . view . renderer ;
296- const links = renderer . links ;
297- links . forEach ( link => {
153+ this . nodeTextMap . forEach ( ( text , link ) => {
298154 this . updateTextPosition ( renderer , link ) ;
299155 } ) ;
300156 requestAnimationFrame ( this . updatePositions . bind ( this ) ) ;
301157 }
302158
303- getLinkToTextCoordinates ( nodeX , nodeY , panX , panY , scale ) {
304- // Apply scaling - assuming node coordinates are scaled
305- let scaledX = nodeX * scale ;
306- let scaledY = nodeY * scale ;
307-
308- // Apply panning - assuming the entire scene is panned
309- let pannedX = scaledX + panX ;
310- let pannedY = scaledY + panY ;
311-
312- return { x : pannedX , y : pannedY } ;
159+ getLinkToTextCoordinates ( linkX , linkY , panX , panY , scale ) {
160+ return { x : linkX * scale + panX , y : linkY * scale + panY } ;
313161 }
314-
315162}
0 commit comments