Skip to content

Commit 0232a1c

Browse files
author
minjk-bl
committed
Add HelpViewer
1 parent 6a70202 commit 0232a1c

File tree

5 files changed

+300
-6
lines changed

5 files changed

+300
-6
lines changed

visualpython/css/component/popupComponent.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@
197197
margin-top: 9px;
198198
margin-left: 10px;
199199
}
200+
.vp-popup-button[data-type="help"] {
201+
float: left;
202+
margin-top: 9px;
203+
margin-left: 10px;
204+
}
200205
.vp-popup-button[data-type="cancel"] {
201206
float: right;
202207
background-color: #E4E4E4;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!--
2+
Project Name : Visual Python
3+
Description : GUI-based Python code generator
4+
File Name : helpViewer.html
5+
Author : Black Logic
6+
Note : Help viewer
7+
License : GNU GPLv3 with Visual Python special exception
8+
Date : 2023. 07. 13
9+
Change Date :
10+
-->
11+
<!-- use body tag to strip comments out on requirejs/text plugin -->
12+
<body>
13+
<div class="vp-popup-frame">
14+
<div class="vp-popup-header">
15+
<!-- CHROME: title is a handler for draggable, but for some reason label tag's width is not controllable. changed tag: label -> div -->
16+
<div class="vp-popup-title">
17+
<!-- Title -->
18+
Help viewer
19+
</div>
20+
<div class="vp-popup-maximize" title="Maximize this popup"></div>
21+
<div class="vp-popup-return" title="Return size of this popup"></div>
22+
<div class="vp-popup-close" title="Close popup"></div>
23+
</div>
24+
<div class="vp-popup-body vp-scrollbar">
25+
<!-- Body -->
26+
<div class="vp-popup-content">
27+
<!-- <textarea id="helpContent" class="wp100"></textarea> -->
28+
<pre id="helpContent">
29+
30+
</pre>
31+
</div>
32+
</div>
33+
<div class="vp-popup-footer">
34+
<!-- Footer -->
35+
<!-- Button box -->
36+
<div class="vp-popup-button-box">
37+
<button type="button" class="vp-button vp-popup-button" data-type="cancel">Cancel</button>
38+
</div>
39+
</div>
40+
</div>
41+
</body>

visualpython/html/component/popupComponent.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
<div class="vp-popup-button-box">
103103
<button type="button" class="vp-button vp-popup-button" data-type="code">Code view</button>
104104
<button type="button" class="vp-button vp-popup-button" data-type="data">Data view</button>
105+
<button type="button" class="vp-button vp-popup-button" data-type="help">Help</button>
105106

106107
<div class="vp-popup-runadd-box">
107108
<button type="button" class="vp-button activated vp-popup-button" data-type="run" title="Save to block & Run cell">Run</button>
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
* Project Name : Visual Python
3+
* Description : GUI-based Python code generator
4+
* File Name : HelpViewer.js
5+
* Author : Black Logic
6+
* Note : Component > HelpViewer
7+
* License : GNU GPLv3 with Visual Python special exception
8+
* Date : 2023. 07. 13
9+
* Change Date :
10+
*/
11+
//============================================================================
12+
// [CLASS] HelpViewer
13+
//============================================================================
14+
define([
15+
__VP_TEXT_LOADER__('vp_base/html/component/helpViewer.html'), // INTEGRATION: unified version of text loader
16+
__VP_CSS_LOADER__('vp_base/css/component/popupComponent'), // INTEGRATION: unified version of css loader
17+
'vp_base/js/com/com_util',
18+
'vp_base/js/com/com_Const',
19+
'vp_base/js/com/com_String',
20+
'vp_base/js/com/component/Component',
21+
'vp_base/js/com/component/LoadingSpinner'
22+
], function(hvHtml, ppCss, com_util, com_Const, com_String, Component, LoadingSpinner) {
23+
24+
/**
25+
* HelpViewer
26+
*/
27+
class HelpViewer extends Component {
28+
constructor() {
29+
super($(vpConfig.parentSelector), {}, {});
30+
}
31+
32+
_init() {
33+
this.position = {
34+
right: 10, top: 120
35+
};
36+
this.size = {
37+
width: 500,
38+
height: 500
39+
};
40+
}
41+
42+
43+
_bindEvent() {
44+
super._bindEvent();
45+
/** Implement binding events */
46+
let that = this;
47+
48+
$(that.wrapSelector('.vp-popup-maximize')).on('click', function() {
49+
// save position
50+
that.position = $(that.wrapSelector()).position();
51+
// save size
52+
that.size = {
53+
width: $(that.wrapSelector()).width(),
54+
height: $(that.wrapSelector()).height()
55+
}
56+
// maximize popup
57+
$(that.wrapSelector()).css({
58+
width: '100%',
59+
height: '100%',
60+
top: 0,
61+
left: 0
62+
});
63+
// show / hide buttons
64+
$(this).hide();
65+
$(that.wrapSelector('.vp-popup-return')).show();
66+
});
67+
68+
// Return operation
69+
$(this.wrapSelector('.vp-popup-return')).on('click', function(evt) {
70+
// return size
71+
$(that.wrapSelector()).css({
72+
width: that.size.width + 'px',
73+
height: that.size.height + 'px',
74+
top: that.position.top,
75+
left: that.position.left
76+
});
77+
// show / hide buttons
78+
$(this).hide();
79+
$(that.wrapSelector('.vp-popup-maximize')).show();
80+
});
81+
82+
$(that.wrapSelector('.vp-popup-close')).on('click', function() {
83+
that.remove();
84+
});
85+
86+
$(that.wrapSelector('.vp-popup-button')).on('click', function() {
87+
var btnType = $(this).data('type');
88+
switch(btnType) {
89+
case 'cancel':
90+
that.remove();
91+
break;
92+
}
93+
});
94+
95+
// Focus recognization
96+
$(this.wrapSelector()).on('click', function() {
97+
that.focus();
98+
});
99+
}
100+
101+
_bindDraggable() {
102+
var that = this;
103+
let containment = 'body';
104+
if (vpConfig.extensionType === 'lab' || vpConfig.extensionType === 'lite') {
105+
containment = '#main';
106+
}
107+
$(this.wrapSelector()).draggable({
108+
handle: '.vp-popup-title',
109+
containment: containment,
110+
start: function(evt, ui) {
111+
// check focused
112+
$(that.eventTarget).trigger({
113+
type: 'focus_option_page',
114+
component: that
115+
});
116+
}
117+
});
118+
}
119+
120+
_bindResizable() {
121+
let that = this;
122+
$(this.wrapSelector()).resizable({
123+
handles: 'all',
124+
start: function(evt, ui) {
125+
// show / hide buttons
126+
$(that.wrapSelector('.vp-popup-return')).hide();
127+
$(that.wrapSelector('.vp-popup-maximize')).show();
128+
}
129+
});
130+
}
131+
132+
template() {
133+
this.$pageDom = $(hvHtml);
134+
135+
return this.$pageDom;
136+
}
137+
138+
render() {
139+
super.render();
140+
141+
// set detailed size
142+
$(this.wrapSelector()).css({
143+
width: this.size.width + 'px',
144+
height: this.size.height + 'px'
145+
});
146+
147+
// position
148+
$(this.wrapSelector()).css({ top: this.position.top, right: this.position.right });
149+
150+
this._bindDraggable();
151+
this._bindResizable();
152+
}
153+
154+
wrapSelector(selector='') {
155+
var sbSelector = new com_String();
156+
var cnt = arguments.length;
157+
if (cnt < 2) {
158+
// if there's no more arguments
159+
sbSelector.appendFormat(".vp-popup-frame.{0} {1}", this.uuid, selector);
160+
} else {
161+
// if there's more arguments
162+
sbSelector.appendFormat(".vp-popup-frame.{0}", this.uuid);
163+
for (var idx = 0; idx < cnt; idx++) {
164+
sbSelector.appendFormat(" {0}", arguments[idx]);
165+
}
166+
}
167+
return sbSelector.toString();
168+
}
169+
170+
open(content, useHelp=true) {
171+
this.show();
172+
173+
let that = this;
174+
175+
let code = content;
176+
if (useHelp === true) {
177+
code = `print(help(${content}))`;
178+
}
179+
180+
let loadingSpinner = new LoadingSpinner($(this.wrapSelector('.vp-popup-body')));
181+
vpKernel.execute(code).then(function(resultObj) {
182+
let { result } = resultObj;
183+
184+
$(that.wrapSelector('#helpContent')).text(result);
185+
186+
}).catch(function(err) {
187+
vpLog.display(VP_LOG_TYPE.ERROR, err);
188+
}).finally(function() {
189+
loadingSpinner.remove();
190+
});
191+
192+
this.focus();
193+
}
194+
195+
generateCode() {
196+
return '';
197+
}
198+
199+
show() {
200+
$(this.wrapSelector()).show();
201+
}
202+
203+
remove() {
204+
$(this.wrapSelector()).remove();
205+
}
206+
207+
focus() {
208+
$('.vp-popup-frame').removeClass('vp-focused');
209+
$('.vp-popup-frame').css({ 'z-index': 1200 });
210+
$(this.wrapSelector()).addClass('vp-focused');
211+
$(this.wrapSelector()).css({ 'z-index': 1205 }); // move forward
212+
}
213+
214+
}
215+
216+
return HelpViewer;
217+
});

visualpython/js/com/component/PopupComponent.js

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ define([
6262
'../com_interface',
6363
'./Component',
6464
'./DataSelector',
65+
'./HelpViewer',
6566

6667
/** codemirror */
6768
'codemirror/lib/codemirror',
@@ -70,7 +71,7 @@ define([
7071
'codemirror/addon/display/autorefresh',
7172
// 'notebook/js/codemirror-ipython' // LAB: disabled to avoid error FIXME:
7273
], function(popupComponentHtml, popupComponentCss
73-
, com_util, com_Const, com_String, com_interface, Component, DataSelector, codemirror
74+
, com_util, com_Const, com_String, com_interface, Component, DataSelector, HelpViewer, codemirror
7475
) {
7576
'use strict';
7677

@@ -107,6 +108,7 @@ define([
107108
// show view box
108109
codeview: true,
109110
dataview: true,
111+
helpview: true,
110112
// show footer
111113
runButton: true,
112114
footer: true,
@@ -115,6 +117,10 @@ define([
115117
saveOnly: false, // apply mode
116118
checkModules: [], // module aliases or function names
117119
docs: 'https://visual-python.gitbook.io/docs/getting-started/welcome-to-visual-python',
120+
helpInfo: {
121+
content: '', // method to show using help() ex) pd.DataFrame
122+
useHelp: true // custom text to show on help viewer
123+
},
118124
...restConfig
119125
};
120126

@@ -145,8 +151,9 @@ define([
145151
}
146152

147153
this.cmCodeview = null;
148-
149154
this.cmCodeList = [];
155+
156+
this.helpViewer = undefined;
150157
}
151158

152159
wrapSelector(selector='') {
@@ -426,6 +433,14 @@ define([
426433
}
427434
evt.stopPropagation();
428435
break;
436+
case 'help':
437+
if ($(that.wrapSelector('.vp-popup-dataview-box')).is(':hidden')) {
438+
that.openView('help');
439+
} else {
440+
that.closeView('help');
441+
}
442+
evt.stopPropagation();
443+
break;
429444
case 'cancel':
430445
if (that.getTaskType() === 'task') {
431446
$(that.eventTarget).trigger({
@@ -919,6 +934,10 @@ define([
919934
return true;
920935
}
921936

937+
_beforeOpen() {
938+
/** Implementation needed - Generated on clicking Install Package button */
939+
}
940+
922941
/**
923942
* Open popup
924943
* - show popup
@@ -929,6 +948,7 @@ define([
929948
vpLog.display(VP_LOG_TYPE.DEVELOP, 'open popup', this);
930949
this.loadState();
931950

951+
this._beforeOpen();
932952
this.show();
933953

934954
// set popup position if its top-left side is outside of view
@@ -1052,7 +1072,7 @@ define([
10521072
* @param {*} viewType code / data
10531073
*/
10541074
openView(viewType) {
1055-
if (viewType == 'code') {
1075+
if (viewType === 'code') {
10561076
this.saveState();
10571077
var code = this.generateCode();
10581078
let codeText = '';
@@ -1069,12 +1089,22 @@ define([
10691089
that.cmCodeview.refresh();
10701090
}, 1);
10711091
$(this.wrapSelector('.vp-popup-dataview-box')).hide();
1072-
} else {
1092+
$(this.wrapSelector('.vp-popup-codeview-box')).show();
1093+
} else if (viewType === 'data') {
10731094
this.renderDataView();
10741095
$(this.wrapSelector('.vp-popup-codeview-box')).hide();
1096+
$(this.wrapSelector('.vp-popup-dataview-box')).show();
1097+
} else if (viewType === 'help') {
1098+
$(this.wrapSelector('.vp-popup-codeview-box')).hide();
1099+
$(this.wrapSelector('.vp-popup-dataview-box')).hide();
1100+
if (this.config.helpview === true) {
1101+
if (this.helpViewer !== undefined) {
1102+
this.helpViewer.remove();
1103+
}
1104+
this.helpViewer = new HelpViewer();
1105+
this.helpViewer.open(this.config.helpInfo.content, this.config.helpInfo.useHelp);
1106+
}
10751107
}
1076-
1077-
$(this.wrapSelector('.vp-popup-'+viewType+'view-box')).show();
10781108
}
10791109

10801110
closeView(viewType) {

0 commit comments

Comments
 (0)