define([ 'require' , 'jquery' , 'nbextensions/visualpython/src/common/vpCommon' , 'nbextensions/visualpython/src/common/constant' , 'nbextensions/visualpython/src/common/StringBuilder' , 'nbextensions/visualpython/src/common/vpFuncJS' , 'nbextensions/visualpython/src/container/vpContainer' , 'nbextensions/visualpython/src/pandas/common/pandasGenerator' , 'nbextensions/visualpython/src/common/component/vpSuggestInputText' ], function (requirejs, $, vpCommon, vpConst, sb, vpFuncJS, vpContainer, pdGen, vpSuggestInputText) { // 옵션 속성 const funcOptProp = { stepCount : 1 , funcName : "Import Matplotlib" , funcID : "mp_importMatplotlib" // TODO: ID 규칙 생성 필요 } /** * html load 콜백. 고유 id 생성하여 부과하며 js 객체 클래스 생성하여 컨테이너로 전달 * @param {function} callback 호출자(컨테이너) 의 콜백함수 */ var optionLoadCallback = function(callback, meta) { // document.getElementsByTagName("head")[0].appendChild(link); // 컨테이너에서 전달된 callback 함수가 존재하면 실행. if (typeof(callback) === 'function') { var uuid = vpCommon.getUUID(); // 최대 10회 중복되지 않도록 체크 for (var idx = 0; idx < 10; idx++) { // 이미 사용중인 uuid 인 경우 다시 생성 if ($(vpConst.VP_CONTAINER_ID).find("." + uuid).length > 0) { uuid = vpCommon.getUUID(); } } $(vpCommon.wrapSelector(vpCommon.formatString("#{0}", vpConst.OPTION_GREEN_ROOM))).find(vpCommon.formatString(".{0}", vpConst.API_OPTION_PAGE)).addClass(uuid); // 옵션 객체 생성 var mpPackage = new MatplotPackage(uuid); mpPackage.metadata = meta; // 옵션 속성 할당. mpPackage.setOptionProp(funcOptProp); // html 설정. mpPackage.initHtml(); callback(mpPackage); // 공통 객체를 callback 인자로 전달 } } /** * html 로드. * @param {function} callback 호출자(컨테이너) 의 콜백함수 */ var initOption = function(callback, meta) { vpCommon.loadHtml(vpCommon.wrapSelector(vpCommon.formatString("#{0}", vpConst.OPTION_GREEN_ROOM)), "pandas/common/commonEmptyPage.html", optionLoadCallback, callback, meta); } /** * 본 옵션 처리 위한 클래스 * @param {String} uuid 고유 id */ var MatplotPackage = function(uuid) { this.uuid = uuid; // Load html 영역의 uuid. this.package = { code: [ 'import matplotlib.pyplot as ${i0}' , '%matplotlib ${magic}' ], input: [ { name: 'i0', label: 'Matplotlib.pyplot as', type: 'int', value: 'plt' }, { name: 'magic' }, { name: 'range' }, { name: 'stylesheet' }, { name: 'fontfamily' }, { name: 'fontsize' } ] } } /** * vpFuncJS 에서 상속 */ MatplotPackage.prototype = Object.create(vpFuncJS.VpFuncJS.prototype); /** * 유효성 검사 * @returns 유효성 검사 결과. 적합시 true */ MatplotPackage.prototype.optionValidation = function() { return true; // 부모 클래스 유효성 검사 호출. // vpFuncJS.VpFuncJS.prototype.optionValidation.apply(this); } /** * html 내부 binding 처리 */ MatplotPackage.prototype.initHtml = function() { var that = this; this.loadCss(Jupyter.notebook.base_url + vpConst.BASE_PATH + vpConst.STYLE_PATH + "pandas/commonPandas.css"); this.showFunctionTitle(); // this.bindOptions(); var sbPageContent = new sb.StringBuilder(); var sbTagString = new sb.StringBuilder(); // TODO: 필수 옵션 테이블 레이아웃 var tblLayoutRequire = this.createVERSimpleLayout("30%"); // 1. import matplotlib.pyplot as plt sbTagString.clear(); sbTagString.appendFormatLine("", "plt"); tblLayoutRequire.addReqRow("Matplotlib.pyplot as", sbTagString.toString()); // FIXME: vpTableLayoutVerticalSimple에 addDivider 추가 가능한지 확인 tblLayoutRequire.addRow("", "
"); // 2. %matplotlib inline/notebook sbTagString.clear(); sbTagString.appendFormatLine("", "inline", "inline"); sbTagString.appendFormatLine("", "notebook", "notebook"); var tempOptionTag = sbTagString.toString(); sbTagString.clear(); sbTagString.appendFormat('', "magic", tempOptionTag); tblLayoutRequire.addReqRow("%matplotlib", sbTagString.toString()); // FIXME: vpTableLayoutVerticalSimple에 addDivider 추가 가능한지 확인 tblLayoutRequire.addRow("", "
"); // 3. plt.style.use('style') sbTagString.clear(); sbTagString.appendFormatLine("", "all", "all"); sbTagString.appendFormatLine("", "part", "part"); tempOptionTag = sbTagString.toString(); sbTagString.clear(); sbTagString.appendFormat('', "range", tempOptionTag); tblLayoutRequire.addRow("Style Range", sbTagString.toString()); sbTagString.clear(); sbTagString.appendFormat('', "stylesheet"); tblLayoutRequire.addRow("Style Sheet", sbTagString.toString()); // FIXME: vpTableLayoutVerticalSimple에 addDivider 추가 가능한지 확인 tblLayoutRequire.addRow("", "
"); // 4. rcParams // #from matplotlib.pylab import rcParams // #rcParams['font.family'] = 'Gulim' // #rcParams['font.size'] = 10 // #rcParams['figure.figsize'] = 12, 8 // #rcParams['axes.grid'] = True sbTagString.clear(); sbTagString.appendFormat('', "fontfamily", "'Gulim'"); tblLayoutRequire.addRow("System Font", sbTagString.toString()); sbTagString.clear(); sbTagString.appendFormat('', "fontsize"); tblLayoutRequire.addRow("Font Size", sbTagString.toString()); // 필수 옵션 영역 (아코디언 박스) var accBoxRequire = this.createOptionContainer(vpConst.API_REQUIRE_OPTION_BOX_CAPTION); accBoxRequire.setOpenBox(true); accBoxRequire.appendContent(tblLayoutRequire.toTagString()); sbPageContent.appendLine(accBoxRequire.toTagString()); // 페이지에 컨트롤 삽입 vpFuncJS 에서 제공 $(this.wrapSelector()).append(sbPageContent.toString()); // 이벤트 처리 // e1. stylesheet autocomplete with SuggestInput this.bindStylesheet(); // e2. system font autocomplete with SuggestInput this.bindSystemfont(); } /** * 선택한 패키지명 입력 */ MatplotPackage.prototype.showFunctionTitle = function() { $(this.wrapSelector('.vp-funcNavi')).html( ` Matplotlib > Import Matplotlib ` ) // $(this.wrapSelector('.vp_functionName')).text('Import Matplotlib'); } /** * get metadata * @param {String} id id */ MatplotPackage.prototype.getMetadata = function(id) { if (this.metadata == undefined) return ""; var len = this.metadata.options.length; for (var i = 0; i < len; i++) { var obj = this.metadata.options[i]; if (obj.id == id) return obj.value; } return ""; } /** * stylesheet autocomplete */ MatplotPackage.prototype.bindStylesheet = function() { var that = this; // 사용가능한 스타일 시트 조회 var stylesheetTag = $(this.wrapSelector('#stylesheet')); // 스타일 시트 조회 코드 var code = new sb.StringBuilder(); code.appendLine('import matplotlib.pyplot as plt'); code.appendLine('import json'); // code.append(`print(json.dumps(plt.style.available))`); code.append(`print(json.dumps([{ 'label': s, 'value': "'"+s+"'" } for s in plt.style.available]))`); this.kernelExecute(code.toString(), function(result) { // 사용가능한 스타일 시트 목록 var varList = JSON.parse(result); var suggestInput = new vpSuggestInputText.vpSuggestInputText(); suggestInput.setComponentID('stylesheet'); suggestInput.addClass('vp-input'); // metadata check var mdvalue = that.getMetadata('stylesheet'); if (mdvalue != undefined && mdvalue != '') { suggestInput.setValue(mdvalue); } suggestInput.setSuggestList(function() { return varList; }); // suggestInput.setNormalFilter(false); $(stylesheetTag).replaceWith(function() { return suggestInput.toTagString(); }); }); }; /** * font family autocomplete */ MatplotPackage.prototype.bindSystemfont = function() { var that = this; // 사용가능한 폰트 목록 조회 var fontFamilyTag = $(this.wrapSelector('#fontfamily')); // 폰트 조회 코드 var code = new sb.StringBuilder(); code.appendLine('import json'); code.appendLine("import matplotlib.font_manager as fm"); code.appendLine("_ttflist = fm.fontManager.ttflist"); code.append(`print(json.dumps([{"label": f.name, "value":("'" + f.name + "'")} for f in _ttflist]))`); this.kernelExecute(code.toString(), function(result) { // 사용가능한 폰트 목록 var varList = JSON.parse(result); var suggestInput = new vpSuggestInputText.vpSuggestInputText(); suggestInput.setComponentID('fontfamily'); suggestInput.addClass('vp-input'); // metadata check var mdvalue = that.getMetadata('fontfamily'); if (mdvalue != undefined && mdvalue != '') { suggestInput.setValue(mdvalue); } else { suggestInput.setValue("'Gulim'"); } suggestInput.setSuggestList(function() { return varList; }); // suggestInput.setNormalFilter(false); $(fontFamilyTag).replaceWith(function() { return suggestInput.toTagString(); }); }); }; /** * 코드 생성 * @param {boolean} exec 실행여부 */ MatplotPackage.prototype.generateCode = function(addCell, exec) { try { var sbCode = new sb.StringBuilder(); // 코드 생성 // 필수 입력 항목 sbCode.appendFormatLine('import matplotlib.pyplot as {0}', $(this.wrapSelector('#i0')).val()); sbCode.appendFormatLine('%matplotlib {0}', $(this.wrapSelector('#magic')).val()); // style range, sheet var stylerange = $(this.wrapSelector('#range')).val(); var stylesheet = $(this.wrapSelector('#stylesheet')).val(); if (stylesheet != '') { if (stylerange == 'all') { // 전체 범위 코드 구성 sbCode.appendFormat("plt.style.use('{0}')", stylesheet); } else { // 일부 범위 코드 구성 sbCode.appendFormatLine("with plt.style.context({0}):", stylesheet); sbCode.append(" pass"); } } // font family, size var fontfamily = $(this.wrapSelector('#fontfamily')).val(); var fontsize = $(this.wrapSelector('#fontsize')).val(); sbCode.appendLine(''); sbCode.appendLine("from matplotlib.pylab import rcParams"); if (fontfamily != '') { sbCode.appendFormatLine("rcParams['font.family'] = {0}", fontfamily); } if (fontsize != '') { sbCode.appendFormatLine("rcParams['font.size'] = {0}", fontsize); } sbCode.appendLine("#rcParams['figure.figsize'] = 12, 8"); sbCode.appendLine("#rcParams['axes.grid'] = True"); // 코드 추가 및 실행 if (addCell) this.cellExecute(sbCode.toString(), exec); } catch (exmsg) { // 에러 표시 vpCommon.renderAlertModal(exmsg); return "BREAK_RUN"; // 코드 생성 중 오류 발생 } return sbCode.toString(); } return { initOption: initOption }; });