1+ /*
2+ * Project Name : Visual Python
3+ * Description : GUI-based Python code generator
4+ * File Name : InnerFuncViewer.js
5+ * Author : Black Logic
6+ * Note : Component > InnerFuncViewer
7+ * License : GNU GPLv3 with Visual Python special exception
8+ * Date : 2022. 06. 14
9+ * Change Date :
10+ */
11+
12+ //============================================================================
13+ // [CLASS] InnerFuncViewer
14+ //============================================================================
15+ define ( [
16+ 'text!vp_base/html/component/innerFuncViewer.html!strip' ,
17+ 'css!vp_base/css/component/innerFuncViewer.css' ,
18+ 'text!vp_base/python/userCommand.py' ,
19+ 'vp_base/js/com/com_util' ,
20+ 'vp_base/js/com/com_String' ,
21+ 'vp_base/js/com/component/PopupComponent' ,
22+ 'vp_base/js/com/component/FileNavigation'
23+ ] , function ( ifHtml , ifCss , userCommandFile , com_util , com_String , PopupComponent , FileNavigation ) {
24+
25+ /**
26+ * InnerFuncViewer
27+ */
28+ class InnerFuncViewer extends PopupComponent {
29+ _init ( ) {
30+ super . _init ( ) ;
31+ /** Write codes executed before rendering */
32+ this . name = 'Inner Function Viewer' ;
33+ this . config . codeview = false ;
34+ this . config . dataview = false ;
35+ this . config . runButton = false ;
36+ this . config . sizeLevel = 3 ;
37+
38+ this . state = {
39+ vp_userCode : '' ,
40+ ...this . state
41+ }
42+
43+ this . codemirrorList = { } ;
44+ this . importedList = [ ] ;
45+ this . title_no = 0 ;
46+
47+ // double click setter
48+ this . clicked = 0 ;
49+ }
50+
51+ _bindEvent ( ) {
52+ super . _bindEvent ( ) ;
53+ /** Implement binding events */
54+ let that = this ;
55+
56+ // search item
57+ $ ( this . wrapSelector ( '.vp-if-search' ) ) . on ( 'change' , function ( evt ) {
58+ var value = $ ( this ) . val ( ) ;
59+ if ( value != '' ) {
60+ $ ( that . wrapSelector ( '.vp-if-item' ) ) . hide ( ) ;
61+ $ ( that . wrapSelector ( '.vp-if-item' ) ) . filter ( function ( ) {
62+ return $ ( this ) . data ( 'title' ) . search ( value ) >= 0 ;
63+ } ) . show ( ) ;
64+ } else {
65+ $ ( that . wrapSelector ( '.vp-if-item' ) ) . show ( ) ;
66+ }
67+ } ) ;
68+ }
69+
70+ bindSnippetItem ( ) {
71+ let that = this ;
72+ // item header click (toggle item)
73+ $ ( this . wrapSelector ( '.vp-if-item-header' ) ) . off ( 'click' ) ;
74+ $ ( this . wrapSelector ( '.vp-if-item-header' ) ) . on ( 'click' , function ( evt ) {
75+ // select item
76+ // remove selection
77+ $ ( that . wrapSelector ( '.vp-if-item-header' ) ) . removeClass ( 'selected' ) ;
78+ // select item
79+ $ ( this ) . addClass ( 'selected' ) ;
80+
81+ // toggle item
82+ var parent = $ ( this ) . parent ( ) ;
83+ var indicator = $ ( parent ) . find ( '.vp-if-indicator' ) ;
84+ var hasOpen = $ ( indicator ) . hasClass ( 'open' ) ;
85+
86+ if ( ! hasOpen ) {
87+ // show code
88+ $ ( indicator ) . addClass ( 'open' ) ;
89+ $ ( parent ) . find ( '.vp-if-item-code' ) . show ( ) ;
90+ } else {
91+ // hide code
92+ $ ( indicator ) . removeClass ( 'open' ) ;
93+ $ ( parent ) . find ( '.vp-if-item-code' ) . hide ( ) ;
94+ }
95+ evt . stopPropagation ( ) ;
96+ } ) ;
97+
98+ // item menu click
99+ $ ( this . wrapSelector ( '.vp-if-item-menu-item' ) ) . off ( 'click' ) ;
100+ $ ( this . wrapSelector ( '.vp-if-item-menu-item' ) ) . on ( 'click' , function ( evt ) {
101+ var menu = $ ( this ) . data ( 'menu' ) ;
102+ var item = $ ( this ) . closest ( '.vp-if-item' ) ;
103+ var title = $ ( item ) . data ( 'title' ) ;
104+ if ( menu == 'run' ) {
105+ // get codemirror
106+ let cmCode = that . codemirrorList [ title ] ;
107+ cmCode . save ( ) ;
108+ var code = cmCode . getValue ( ) ;
109+ // create block and run it
110+ $ ( '#vp_wrapper' ) . trigger ( {
111+ type : 'create_option_page' ,
112+ blockType : 'block' ,
113+ menuId : 'lgExe_code' ,
114+ menuState : { taskState : { code : code } } ,
115+ afterAction : 'run'
116+ } ) ;
117+ }
118+ evt . stopPropagation ( ) ;
119+ } ) ;
120+ }
121+
122+ bindCodeMirror ( title , selector ) {
123+ let cmCode = this . initCodemirror ( {
124+ key : title ,
125+ selector : selector ,
126+ type : 'readonly' ,
127+ events : [ {
128+ key : 'change' ,
129+ callback : function ( evt , chgObj ) {
130+ if ( chgObj . removed . join ( '' ) != '' || chgObj . text . join ( '' ) != '' ) {
131+ // enable save button
132+ $ ( selector ) . parent ( ) . find ( '.vp-if-save' ) . removeClass ( 'vp-disable' ) ;
133+ }
134+ }
135+ } ]
136+ } ) ;
137+ this . codemirrorList [ title ] = cmCode ;
138+ }
139+
140+ templateForBody ( ) {
141+ return ifHtml ;
142+ }
143+
144+ render ( ) {
145+ super . render ( ) ;
146+
147+ // load udf list
148+ this . loadUserCommandList ( ) ;
149+ }
150+
151+ renderSnippetItem ( title , code , description ) {
152+ var item = new com_String ( ) ;
153+ item . appendFormatLine ( '<div class="{0}" data-title="{1}">' , 'vp-if-item' , title , title ) ;
154+ item . appendFormatLine ( '<div class="{0}" title="{1}">' , 'vp-if-item-header' , description ) ;
155+ item . appendFormatLine ( '<div class="{0}"></div>' , 'vp-if-indicator' ) ;
156+ item . appendFormatLine ( '<input type="text" class="vp-input {0}" value="{1}" disabled/>' , 'vp-if-item-title' , title ) ;
157+ item . appendFormatLine ( '<div class="{0}">' , 'vp-if-item-menu' ) ;
158+ item . appendFormatLine ( '<div class="{0}" data-menu="{1}" title="{2}">'
159+ , 'vp-if-item-menu-item' , 'run' , 'Run' ) ;
160+ item . appendFormatLine ( '<img src="{0}"/>' , '/nbextensions/visualpython/img/snippets/run.svg' ) ;
161+ item . appendLine ( '</div>' ) ;
162+ item . appendLine ( '</div>' ) ; // end of vp-if-item-menu
163+ item . appendLine ( '</div>' ) ; // end of vp-if-item-header
164+ item . appendFormatLine ( '<div class="{0}">' , 'vp-if-item-code' ) ;
165+ item . appendFormatLine ( '<textarea>{0}</textarea>' , code ) ;
166+ item . appendLine ( '</div>' ) ; // end of vp-if-item-code
167+ item . appendLine ( '</div>' ) ; // end of vp-if-item
168+ return item . toString ( ) ;
169+ }
170+
171+ generateCode ( ) {
172+ return '' ;
173+ }
174+
175+ loadUserCommandList ( ) {
176+ var that = this ;
177+
178+ let divider = '#' . repeat ( 6 ) ;
179+ // get list of codes (ignore first 2 items)
180+ let tmpList = userCommandFile . split ( divider ) . slice ( 2 ) ;
181+
182+ // match key-codes-description
183+ // { 'func_name': { code: '', description: '' } }
184+ let funcDict = { } ;
185+ let reg = / ^ d e f ( .+ ) \( / ;
186+ let name = '' ;
187+ let code = '' ;
188+ let desc = '' ;
189+
190+ for ( let i = 0 ; i < tmpList . length ; i += 2 ) {
191+ desc = tmpList [ i ] . trim ( ) ;
192+ code = tmpList [ i + 1 ] . trim ( ) ;
193+ let regResult = reg . exec ( code ) ;
194+ if ( regResult !== null ) {
195+ name = regResult [ 1 ] ;
196+ funcDict [ name ] = { code : code , description : desc } ;
197+ }
198+ }
199+
200+ // clear table except head
201+ $ ( this . wrapSelector ( '.vp-if-table' ) ) . html ( '' ) ;
202+
203+ // load code list
204+ var innerFuncCode = new com_String ( ) ;
205+ Object . keys ( funcDict ) . forEach ( key => {
206+ let obj = funcDict [ key ] ;
207+ if ( obj . code != null && obj . code != undefined ) {
208+ var item = that . renderSnippetItem ( key , obj . code , obj . description ) ;
209+ innerFuncCode . append ( item ) ;
210+ }
211+ } ) ;
212+ $ ( that . wrapSelector ( '.vp-if-table' ) ) . html ( innerFuncCode . toString ( ) ) ;
213+
214+ // bind snippet item
215+ that . bindSnippetItem ( ) ;
216+
217+ // load codemirror
218+ var codeList = $ ( that . wrapSelector ( '.vp-if-item-code textarea' ) ) ;
219+ codeList . each ( ( idx , tag ) => {
220+ var title = $ ( tag ) . closest ( '.vp-if-item' ) . data ( 'title' ) ;
221+ that . bindCodeMirror ( title , tag ) ;
222+ } ) ;
223+ }
224+
225+ }
226+
227+ return InnerFuncViewer ;
228+ } ) ;
0 commit comments