diff --git a/newIDE/app/src/CompactPropertiesEditor/TopLevelCollapsibleSection.js b/newIDE/app/src/CompactPropertiesEditor/TopLevelCollapsibleSection.js
new file mode 100644
index 000000000000..2c42658d376a
--- /dev/null
+++ b/newIDE/app/src/CompactPropertiesEditor/TopLevelCollapsibleSection.js
@@ -0,0 +1,77 @@
+// @flow
+
+import * as React from 'react';
+import Text from '../UI/Text';
+import { Separator } from '../CompactPropertiesEditor';
+import ShareExternal from '../UI/CustomSvgIcons/ShareExternal';
+import ChevronArrowDownWithRoundedBorder from '../UI/CustomSvgIcons/ChevronArrowDownWithRoundedBorder';
+import ChevronArrowRightWithRoundedBorder from '../UI/CustomSvgIcons/ChevronArrowRightWithRoundedBorder';
+import { Column, Line } from '../UI/Grid';
+import IconButton from '../UI/IconButton';
+import { LineStackLayout } from '../UI/Layout';
+import Add from '../UI/CustomSvgIcons/Add';
+import { textEllipsisStyle } from '../UI/TextEllipsis';
+import { styles } from '../ObjectEditor/CompactObjectPropertiesEditor';
+
+type Props = {
+ title: React.Node,
+ isFolded: boolean,
+ toggleFolded: () => void,
+ renderContent: () => React.Node,
+ renderContentAsHiddenWhenFolded?: boolean,
+ noContentMargin?: boolean,
+ onOpenFullEditor?: () => void,
+ onAdd?: (() => void) | null,
+};
+
+export const TopLevelCollapsibleSection = ({
+ title,
+ isFolded,
+ toggleFolded,
+ renderContent,
+ renderContentAsHiddenWhenFolded,
+ noContentMargin,
+ onOpenFullEditor,
+ onAdd,
+}: Props): React.Node => (
+ <>
+
+
+
+
+
+ {isFolded ? (
+
+ ) : (
+
+ )}
+
+
+ {title}
+
+
+
+ {onOpenFullEditor && (
+
+
+
+ )}
+ {onAdd && (
+
+
+
+ )}
+
+
+
+
+ {isFolded ? (
+ renderContentAsHiddenWhenFolded ? (
+ {renderContent()}
+ ) : null
+ ) : (
+ renderContent()
+ )}
+
+ >
+);
diff --git a/newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js b/newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js
index c30d8139fbd8..799e50845a13 100644
--- a/newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js
+++ b/newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js
@@ -9,7 +9,6 @@ import CompactPropertiesEditor, {
import propertiesMapToSchema from '../../PropertiesEditor/PropertiesMapToSchema';
import { type Schema } from '../../PropertiesEditor/PropertiesEditorSchema';
import getObjectByName from '../../Utils/GetObjectByName';
-import IconButton from '../../UI/IconButton';
import { Line, Column, Spacer, marginsSize } from '../../UI/Grid';
import Text from '../../UI/Text';
import { type UnsavedChanges } from '../../MainFrame/UnsavedChangesContext';
@@ -18,7 +17,6 @@ import EventsRootVariablesFinder from '../../Utils/EventsRootVariablesFinder';
import VariablesList, {
type HistoryHandler,
} from '../../VariablesList/VariablesList';
-import ShareExternal from '../../UI/CustomSvgIcons/ShareExternal';
import useForceUpdate from '../../Utils/UseForceUpdate';
import ErrorBoundary from '../../UI/ErrorBoundary';
import {
@@ -30,10 +28,10 @@ import TileSetVisualizer, {
type TileMapTileSelection,
} from '../TileSetVisualizer';
import {
- TopLevelCollapsibleSection,
CollapsibleSubPanel,
type TitleBarButton,
} from '../../ObjectEditor/CompactObjectPropertiesEditor';
+import { TopLevelCollapsibleSection } from '../../CompactPropertiesEditor/TopLevelCollapsibleSection';
import { ColumnStackLayout } from '../../UI/Layout';
import Link from '../../UI/Link';
import { IconContainer } from '../../UI/IconContainer';
@@ -41,6 +39,7 @@ import { getHelpLink } from '../../Utils/HelpLink';
import Window from '../../Utils/Window';
import { type ResourceManagementProps } from '../../ResourcesList/ResourceSource';
import { usePersistedScrollPosition } from '../../Utils/UsePersistedScrollPosition';
+import { usePersistedCollapsedSection } from '../../Utils/UsePersistedCollapsedSection';
import EmptyMessage from '../../UI/EmptyMessage';
import CompactInstanceBehaviorsEditorService from './CompactInstanceBehaviorsEditorService';
import { exceptionallyGuardAgainstDeadObject } from '../../Utils/IsNullPtr';
@@ -172,7 +171,7 @@ export const CompactInstancePropertiesEditor = ({
.map((instance: gdInitialInstance) => '' + instance.ptr)
.join(';');
- const persistedScrollId = React.useMemo(
+ const persistedPanelStateId = React.useMemo(
() => {
if (!instances.length || !scrollKey) return null;
@@ -193,9 +192,16 @@ export const CompactInstancePropertiesEditor = ({
project,
scrollViewRef,
scrollKey,
- persistedScrollId,
- persistedScrollType: 'instances-of-object',
+ persistedPanelStateId: persistedPanelStateId,
+ persistedPanelStateType: 'instances-of-object',
});
+ const { isSectionFolded, toggleSectionFolded } = usePersistedCollapsedSection(
+ {
+ project,
+ persistedPanelStateId: persistedPanelStateId,
+ persistedPanelStateType: 'instances-of-object',
+ }
+ );
const { object, instanceSchema, allVisibleBehaviors } = React.useMemo<{|
object?: gdObject,
@@ -521,52 +527,41 @@ export const CompactInstancePropertiesEditor = ({
/>
) : null}
{object && shouldDisplayVariablesList && variablesContainer ? (
- <>
-
-
-
-
- Instance Variables
-
-
- {
- editInstanceVariables(instance);
- }}
- >
-
-
-
-
-
-
- object && layout
- ? EventsRootVariablesFinder.findAllObjectVariables(
- project.getCurrentPlatform(),
- project,
- layout,
- object.getName()
- )
- : []
- }
- historyHandler={historyHandler}
- toolbarIconStyle={styles.icon}
- compactEmptyPlaceholderText={
- There are no variables on this instance.
- }
- isListLocked={true}
- />
- >
+ Instance Variables}
+ isFolded={isSectionFolded('variables')}
+ toggleFolded={() => toggleSectionFolded('variables')}
+ onOpenFullEditor={() => editInstanceVariables(instance)}
+ noContentMargin
+ renderContent={() => (
+
+ object && layout
+ ? EventsRootVariablesFinder.findAllObjectVariables(
+ project.getCurrentPlatform(),
+ project,
+ layout,
+ object.getName()
+ )
+ : []
+ }
+ historyHandler={historyHandler}
+ toolbarIconStyle={styles.icon}
+ compactEmptyPlaceholderText={
+ There are no variables on this instance.
+ }
+ isListLocked={true}
+ />
+ )}
+ />
) : null}
diff --git a/newIDE/app/src/LayersList/CompactLayerPropertiesEditor/CompactEffectsListEditor.js b/newIDE/app/src/LayersList/CompactLayerPropertiesEditor/CompactEffectsListEditor.js
index 80c6a0f9d329..792844a4df1f 100644
--- a/newIDE/app/src/LayersList/CompactLayerPropertiesEditor/CompactEffectsListEditor.js
+++ b/newIDE/app/src/LayersList/CompactLayerPropertiesEditor/CompactEffectsListEditor.js
@@ -23,10 +23,9 @@ import { getHelpLink } from '../../Utils/HelpLink';
import Window from '../../Utils/Window';
import Link from '../../UI/Link';
import { CompactPropertiesEditorByVisibility } from '../../CompactPropertiesEditor/CompactPropertiesEditorByVisibility';
-import {
- TopLevelCollapsibleSection,
- CollapsibleSubPanel,
-} from '../../ObjectEditor/CompactObjectPropertiesEditor';
+import { CollapsibleSubPanel } from '../../ObjectEditor/CompactObjectPropertiesEditor';
+import { TopLevelCollapsibleSection } from '../../CompactPropertiesEditor/TopLevelCollapsibleSection';
+import { usePersistedCollapsedSection } from '../../Utils/UsePersistedCollapsedSection';
export const styles = {
icon: {
@@ -68,6 +67,7 @@ type Props = {|
onEffectAdded: () => void,
layerRenderingType: '2d' | '3d',
target: 'object' | 'layer',
+ persistedPanelStateId: string,
|};
export const CompactEffectsListEditor = ({
@@ -82,9 +82,19 @@ export const CompactEffectsListEditor = ({
onEffectAdded,
layerRenderingType,
target,
+ persistedPanelStateId,
}: Props): React.Node => {
const forceUpdate = useForceUpdate();
- const [isEffectsFolded, setEffectsFolded] = React.useState(false);
+
+ const {
+ isSectionFolded,
+ toggleSectionFolded,
+ setSectionFolded,
+ } = usePersistedCollapsedSection({
+ project,
+ persistedPanelStateId: persistedPanelStateId,
+ persistedPanelStateType: 'layer',
+ });
// Effects:
const {
@@ -109,6 +119,27 @@ export const CompactEffectsListEditor = ({
const filteredEffectMetadata =
layerRenderingType === '3d' ? all3DEffectMetadata : all2DEffectMetadata;
+ const effects = mapFor(
+ 0,
+ effectsContainer.getEffectsCount(),
+ (index: number) => {
+ const effect: gdEffect = effectsContainer.getEffectAt(index);
+ const effectType = effect.getEffectType();
+ const effectMetadata = getEnumeratedEffectMetadata(
+ allEffectMetadata,
+ effectType
+ );
+ return { effect, effectMetadata };
+ }
+ ).filter(
+ ({ effectMetadata }) =>
+ !effectMetadata ||
+ (layerRenderingType !== '3d' &&
+ !effectMetadata.isMarkedAsOnlyWorkingFor3D) ||
+ (layerRenderingType !== '2d' &&
+ !effectMetadata.isMarkedAsOnlyWorkingFor2D)
+ );
+
return (
2D effects
)
}
- isFolded={isEffectsFolded}
- toggleFolded={() => setEffectsFolded(!isEffectsFolded)}
+ isFolded={isSectionFolded(layerRenderingType + '-effects')}
+ toggleFolded={() => toggleSectionFolded(layerRenderingType + '-effects')}
onOpenFullEditor={onOpenFullEditor}
- onAdd={() => addEffect(layerRenderingType === '3d')}
+ onAdd={() => {
+ addEffect(layerRenderingType === '3d');
+ setSectionFolded(layerRenderingType + '-effects', false);
+ }}
renderContent={() => (
- {effectsContainer.getEffectsCount() === 0 && (
+ {effects.length === 0 && (
{target === 'object' ? (
@@ -166,86 +200,71 @@ export const CompactEffectsListEditor = ({
)}
)}
- {mapFor(0, effectsContainer.getEffectsCount(), (index: number) => {
- const effect: gdEffect = effectsContainer.getEffectAt(index);
- const effectType = effect.getEffectType();
- const effectMetadata = getEnumeratedEffectMetadata(
- allEffectMetadata,
- effectType
- );
-
- return !effectMetadata ||
- (layerRenderingType !== '3d' &&
- !effectMetadata.isMarkedAsOnlyWorkingFor3D) ||
- (layerRenderingType !== '2d' &&
- !effectMetadata.isMarkedAsOnlyWorkingFor2D) ? (
- (
-
- chooseEffectType(effect, type)}
- >
- {filteredEffectMetadata.map(effectMetadata => (
-
- ))}
-
- {effectMetadata && (
- Nothing to configure for this effect.
+ {effects.map(({ effect, effectMetadata }) => (
+ (
+
+ chooseEffectType(effect, type)}
+ >
+ {filteredEffectMetadata.map(effectMetadata => (
+
- )}
-
- )}
- isFolded={effect.isFolded()}
- toggleFolded={() => {
- effect.setFolded(!effect.isFolded());
- forceUpdate();
- }}
- title={effect.getName()}
- titleBarButtons={[
- {
- id: 'effect-visibility',
- icon: effect.isEnabled()
- ? VisibilityIcon
- : VisibilityOffIcon,
- label: effect.isEnabled() ? t`Hide effect` : t`Show effect`,
- onClick: () => {
- effect.setEnabled(!effect.isEnabled());
- onEffectsUpdated();
- forceUpdate();
- },
+ ))}
+
+ {effectMetadata && (
+ Nothing to configure for this effect.
+ }
+ onRefreshAllFields={forceUpdate}
+ />
+ )}
+
+ )}
+ isFolded={effect.isFolded()}
+ toggleFolded={() => {
+ effect.setFolded(!effect.isFolded());
+ forceUpdate();
+ }}
+ title={effect.getName()}
+ titleBarButtons={[
+ {
+ id: 'effect-visibility',
+ icon: effect.isEnabled() ? VisibilityIcon : VisibilityOffIcon,
+ label: effect.isEnabled() ? t`Hide effect` : t`Show effect`,
+ onClick: () => {
+ effect.setEnabled(!effect.isEnabled());
+ onEffectsUpdated();
+ forceUpdate();
},
- {
- id: 'remove-effect',
- icon: RemoveIcon,
- label: t`Remove effect`,
- onClick: () => {
- removeEffect(effect);
- onEffectsUpdated();
- },
+ },
+ {
+ id: 'remove-effect',
+ icon: RemoveIcon,
+ label: t`Remove effect`,
+ onClick: () => {
+ removeEffect(effect);
+ onEffectsUpdated();
},
- ]}
- />
- ) : null;
- })}
+ },
+ ]}
+ />
+ ))}
)}
/>
diff --git a/newIDE/app/src/LayersList/CompactLayerPropertiesEditor/index.js b/newIDE/app/src/LayersList/CompactLayerPropertiesEditor/index.js
index 856b05ce14db..2aa580480290 100644
--- a/newIDE/app/src/LayersList/CompactLayerPropertiesEditor/index.js
+++ b/newIDE/app/src/LayersList/CompactLayerPropertiesEditor/index.js
@@ -23,7 +23,7 @@ import { type Schema } from '../../PropertiesEditor/PropertiesEditorSchema';
import { CompactEffectsListEditor } from './CompactEffectsListEditor';
import { useForceRecompute } from '../../Utils/UseForceUpdate';
import { usePersistedScrollPosition } from '../../Utils/UsePersistedScrollPosition';
-import { TopLevelCollapsibleSection } from '../../ObjectEditor/CompactObjectPropertiesEditor';
+import { TopLevelCollapsibleSection } from '../../CompactPropertiesEditor/TopLevelCollapsibleSection';
export const styles = {
icon: {
@@ -95,14 +95,14 @@ export const CompactLayerPropertiesEditor = ({
// Layers have no persistent UUID, so the name is used (like for scenes).
// The base layer has an empty name, so a placeholder is used instead.
- const persistedScrollId = layer.getName() || 'base-layer';
+ const persistedPanelStateId = layer.getName() || 'base-layer';
const onScroll = usePersistedScrollPosition({
project,
scrollViewRef,
scrollKey,
- persistedScrollId,
- persistedScrollType: 'layer',
+ persistedPanelStateId: persistedPanelStateId,
+ persistedPanelStateType: 'layer',
});
const layerPropertiesSchema = React.useMemo(
@@ -197,6 +197,7 @@ export const CompactLayerPropertiesEditor = ({
onEffectsUpdated={() => onLayersModified([layer])}
onOpenFullEditor={() => onEditLayerEffects(layer)}
onEffectAdded={onEffectAdded}
+ persistedPanelStateId={persistedPanelStateId}
/>
)}
{layer.getRenderingType() !== '2d' && !layer.isLightingLayer() && (
@@ -212,6 +213,7 @@ export const CompactLayerPropertiesEditor = ({
onEffectsUpdated={() => onLayersModified([layer])}
onOpenFullEditor={() => onEditLayerEffects(layer)}
onEffectAdded={onEffectAdded}
+ persistedPanelStateId={persistedPanelStateId}
/>
)}
diff --git a/newIDE/app/src/MainFrame/Preferences/PreferencesContext.js b/newIDE/app/src/MainFrame/Preferences/PreferencesContext.js
index d6907770f3e8..b40883ee54ea 100644
--- a/newIDE/app/src/MainFrame/Preferences/PreferencesContext.js
+++ b/newIDE/app/src/MainFrame/Preferences/PreferencesContext.js
@@ -177,7 +177,14 @@ export const allAlertMessages: Array<{
*/
export type EditorStateForProject = {|
editorTabs: EditorTabsPersistedState | null,
- propertiesPanelScroll: { [string]: { [string]: number } },
+ propertiesPanel: {
+ [string]: {
+ [string]: {
+ scrollPosition: number,
+ collapsedSections: { [string]: boolean },
+ },
+ },
+ },
|};
// $FlowFixMe[deprecated-utility]
diff --git a/newIDE/app/src/MainFrame/Preferences/PreferencesProvider.js b/newIDE/app/src/MainFrame/Preferences/PreferencesProvider.js
index 6720e3fa41fe..5635635ec9ee 100644
--- a/newIDE/app/src/MainFrame/Preferences/PreferencesProvider.js
+++ b/newIDE/app/src/MainFrame/Preferences/PreferencesProvider.js
@@ -1303,7 +1303,7 @@ export default class PreferencesProvider extends React.Component {
return {
editorTabs:
editorState.editorTabs == null ? null : editorState.editorTabs,
- propertiesPanelScroll: editorState.propertiesPanelScroll || {},
+ propertiesPanel: editorState.propertiesPanel || {},
};
}
@@ -1324,7 +1324,7 @@ export default class PreferencesProvider extends React.Component {
projectId
] || {
editorTabs: null,
- propertiesPanelScroll: {},
+ propertiesPanel: {},
};
const mergedEditorState: EditorStateForProject = {
...previousEditorState,
diff --git a/newIDE/app/src/ObjectEditor/CompactObjectPropertiesEditor/index.js b/newIDE/app/src/ObjectEditor/CompactObjectPropertiesEditor/index.js
index b3aa34ee8bb9..21cd63d27141 100644
--- a/newIDE/app/src/ObjectEditor/CompactObjectPropertiesEditor/index.js
+++ b/newIDE/app/src/ObjectEditor/CompactObjectPropertiesEditor/index.js
@@ -11,10 +11,8 @@ import { type ProjectScopedContainersAccessor } from '../../InstructionOrExpress
import ErrorBoundary from '../../UI/ErrorBoundary';
import ScrollView, { type ScrollViewInterface } from '../../UI/ScrollView';
import { Column, Line, Spacer, marginsSize } from '../../UI/Grid';
-import { Separator } from '../../CompactPropertiesEditor';
import Text from '../../UI/Text';
import IconButton from '../../UI/IconButton';
-import ShareExternal from '../../UI/CustomSvgIcons/ShareExternal';
import EventsRootVariablesFinder from '../../Utils/EventsRootVariablesFinder';
import { type ObjectEditorTab } from '../../ObjectEditor/ObjectEditorDialog';
import CompactBehaviorsEditorService from './CompactBehaviorsEditorService';
@@ -26,8 +24,6 @@ import RemoveIcon from '../../UI/CustomSvgIcons/Remove';
import useForceUpdate from '../../Utils/UseForceUpdate';
import ChevronArrowRight from '../../UI/CustomSvgIcons/ChevronArrowRight';
import ChevronArrowBottom from '../../UI/CustomSvgIcons/ChevronArrowBottom';
-import ChevronArrowDownWithRoundedBorder from '../../UI/CustomSvgIcons/ChevronArrowDownWithRoundedBorder';
-import ChevronArrowRightWithRoundedBorder from '../../UI/CustomSvgIcons/ChevronArrowRightWithRoundedBorder';
import Add from '../../UI/CustomSvgIcons/Add';
import Trash from '../../UI/CustomSvgIcons/Trash';
import Edit from '../../UI/CustomSvgIcons/ShareExternal';
@@ -37,6 +33,7 @@ import Object3d from '../../UI/CustomSvgIcons/Object3d';
import Object2d from '../../UI/CustomSvgIcons/Object2d';
import { mapFor } from '../../Utils/MapFor';
import { usePersistedScrollPosition } from '../../Utils/UsePersistedScrollPosition';
+import { usePersistedCollapsedSection } from '../../Utils/UsePersistedCollapsedSection';
import CompactSelectField from '../../UI/CompactSelectField';
import SelectOption from '../../UI/SelectOption';
import { ChildObjectPropertiesEditor } from './ChildObjectPropertiesEditor';
@@ -67,6 +64,7 @@ import {
type FieldChoices,
} from '../../PropertiesEditor/PropertiesEditorSchema';
import useVariablesContainerRefactoring from '../../VariablesList/useVariablesContainerRefactoring';
+import { TopLevelCollapsibleSection } from '../../CompactPropertiesEditor/TopLevelCollapsibleSection';
const gd: libGDevelop = global.gd;
@@ -165,67 +163,6 @@ export const CollapsibleSubPanel = ({
);
-export const TopLevelCollapsibleSection = ({
- title,
- isFolded,
- toggleFolded,
- renderContent,
- renderContentAsHiddenWhenFolded,
- noContentMargin,
- onOpenFullEditor,
- onAdd,
-}: {|
- title: React.Node,
- isFolded: boolean,
- toggleFolded: () => void,
- renderContent: () => React.Node,
- renderContentAsHiddenWhenFolded?: boolean,
- noContentMargin?: boolean,
- onOpenFullEditor?: () => void,
- onAdd?: (() => void) | null,
-|}): React.Node => (
- <>
-
-
-
-
-
- {isFolded ? (
-
- ) : (
-
- )}
-
-
- {title}
-
-
-
- {onOpenFullEditor && (
-
-
-
- )}
- {onAdd && (
-
-
-
- )}
-
-
-
-
- {isFolded ? (
- renderContentAsHiddenWhenFolded ? (
- {renderContent()}
- ) : null
- ) : (
- renderContent()
- )}
-
- >
-);
-
const resourcesPreloadingFieldChoices: Array = [
{
value: 'with-scene',
@@ -322,9 +259,6 @@ export const CompactObjectPropertiesEditor = ({
isBehaviorListLocked,
}: Props): React.Node => {
const forceUpdate = useForceUpdate();
- const [isPropertiesFolded, setIsPropertiesFolded] = React.useState(false);
- const [isBehaviorsFolded, setIsBehaviorsFolded] = React.useState(false);
- const [isVariablesFolded, setIsVariablesFolded] = React.useState(false);
const [newVariantDialogOpen, setNewVariantDialogOpen] = React.useState(false);
const [
duplicateAndEditVariantDialogOpen,
@@ -540,14 +474,23 @@ export const CompactObjectPropertiesEditor = ({
.map((instance: gdObject) => '' + instance.ptr)
.join(';');
- const persistedScrollId = object.getPersistentUuid();
+ const persistedPanelStateId = object.getPersistentUuid();
const onScroll = usePersistedScrollPosition({
project,
scrollViewRef,
scrollKey,
- persistedScrollId,
- persistedScrollType: 'object',
+ persistedPanelStateId: persistedPanelStateId,
+ persistedPanelStateType: 'object',
+ });
+ const {
+ isSectionFolded,
+ setSectionFolded,
+ toggleSectionFolded,
+ } = usePersistedCollapsedSection({
+ project,
+ persistedPanelStateId: persistedPanelStateId,
+ persistedPanelStateType: 'object',
});
// Variable refactoring: snapshot on object selection, apply on deselection/unmount.
@@ -655,8 +598,8 @@ export const CompactObjectPropertiesEditor = ({
Properties}
- isFolded={isPropertiesFolded}
- toggleFolded={() => setIsPropertiesFolded(!isPropertiesFolded)}
+ isFolded={isSectionFolded('properties')}
+ toggleFolded={() => toggleSectionFolded('properties')}
onOpenFullEditor={openFullEditor}
renderContent={() => (
@@ -808,8 +751,8 @@ export const CompactObjectPropertiesEditor = ({
/>
Behaviors}
- isFolded={isBehaviorsFolded}
- toggleFolded={() => setIsBehaviorsFolded(!isBehaviorsFolded)}
+ isFolded={isSectionFolded('behaviors')}
+ toggleFolded={() => toggleSectionFolded('behaviors')}
onOpenFullEditor={() => onEditObject(object, 'behaviors')}
onAdd={isBehaviorListLocked ? null : openNewBehaviorDialog}
renderContent={() => (
@@ -891,8 +834,8 @@ export const CompactObjectPropertiesEditor = ({
{variablesContainer && (
Object Variables}
- isFolded={isVariablesFolded}
- toggleFolded={() => setIsVariablesFolded(!isVariablesFolded)}
+ isFolded={isSectionFolded('variables')}
+ toggleFolded={() => toggleSectionFolded('variables')}
onOpenFullEditor={() => onEditObject(object, 'variables')}
onAdd={
isVariableListLocked
@@ -901,7 +844,7 @@ export const CompactObjectPropertiesEditor = ({
if (variablesListRef.current) {
variablesListRef.current.addVariable();
}
- setIsVariablesFolded(false);
+ setSectionFolded('variables', false);
}
}
renderContentAsHiddenWhenFolded={
@@ -968,6 +911,7 @@ export const CompactObjectPropertiesEditor = ({
onEffectsUpdated={() => onObjectsModified([object])}
onOpenFullEditor={() => onEditObject(object, 'effects')}
onEffectAdded={onEffectAdded}
+ persistedPanelStateId={persistedPanelStateId}
/>
)}
diff --git a/newIDE/app/src/ObjectGroupEditor/CompactObjectGroupPropertiesEditor.js b/newIDE/app/src/ObjectGroupEditor/CompactObjectGroupPropertiesEditor.js
index 6ef7b771df99..d76e5b04c8ba 100644
--- a/newIDE/app/src/ObjectGroupEditor/CompactObjectGroupPropertiesEditor.js
+++ b/newIDE/app/src/ObjectGroupEditor/CompactObjectGroupPropertiesEditor.js
@@ -17,6 +17,7 @@ import { ColumnStackLayout, LineStackLayout } from '../UI/Layout';
import useForceUpdate from '../Utils/UseForceUpdate';
import ObjectGroup from '../UI/CustomSvgIcons/ObjectGroup';
import { usePersistedScrollPosition } from '../Utils/UsePersistedScrollPosition';
+import { usePersistedCollapsedSection } from '../Utils/UsePersistedCollapsedSection';
import Help from '../UI/CustomSvgIcons/Help';
import { getHelpLink } from '../Utils/HelpLink';
import Window from '../Utils/Window';
@@ -25,10 +26,8 @@ import Link from '../UI/Link';
import useVariablesContainerRefactoring from '../VariablesList/useVariablesContainerRefactoring';
import { type ObjectGroupEditorTab } from './EditedObjectGroupEditorDialog';
import CompactObjectGroupEditor from './CompactObjectGroupEditor';
-import {
- TopLevelCollapsibleSection,
- CollapsibleSubPanel,
-} from '../ObjectEditor/CompactObjectPropertiesEditor';
+import { CollapsibleSubPanel } from '../ObjectEditor/CompactObjectPropertiesEditor';
+import { TopLevelCollapsibleSection } from '../CompactPropertiesEditor/TopLevelCollapsibleSection';
import { useManageObjectBehaviors } from '../BehaviorsEditor';
import CompactBehaviorsEditorService from '../ObjectEditor/CompactObjectPropertiesEditor/CompactBehaviorsEditorService';
import { IconContainer } from '../UI/IconContainer';
@@ -121,9 +120,6 @@ export const CompactObjectGroupPropertiesEditor = ({
}: Props): React.Node => {
const forceUpdate = useForceUpdate();
const { isMobile } = useResponsiveWindowSize();
- const [isObjectsFolded, setIsObjectsFolded] = React.useState(false);
- const [isVariablesFolded, setIsVariablesFolded] = React.useState(false);
- const [isBehaviorsFolded, setIsBehaviorsFolded] = React.useState(false);
const variablesListRef = React.useRef(null);
const groupVariablesContainer = React.useMemo(
@@ -147,14 +143,23 @@ export const CompactObjectGroupPropertiesEditor = ({
// Object groups have no persistent UUID, so the name is used
// (like for scenes).
- const persistedScrollId = objectGroup.getName();
+ const persistedPanelStateId = objectGroup.getName();
const onScroll = usePersistedScrollPosition({
project,
scrollViewRef,
scrollKey,
- persistedScrollId,
- persistedScrollType: 'objectGroup',
+ persistedPanelStateId: persistedPanelStateId,
+ persistedPanelStateType: 'objectGroup',
+ });
+ const {
+ isSectionFolded,
+ setSectionFolded,
+ toggleSectionFolded,
+ } = usePersistedCollapsedSection({
+ project,
+ persistedPanelStateId,
+ persistedPanelStateType: 'objectGroup',
});
const objects: Array = mapVector(
@@ -310,8 +315,8 @@ export const CompactObjectGroupPropertiesEditor = ({
Objects}
- isFolded={isObjectsFolded}
- toggleFolded={() => setIsObjectsFolded(!isObjectsFolded)}
+ isFolded={isSectionFolded('objects')}
+ toggleFolded={() => toggleSectionFolded('objects')}
onOpenFullEditor={openFullEditor}
renderContent={() => (
@@ -334,8 +339,8 @@ export const CompactObjectGroupPropertiesEditor = ({
/>
Behaviors}
- isFolded={isBehaviorsFolded}
- toggleFolded={() => setIsBehaviorsFolded(!isBehaviorsFolded)}
+ isFolded={isSectionFolded('behaviors')}
+ toggleFolded={() => toggleSectionFolded('behaviors')}
onOpenFullEditor={undefined}
onAdd={isBehaviorListLocked ? null : openNewBehaviorDialog}
renderContent={() => (
@@ -417,8 +422,8 @@ export const CompactObjectGroupPropertiesEditor = ({
/>
Object Variables}
- isFolded={isVariablesFolded}
- toggleFolded={() => setIsVariablesFolded(!isVariablesFolded)}
+ isFolded={isSectionFolded('variables')}
+ toggleFolded={() => toggleSectionFolded('variables')}
onOpenFullEditor={() =>
onEditObjectGroup(objectGroup, 'variables')
}
@@ -429,7 +434,7 @@ export const CompactObjectGroupPropertiesEditor = ({
if (variablesListRef.current) {
variablesListRef.current.addVariable();
}
- setIsVariablesFolded(false);
+ setSectionFolded('variables', false);
}
}
renderContentAsHiddenWhenFolded={
diff --git a/newIDE/app/src/SceneEditor/CompactScenePropertiesEditor/index.js b/newIDE/app/src/SceneEditor/CompactScenePropertiesEditor/index.js
index d417544fa49e..cfb78f4b914b 100644
--- a/newIDE/app/src/SceneEditor/CompactScenePropertiesEditor/index.js
+++ b/newIDE/app/src/SceneEditor/CompactScenePropertiesEditor/index.js
@@ -15,16 +15,15 @@ import { Trans } from '@lingui/macro';
import IconButton from '../../UI/IconButton';
import EventsRootVariablesFinder from '../../Utils/EventsRootVariablesFinder';
import { CompactBehaviorSharedDataPropertiesEditor } from './CompactBehaviorSharedDataPropertiesEditor';
-import {
- TopLevelCollapsibleSection,
- CollapsibleSubPanel,
-} from '../../ObjectEditor/CompactObjectPropertiesEditor';
+import { CollapsibleSubPanel } from '../../ObjectEditor/CompactObjectPropertiesEditor';
+import { TopLevelCollapsibleSection } from '../../CompactPropertiesEditor/TopLevelCollapsibleSection';
import { type ResourceManagementProps } from '../../ResourcesList/ResourceSource';
import { ColumnStackLayout, LineStackLayout } from '../../UI/Layout';
import { IconContainer } from '../../UI/IconContainer';
import useForceUpdate from '../../Utils/UseForceUpdate';
import SceneIcon from '../../UI/CustomSvgIcons/Scene';
import { usePersistedScrollPosition } from '../../Utils/UsePersistedScrollPosition';
+import { usePersistedCollapsedSection } from '../../Utils/UsePersistedCollapsedSection';
import Help from '../../UI/CustomSvgIcons/Help';
import { getHelpLink } from '../../Utils/HelpLink';
import Window from '../../Utils/Window';
@@ -90,9 +89,6 @@ export const CompactScenePropertiesEditor = ({
historyHandler,
}: Props): React.Node => {
const forceUpdate = useForceUpdate();
- const [isPropertiesFolded, setIsPropertiesFolded] = React.useState(false);
- const [isBehaviorsFolded, setIsBehaviorsFolded] = React.useState(false);
- const [isVariablesFolded, setIsVariablesFolded] = React.useState(false);
const variablesListRef = React.useRef(null);
const allVisibleBehaviors = scene
@@ -113,14 +109,23 @@ export const CompactScenePropertiesEditor = ({
const scrollViewRef = React.useRef(null);
const scrollKey = 'scene-' + scene.ptr;
- const persistedScrollId = scene.getName();
+ const persistedPanelStateId = scene.getName();
const onScroll = usePersistedScrollPosition({
project,
scrollViewRef,
scrollKey,
- persistedScrollId,
- persistedScrollType: 'scene',
+ persistedPanelStateId,
+ persistedPanelStateType: 'scene',
+ });
+ const {
+ isSectionFolded,
+ setSectionFolded,
+ toggleSectionFolded,
+ } = usePersistedCollapsedSection({
+ project,
+ persistedPanelStateId,
+ persistedPanelStateType: 'scene',
});
// Variable refactoring: snapshot on mount, apply on unmount/scene change.
@@ -188,8 +193,8 @@ export const CompactScenePropertiesEditor = ({
Properties}
- isFolded={isPropertiesFolded}
- toggleFolded={() => setIsPropertiesFolded(!isPropertiesFolded)}
+ isFolded={isSectionFolded('properties')}
+ toggleFolded={() => toggleSectionFolded('properties')}
renderContent={() => (
0 && (
Behaviors}
- isFolded={isBehaviorsFolded}
- toggleFolded={() => setIsBehaviorsFolded(!isBehaviorsFolded)}
+ isFolded={isSectionFolded('behaviors')}
+ toggleFolded={() => toggleSectionFolded('behaviors')}
renderContent={() => (
{allVisibleBehaviors.map(behaviorSharedData => {
@@ -271,14 +276,14 @@ export const CompactScenePropertiesEditor = ({
)}
Scene Variables}
- isFolded={isVariablesFolded}
- toggleFolded={() => setIsVariablesFolded(!isVariablesFolded)}
+ isFolded={isSectionFolded('variables')}
+ toggleFolded={() => toggleSectionFolded('variables')}
onOpenFullEditor={() => openSceneVariables()}
onAdd={() => {
if (variablesListRef.current) {
variablesListRef.current.addVariable();
}
- setIsVariablesFolded(false);
+ setSectionFolded('variables', false);
}}
renderContentAsHiddenWhenFolded={
true /* Allows to keep a ref to the variables list for add button to work. */
diff --git a/newIDE/app/src/Utils/UsePersistedCollapsedSection.js b/newIDE/app/src/Utils/UsePersistedCollapsedSection.js
new file mode 100644
index 000000000000..622f79a3d997
--- /dev/null
+++ b/newIDE/app/src/Utils/UsePersistedCollapsedSection.js
@@ -0,0 +1,92 @@
+// @flow
+import * as React from 'react';
+import PreferencesContext from '../MainFrame/Preferences/PreferencesContext';
+
+type Props = {|
+ project: gdProject,
+ persistedPanelStateType:
+ | 'instances-of-object'
+ | 'object'
+ | 'scene'
+ | 'objectGroup'
+ | 'layer',
+ persistedPanelStateId: string | null,
+|};
+
+export const usePersistedCollapsedSection = ({
+ project,
+ persistedPanelStateType,
+ persistedPanelStateId,
+}: Props): {
+ isSectionFolded: (sectionId: string) => boolean,
+ setSectionFolded: (sectionId: string, isCollapsed: boolean) => void,
+ toggleSectionFolded: (sectionId: string) => void,
+} => {
+ const {
+ getEditorStateForProject,
+ setEditorStateForProject,
+ } = React.useContext(PreferencesContext);
+ const projectId = project.getProjectUuid();
+
+ const isSectionFolded = React.useCallback(
+ (sectionId: string): boolean => {
+ const editorStateForProject = getEditorStateForProject(projectId);
+ if (!editorStateForProject || !persistedPanelStateId) return false;
+
+ return editorStateForProject.propertiesPanel[persistedPanelStateType]?.[
+ persistedPanelStateId
+ ]?.collapsedSections[sectionId];
+ },
+ [
+ getEditorStateForProject,
+ persistedPanelStateId,
+ persistedPanelStateType,
+ projectId,
+ ]
+ );
+
+ const setSectionFolded = React.useCallback(
+ (sectionId: string, isCollapsed: boolean): void => {
+ if (!persistedPanelStateId) return;
+
+ const currentEditorState = getEditorStateForProject(projectId);
+ setEditorStateForProject(projectId, {
+ propertiesPanel: {
+ ...currentEditorState?.propertiesPanel,
+ [persistedPanelStateType]: {
+ ...currentEditorState?.propertiesPanel[persistedPanelStateType],
+ [persistedPanelStateId]: {
+ ...currentEditorState?.propertiesPanel[persistedPanelStateType]?.[
+ persistedPanelStateId
+ ],
+ collapsedSections: {
+ ...currentEditorState?.propertiesPanel[
+ persistedPanelStateType
+ ]?.[persistedPanelStateId]?.collapsedSections,
+ [sectionId]: isCollapsed,
+ },
+ },
+ },
+ },
+ });
+ },
+ [
+ getEditorStateForProject,
+ persistedPanelStateId,
+ persistedPanelStateType,
+ projectId,
+ setEditorStateForProject,
+ ]
+ );
+
+ const toggleSectionFolded = React.useCallback(
+ (sectionId: string) =>
+ setSectionFolded(sectionId, !isSectionFolded(sectionId)),
+ [isSectionFolded, setSectionFolded]
+ );
+
+ return React.useMemo(
+ () => ({ isSectionFolded, setSectionFolded, toggleSectionFolded }),
+ [isSectionFolded, setSectionFolded, toggleSectionFolded]
+ );
+};
diff --git a/newIDE/app/src/Utils/UsePersistedScrollPosition.js b/newIDE/app/src/Utils/UsePersistedScrollPosition.js
index 1a6d03771edf..2fe26a5e4d08 100644
--- a/newIDE/app/src/Utils/UsePersistedScrollPosition.js
+++ b/newIDE/app/src/Utils/UsePersistedScrollPosition.js
@@ -7,13 +7,13 @@ type Props = {|
project: gdProject,
scrollViewRef: {| current: ?ScrollViewInterface |},
scrollKey: string,
- persistedScrollType:
+ persistedPanelStateType:
| 'instances-of-object'
| 'object'
| 'scene'
| 'objectGroup'
| 'layer',
- persistedScrollId: string | null,
+ persistedPanelStateId: string | null,
saveDebounceTimeInMs?: number,
|};
@@ -21,8 +21,8 @@ export const usePersistedScrollPosition = ({
project,
scrollViewRef,
scrollKey,
- persistedScrollType,
- persistedScrollId,
+ persistedPanelStateType,
+ persistedPanelStateId,
saveDebounceTimeInMs = 300,
}: Props): (() => void) => {
const {
@@ -45,16 +45,16 @@ export const usePersistedScrollPosition = ({
React.useLayoutEffect(
() => {
const scrollView = scrollViewRef.current;
- if (!persistedScrollId || !scrollView) {
+ if (!persistedPanelStateId || !scrollView) {
return;
}
const editorStateForProject = getEditorStateForProject(projectId);
if (!editorStateForProject) return;
const scrollPosition =
- editorStateForProject.propertiesPanelScroll[persistedScrollType]?.[
- persistedScrollId
- ];
+ editorStateForProject.propertiesPanel[persistedPanelStateType]?.[
+ persistedPanelStateId
+ ]?.scrollPosition;
if (!Number.isFinite(scrollPosition)) {
return;
}
@@ -63,18 +63,18 @@ export const usePersistedScrollPosition = ({
},
[
getEditorStateForProject,
- persistedScrollId,
- persistedScrollType,
+ persistedPanelStateId,
+ persistedPanelStateType,
projectId,
scrollKey,
scrollViewRef,
]
);
- return React.useCallback(
+ const onScroll = React.useCallback(
() => {
const scrollView = scrollViewRef.current;
- if (!scrollView || !persistedScrollId) return;
+ if (!scrollView || !persistedPanelStateId) return;
if (saveScrollTimeoutId.current) {
clearTimeout(saveScrollTimeoutId.current);
}
@@ -83,11 +83,16 @@ export const usePersistedScrollPosition = ({
const currentEditorState = getEditorStateForProject(projectId);
setEditorStateForProject(projectId, {
- propertiesPanelScroll: {
- ...currentEditorState?.propertiesPanelScroll,
- [persistedScrollType]: {
- ...currentEditorState?.propertiesPanelScroll[persistedScrollType],
- [persistedScrollId]: scrollView.getScrollPosition(),
+ propertiesPanel: {
+ ...currentEditorState?.propertiesPanel,
+ [persistedPanelStateType]: {
+ ...currentEditorState?.propertiesPanel[persistedPanelStateType],
+ [persistedPanelStateId]: {
+ ...currentEditorState?.propertiesPanel[
+ persistedPanelStateType
+ ]?.[persistedPanelStateId],
+ scrollPosition: scrollView.getScrollPosition(),
+ },
},
},
});
@@ -95,12 +100,14 @@ export const usePersistedScrollPosition = ({
},
[
getEditorStateForProject,
- persistedScrollId,
- persistedScrollType,
+ persistedPanelStateId,
+ persistedPanelStateType,
projectId,
saveDebounceTimeInMs,
scrollViewRef,
setEditorStateForProject,
]
);
+
+ return onScroll;
};