1- import { Plugin , WorkspaceLeaf , Notice } from 'obsidian' ;
1+ import { Plugin , App , WorkspaceLeaf , Notice , Modal } from 'obsidian' ;
22import { getAPI } from 'obsidian-dataview' ;
3+ import * as PIXI from 'pixi.js' ;
4+
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 } ) ;
71+
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 ;
77+
78+ const colorPreviewBox = colorCell . createEl ( 'div' , {
79+ cls : 'color-preview-box' ,
80+ } ) ;
81+
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+
98+
99+ onClose ( ) {
100+ const { contentEl} = this ;
101+ contentEl . empty ( ) ;
102+ }
103+
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+
131+
132+ }
3133
4134export default class UniqueMetadataKeysPlugin extends Plugin {
5135 api = getAPI ( ) ;
6- keyColorMap = new Map < string , number > ( ) ;
136+ keyColorMap = new Map < string | null , number > ( ) ;
137+ nodeTextMap = new Map ( ) ; // Store node-text pairs
138+ selectedKey : string | null ;
139+
7140
8141 onload ( ) {
9142 this . addCommand ( {
@@ -12,9 +145,18 @@ export default class UniqueMetadataKeysPlugin extends Plugin {
12145 callback : ( ) => this . printUniqueMetadataKeys ( )
13146 } ) ;
14147 this . addCommand ( {
15- id : 'print-graph-leaf' ,
16- name : 'Print Graph Leaf' ,
17- callback : ( ) => this . findGraphLeaf ( )
148+ id : 'print-link-type' ,
149+ name : 'Print Link Type' ,
150+ callback : ( ) => this . startUpdateLoop ( )
151+ } ) ;
152+
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 ( ) ;
18160 } ) ;
19161 }
20162
@@ -45,14 +187,12 @@ export default class UniqueMetadataKeysPlugin extends Plugin {
45187 this . keyColorMap . set ( key , color ) ;
46188 } ) ;
47189
48- console . log ( 'Unique Metadata Keys with Link Values:' ) ;
190+ this . keyColorMap . set ( null , 0 ) ;
49191 this . keyColorMap . forEach ( ( color , key ) => console . log ( `${ key } : ${ color } ` ) ) ;
50192 }
193+
51194
52- getColorForKey ( key : string | null ) : number | undefined {
53- if ( key === null ) {
54- return 0 ;
55- }
195+ getColorForKey ( key : string | null ) : number | undefined {
56196 return this . keyColorMap . get ( key ) ;
57197 }
58198
@@ -76,6 +216,20 @@ export default class UniqueMetadataKeysPlugin extends Plugin {
76216 }
77217
78218 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+
79233 let graphLeaves = this . app . workspace . getLeavesOfType ( 'graph' ) ;
80234 if ( graphLeaves . length != 1 ) {
81235 if ( graphLeaves . length < 1 ) {
@@ -85,23 +239,77 @@ export default class UniqueMetadataKeysPlugin extends Plugin {
85239 }
86240 return null ;
87241 }
88- const links = graphLeaves [ 0 ] . view . renderer . links ;
89-
90- for ( let i = 0 ; i < 2 ; i ++ ) {
91- const sourceId = links [ i ] . source . id ;
92- const targetId = links [ i ] . target . id ;
93- console . log ( sourceId ) ;
94- console . log ( targetId ) ;
95- const linkKey = this . getMetadataKeyForLink ( sourceId , targetId ) ;
96- const linkColor = this . getColorForKey ( linkKey ) ;
97- console . log ( linkColor ) ;
98- console . log ( links [ i ] . renderer ) ;
99- links [ i ] . line . _tintRGB = linkColor ;
100- links [ i ] . renderer . colors . line . rgb = links [ i ] . line . _tintRGB ;
101-
102- }
103-
242+ console . log ( graphLeaves [ 0 ] . view . renderer ) ;
104243
105244 return graphLeaves [ 0 ]
106245 }
246+
247+ createTextForLink ( renderer , link ) {
248+ const linkString = this . getMetadataKeyForLink ( link . source . id , link . target . id ) ;
249+ if ( linkString === null ) return ;
250+ console . log ( this . getColorForKey ( linkString ) )
251+ const textStyle = new PIXI . TextStyle ( {
252+ fontFamily : 'Arial' ,
253+ fontSize : 36 ,
254+ fill : this . getColorForKey ( linkString )
255+ } ) ;
256+ const text = new PIXI . Text ( linkString , textStyle ) ;
257+ text . alpha = 0.7 ;
258+ text . anchor . set ( 0.5 , 0.5 ) ;
259+ this . nodeTextMap . set ( link , text ) ;
260+ this . updateTextPosition ( renderer , link ) ;
261+ renderer . px . stage . addChild ( text ) ;
262+ }
263+
264+
265+ updateTextPosition ( renderer , link ) {
266+ const text = this . nodeTextMap . get ( link ) ;
267+ if ( text ) {
268+ const midX = ( link . source . x + link . target . x ) / 2 ;
269+ const midY = ( link . source . y + link . target . y ) / 2 ;
270+ const { x, y } = this . getLinkToTextCoordinates ( midX , midY , renderer . panX , renderer . panY , renderer . scale ) ;
271+ text . x = x ;
272+ text . y = y ;
273+ text . scale . set ( 1 / ( 3 * renderer . nodeScale ) ) ;
274+ }
275+ }
276+
277+ startUpdateLoop ( ) {
278+ const graphLeaf = this . findGraphLeaf ( ) ;
279+ if ( graphLeaf === null ) {
280+ console . log ( "Graph leaf not found." ) ;
281+ return ;
282+ }
283+ const renderer = graphLeaf . view . renderer ;
284+ const links = renderer . links ;
285+ links . forEach ( link => this . createTextForLink ( renderer , link ) ) ;
286+ requestAnimationFrame ( this . updatePositions . bind ( this ) ) ;
287+ }
288+
289+ updatePositions ( ) {
290+ const graphLeaf = this . findGraphLeaf ( ) ;
291+ if ( graphLeaf === null ) {
292+ console . log ( "Graph leaf not found." ) ;
293+ return ;
294+ }
295+ const renderer = graphLeaf . view . renderer ;
296+ const links = renderer . links ;
297+ links . forEach ( link => {
298+ this . updateTextPosition ( renderer , link ) ;
299+ } ) ;
300+ requestAnimationFrame ( this . updatePositions . bind ( this ) ) ;
301+ }
302+
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 } ;
313+ }
314+
107315}
0 commit comments