mirror of
https://github.com/4ian/GDevelop.git
synced 2026-10-12 02:01:17 +00:00
Save the scroll position of JS code events when closing and opening tabs (#8417)
This commit is contained in:
@@ -73,8 +73,13 @@ void JsCodeEvent::UnserializeFrom(gd::Project& project,
|
||||
|
||||
JsCodeEvent::JsCodeEvent()
|
||||
: BaseEvent(),
|
||||
inlineCode("runtimeScene.setBackgroundColor(100,100,240);\n"),
|
||||
useStrict(true),
|
||||
eventsSheetExpanded(false) {}
|
||||
inlineCode("runtimeScene.setBackgroundColor(100,100,240);\n") {}
|
||||
|
||||
JsCodeEvent::JsCodeEvent(const JsCodeEvent &event): BaseEvent(event) {
|
||||
inlineCode = event.inlineCode;
|
||||
parameterObjects = event.parameterObjects;
|
||||
useStrict = event.useStrict;
|
||||
eventsSheetExpanded = event.eventsSheetExpanded;
|
||||
}
|
||||
|
||||
} // namespace gdjs
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
* 2008-2016 Florian Rival ([email protected])
|
||||
*/
|
||||
|
||||
#ifndef JSCODEEVENT_H
|
||||
#define JSCODEEVENT_H
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Project/MemoryTrackedRegistry.h"
|
||||
|
||||
namespace gd {
|
||||
class Instruction;
|
||||
class Project;
|
||||
@@ -50,18 +52,33 @@ class JsCodeEvent : public gd::BaseEvent {
|
||||
bool IsEventsSheetExpanded() const { return eventsSheetExpanded; }
|
||||
void SetEventsSheetExpanded(bool enable) { eventsSheetExpanded = enable; };
|
||||
|
||||
private:
|
||||
void Init(const JsCodeEvent& event);
|
||||
long GetScrollTop() const { return scrollTop; }
|
||||
void SetScrollTop(long value) { scrollTop = value; };
|
||||
|
||||
long GetCursorColumn() const { return cursorColumn; }
|
||||
void SetCursorColumn(long value) { cursorColumn = value; };
|
||||
|
||||
long GetCursorLine() const { return cursorLine; }
|
||||
void SetCursorLine(long value) { cursorLine = value; };
|
||||
|
||||
private:
|
||||
JsCodeEvent(const JsCodeEvent& event);
|
||||
|
||||
gd::String inlineCode; ///< Contains the Javascript code of the event.
|
||||
gd::Expression parameterObjects; ///< Name of the (group of) objects to pass as
|
||||
///< parameter.
|
||||
bool useStrict; ///< Should the generated JS function have "use strict". true
|
||||
///< by default. Should be removed once all the game engine
|
||||
///< is using "use strict".
|
||||
bool eventsSheetExpanded; ///< Is the code block expanded in the events sheet?
|
||||
bool useStrict = true; ///< Should the generated JS function have "use strict". true
|
||||
///< by default. Should be removed once all the game engine
|
||||
///< is using "use strict".
|
||||
bool eventsSheetExpanded = false; ///< Is the code block expanded in the events sheet?
|
||||
|
||||
// These members are not serialized.
|
||||
long scrollTop = 0;
|
||||
long cursorColumn = 0;
|
||||
long cursorLine = 0;
|
||||
|
||||
gd::MemoryTracked _memoryTracked{this, "JsCodeEvent"};
|
||||
};
|
||||
|
||||
} // namespace gdjs
|
||||
|
||||
#endif // JSCODEEVENT_H
|
||||
|
||||
@@ -4366,6 +4366,13 @@ interface JsCodeEvent {
|
||||
boolean IsFolded();
|
||||
void SetFolded(boolean folded);
|
||||
|
||||
long GetScrollTop();
|
||||
void SetScrollTop(long value);
|
||||
long GetCursorColumn();
|
||||
void SetCursorColumn(long value);
|
||||
long GetCursorLine();
|
||||
void SetCursorLine(long value);
|
||||
|
||||
void SerializeTo([Ref] SerializerElement element);
|
||||
void UnserializeFrom([Ref] Project project, [Const, Ref] SerializerElement element);
|
||||
};
|
||||
|
||||
@@ -563,6 +563,7 @@ patchClassesForUseAfterFreeDetection(Module, {
|
||||
'ObjectGroupsContainer',
|
||||
'ObjectsContainer',
|
||||
'VariablesContainer',
|
||||
'JsCodeEvent',
|
||||
]),
|
||||
verbose: false,
|
||||
});
|
||||
|
||||
Vendored
+6
@@ -3242,6 +3242,12 @@ export class JsCodeEvent extends EmscriptenObject {
|
||||
setDisabled(disable: boolean): void;
|
||||
isFolded(): boolean;
|
||||
setFolded(folded: boolean): void;
|
||||
getScrollTop(): number;
|
||||
setScrollTop(value: number): void;
|
||||
getCursorColumn(): number;
|
||||
setCursorColumn(value: number): void;
|
||||
getCursorLine(): number;
|
||||
setCursorLine(value: number): void;
|
||||
serializeTo(element: SerializerElement): void;
|
||||
unserializeFrom(project: Project, element: SerializerElement): void;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,12 @@ declare class gdJsCodeEvent extends gdBaseEvent {
|
||||
setDisabled(disable: boolean): void;
|
||||
isFolded(): boolean;
|
||||
setFolded(folded: boolean): void;
|
||||
getScrollTop(): number;
|
||||
setScrollTop(value: number): void;
|
||||
getCursorColumn(): number;
|
||||
setCursorColumn(value: number): void;
|
||||
getCursorLine(): number;
|
||||
setCursorLine(value: number): void;
|
||||
serializeTo(element: gdSerializerElement): void;
|
||||
unserializeFrom(project: gdProject, element: gdSerializerElement): void;
|
||||
delete(): void;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
diff --git a/node_modules/react-monaco-editor/lib/editor.js b/node_modules/react-monaco-editor/lib/editor.js
|
||||
index 8e6ae66..87205ba 100644
|
||||
--- a/node_modules/react-monaco-editor/lib/editor.js
|
||||
+++ b/node_modules/react-monaco-editor/lib/editor.js
|
||||
@@ -107,6 +107,13 @@ var MonacoEditor = function (_React$Component) {
|
||||
}
|
||||
});
|
||||
}
|
||||
+ }, {
|
||||
+ key: 'editorWillUnmount',
|
||||
+ value: function editorWillUnmount(editor) {
|
||||
+ var editorWillUnmount = this.props.editorWillUnmount;
|
||||
+
|
||||
+ editorWillUnmount(editor, monaco);
|
||||
+ }
|
||||
}, {
|
||||
key: 'initMonaco',
|
||||
value: function initMonaco() {
|
||||
@@ -134,6 +141,7 @@ var MonacoEditor = function (_React$Component) {
|
||||
key: 'destroyMonaco',
|
||||
value: function destroyMonaco() {
|
||||
if (typeof this.editor !== 'undefined') {
|
||||
+ this.editorWillUnmount(this.editor);
|
||||
this.editor.dispose();
|
||||
}
|
||||
}
|
||||
@@ -168,6 +176,7 @@ MonacoEditor.propTypes = {
|
||||
options: _propTypes2.default.object,
|
||||
editorDidMount: _propTypes2.default.func,
|
||||
editorWillMount: _propTypes2.default.func,
|
||||
+ editorWillUnmount: _propTypes2.default.func,
|
||||
onChange: _propTypes2.default.func
|
||||
};
|
||||
|
||||
@@ -181,6 +190,7 @@ MonacoEditor.defaultProps = {
|
||||
options: {},
|
||||
editorDidMount: noop,
|
||||
editorWillMount: noop,
|
||||
+ editorWillUnmount: noop,
|
||||
onChange: noop
|
||||
};
|
||||
|
||||
diff --git a/node_modules/react-monaco-editor/src/editor.js b/node_modules/react-monaco-editor/src/editor.js
|
||||
index 90ab4de..589dc40 100644
|
||||
--- a/node_modules/react-monaco-editor/src/editor.js
|
||||
+++ b/node_modules/react-monaco-editor/src/editor.js
|
||||
@@ -64,6 +64,13 @@ class MonacoEditor extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
+ // This is a backport from react-monaco-editor0.47.0 of https://github.com/react-monaco-editor/react-monaco-editor/pull/482
|
||||
+ // Starting from react-monaco-editor0.21.0 no language is registered for some reason.
|
||||
+ editorWillUnmount(editor) {
|
||||
+ const { editorWillUnmount } = this.props;
|
||||
+ editorWillUnmount(editor, monaco);
|
||||
+ }
|
||||
+
|
||||
initMonaco() {
|
||||
const value = this.props.value !== null ? this.props.value : this.props.defaultValue;
|
||||
const { language, theme, options } = this.props;
|
||||
@@ -85,6 +92,7 @@ class MonacoEditor extends React.Component {
|
||||
|
||||
destroyMonaco() {
|
||||
if (typeof this.editor !== 'undefined') {
|
||||
+ this.editorWillUnmount(this.editor);
|
||||
this.editor.dispose();
|
||||
}
|
||||
}
|
||||
@@ -116,6 +124,7 @@ MonacoEditor.propTypes = {
|
||||
options: PropTypes.object,
|
||||
editorDidMount: PropTypes.func,
|
||||
editorWillMount: PropTypes.func,
|
||||
+ editorWillUnmount: PropTypes.func,
|
||||
onChange: PropTypes.func
|
||||
};
|
||||
|
||||
@@ -129,6 +138,7 @@ MonacoEditor.defaultProps = {
|
||||
options: {},
|
||||
editorDidMount: noop,
|
||||
editorWillMount: noop,
|
||||
+ editorWillUnmount: noop,
|
||||
onChange: noop
|
||||
};
|
||||
|
||||
@@ -16,6 +16,14 @@ export type State = {|
|
||||
export type Props = {|
|
||||
value: string,
|
||||
onChange: string => void,
|
||||
initialScrollTop: number,
|
||||
initialCursorColumn: number,
|
||||
initialCursorLine: number,
|
||||
saveEditorState: ({
|
||||
scrollTop: number,
|
||||
cursorColumn: number,
|
||||
cursorLine: number,
|
||||
}) => void,
|
||||
width?: number,
|
||||
height?: number,
|
||||
onEditorMounted?: () => void,
|
||||
@@ -97,6 +105,12 @@ export class CodeEditor extends React.Component<Props, State> {
|
||||
setupAutocompletions(monaco);
|
||||
}
|
||||
|
||||
editor.setScrollTop(this.props.initialScrollTop);
|
||||
editor.setPosition({
|
||||
column: this.props.initialCursorColumn,
|
||||
lineNumber: this.props.initialCursorLine,
|
||||
});
|
||||
|
||||
if (this.props.onEditorMounted) this.props.onEditorMounted();
|
||||
};
|
||||
|
||||
@@ -140,6 +154,15 @@ export class CodeEditor extends React.Component<Props, State> {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
_saveEditorState = (editor: any, monaco: any) => {
|
||||
const cursorPosition = editor.getPosition();
|
||||
this.props.saveEditorState({
|
||||
scrollTop: editor.getScrollTop(),
|
||||
cursorColumn: cursorPosition.column,
|
||||
cursorLine: cursorPosition.lineNumber,
|
||||
});
|
||||
};
|
||||
|
||||
render(): any {
|
||||
const { MonacoEditor, error } = this.state;
|
||||
if (error) {
|
||||
@@ -174,6 +197,7 @@ export class CodeEditor extends React.Component<Props, State> {
|
||||
onChange={this.props.onChange}
|
||||
editorWillMount={this.setupEditorThemes}
|
||||
editorDidMount={this.setupEditorCompletions}
|
||||
editorWillUnmount={this._saveEditorState}
|
||||
options={{
|
||||
...monacoEditorOptions,
|
||||
fontSize: preferences.eventsSheetZoomLevel,
|
||||
|
||||
@@ -18,6 +18,8 @@ import { type ParameterFieldInterface } from '../../ParameterFields/ParameterFie
|
||||
import { Trans } from '@lingui/macro';
|
||||
import ChevronArrowTop from '../../../UI/CustomSvgIcons/ChevronArrowTop';
|
||||
import ChevronArrowBottom from '../../../UI/CustomSvgIcons/ChevronArrowBottom';
|
||||
import { exceptionallyGuardAgainstDeadObject } from '../../../Utils/IsNullPtr';
|
||||
|
||||
const gd: libGDevelop = global.gd;
|
||||
|
||||
const fontFamily = '"Lucida Console", Monaco, monospace';
|
||||
@@ -98,6 +100,26 @@ export default class JsCodeEvent extends React.Component<
|
||||
jsCodeEvent.setInlineCode(newValue);
|
||||
};
|
||||
|
||||
saveEditorState = ({
|
||||
scrollTop,
|
||||
cursorColumn,
|
||||
cursorLine,
|
||||
}: {
|
||||
scrollTop: number,
|
||||
cursorColumn: number,
|
||||
cursorLine: number,
|
||||
}): void => {
|
||||
const jsCodeEvent = exceptionallyGuardAgainstDeadObject(
|
||||
gd.asJsCodeEvent(this.props.event)
|
||||
);
|
||||
if (!jsCodeEvent) {
|
||||
return;
|
||||
}
|
||||
jsCodeEvent.setScrollTop(scrollTop);
|
||||
jsCodeEvent.setCursorColumn(cursorColumn);
|
||||
jsCodeEvent.setCursorLine(cursorLine);
|
||||
};
|
||||
|
||||
editObject = (domEvent: any) => {
|
||||
const jsCodeEvent = gd.asJsCodeEvent(this.props.event);
|
||||
const parameterObjects = jsCodeEvent.getParameterObjects();
|
||||
@@ -270,6 +292,10 @@ export default class JsCodeEvent extends React.Component<
|
||||
<CodeEditor
|
||||
value={jsCodeEvent.getInlineCode()}
|
||||
onChange={this.onChange}
|
||||
initialScrollTop={jsCodeEvent.getScrollTop()}
|
||||
initialCursorColumn={jsCodeEvent.getCursorColumn()}
|
||||
initialCursorLine={jsCodeEvent.getCursorLine()}
|
||||
saveEditorState={this.saveEditorState}
|
||||
width={contentRect.bounds.width - 5}
|
||||
height={this._getCodeEditorHeight()}
|
||||
onEditorMounted={() => {
|
||||
|
||||
@@ -30,6 +30,7 @@ const trackedClasses = [
|
||||
'ObjectGroupsContainer',
|
||||
'ObjectsContainer',
|
||||
'VariablesContainer',
|
||||
'JsCodeEvent',
|
||||
];
|
||||
|
||||
type Stats = {|
|
||||
|
||||
Reference in New Issue
Block a user