Skip to content

Commit 34cf5da

Browse files
Improve navigation shortcuts in Resources List tab
1 parent 675a58e commit 34cf5da

File tree

8 files changed

+217
-42
lines changed

8 files changed

+217
-42
lines changed

Core/GDCore/Project/ResourcesContainer.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,20 @@ ResourcesContainer::GetResourcePosition(const gd::String &name) const {
311311
return gd::String::npos;
312312
}
313313

314+
Resource &ResourcesContainer::GetResourceAt(std::size_t index) {
315+
if (index < resources.size())
316+
return *resources[index];
317+
318+
return badResource;
319+
}
320+
321+
const Resource &ResourcesContainer::GetResourceAt(std::size_t index) const {
322+
if (index < resources.size())
323+
return *resources[index];
324+
325+
return badResource;
326+
}
327+
314328
void ResourcesContainer::MoveResource(std::size_t oldIndex,
315329
std::size_t newIndex) {
316330
if (oldIndex >= resources.size() || newIndex >= resources.size())

Core/GDCore/Project/ResourcesContainer.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,16 @@ class GD_CORE_API ResourcesContainer {
737737
*/
738738
std::size_t GetResourcePosition(const gd::String &name) const;
739739

740+
/**
741+
* \brief Return a reference to the resource at the specified position.
742+
*/
743+
Resource &GetResourceAt(std::size_t index);
744+
745+
/**
746+
* \brief Return a reference to the resource at the specified position.
747+
*/
748+
const Resource &GetResourceAt(std::size_t index) const;
749+
740750
/**
741751
* \brief Move a resource up in the list
742752
*/

GDevelop.js/Bindings/Bindings.idl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,12 +1336,14 @@ interface ResourcesContainer {
13361336
[Value] VectorString FindFilesNotInResources([Const, Ref] VectorString filesToCheck);
13371337
boolean HasResource([Const] DOMString name);
13381338
[Const, Ref] Resource GetResource([Const] DOMString name);
1339+
[Const, Ref] Resource GetResourceAt(unsigned long index);
13391340
[Const, Ref] DOMString GetResourceNameWithOrigin([Const] DOMString originName, [Const] DOMString originIdentifier);
13401341
[Const, Ref] DOMString GetResourceNameWithFile([Const] DOMString file);
13411342
boolean AddResource([Const, Ref] Resource res);
13421343
void RemoveResource([Const] DOMString name);
13431344
void RenameResource([Const] DOMString oldName, [Const] DOMString name);
13441345
unsigned long GetResourcePosition([Const] DOMString name);
1346+
unsigned long Count();
13451347
boolean MoveResourceUpInList([Const] DOMString oldName);
13461348
boolean MoveResourceDownInList([Const] DOMString oldName);
13471349
void MoveResource(unsigned long oldIndex, unsigned long newIndex);

GDevelop.js/types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,12 +1125,14 @@ export class ResourcesContainer extends EmscriptenObject {
11251125
findFilesNotInResources(filesToCheck: VectorString): VectorString;
11261126
hasResource(name: string): boolean;
11271127
getResource(name: string): Resource;
1128+
getResourceAt(index: number): Resource;
11281129
getResourceNameWithOrigin(originName: string, originIdentifier: string): string;
11291130
getResourceNameWithFile(file: string): string;
11301131
addResource(res: Resource): boolean;
11311132
removeResource(name: string): void;
11321133
renameResource(oldName: string, name: string): void;
11331134
getResourcePosition(name: string): number;
1135+
count(): number;
11341136
moveResourceUpInList(oldName: string): boolean;
11351137
moveResourceDownInList(oldName: string): boolean;
11361138
moveResource(oldIndex: number, newIndex: number): void;

GDevelop.js/types/gdresourcescontainer.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ declare class gdResourcesContainer {
1010
findFilesNotInResources(filesToCheck: gdVectorString): gdVectorString;
1111
hasResource(name: string): boolean;
1212
getResource(name: string): gdResource;
13+
getResourceAt(index: number): gdResource;
1314
getResourceNameWithOrigin(originName: string, originIdentifier: string): string;
1415
getResourceNameWithFile(file: string): string;
1516
addResource(res: gdResource): boolean;
1617
removeResource(name: string): void;
1718
renameResource(oldName: string, name: string): void;
1819
getResourcePosition(name: string): number;
20+
count(): number;
1921
moveResourceUpInList(oldName: string): boolean;
2022
moveResourceDownInList(oldName: string): boolean;
2123
moveResource(oldIndex: number, newIndex: number): void;

newIDE/app/src/ResourcesEditor/index.js

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
registerOnResourceExternallyChangedCallback,
2424
unregisterOnResourceExternallyChangedCallback,
2525
} from '../MainFrame/ResourcesWatcher';
26+
import { showWarningBox } from '../UI/Messages/MessageBox';
2627

2728
const gd: libGDevelop = global.gd;
2829

@@ -84,6 +85,7 @@ export default class ResourcesEditor extends React.Component<Props, State> {
8485
this.onResourceExternallyChanged.bind(this)
8586
);
8687
}
88+
8789
componentWillUnmount() {
8890
unregisterOnResourceExternallyChangedCallback(
8991
this.resourceExternallyChangedCallbackId
@@ -126,24 +128,70 @@ export default class ResourcesEditor extends React.Component<Props, State> {
126128
);
127129
if (!answer) return;
128130

131+
const resourcesManager = project.getResourcesManager();
132+
const currentIndex = resourcesManager.getResourcePosition(
133+
resource.getName()
134+
);
135+
129136
onDeleteResource(resource, doRemove => {
130137
if (!doRemove || !resource) return;
131138

132-
project.getResourcesManager().removeResource(resource.getName());
139+
resourcesManager.removeResource(resource.getName());
140+
141+
const newCount = resourcesManager.count();
142+
const nextResourceToSelect =
143+
newCount > 0
144+
? resourcesManager.getResourceAt(Math.min(currentIndex, newCount - 1))
145+
: null;
146+
133147
this.setState(
134148
{
135-
selectedResource: null,
149+
selectedResource: nextResourceToSelect,
136150
},
137151
() => {
138-
// Force update of the resources list as otherwise it could render
139-
// resource that was just deleted.
140-
if (this._resourcesList) this._resourcesList.forceUpdateList();
152+
const resourcesList = this._resourcesList;
153+
if (resourcesList) {
154+
resourcesList.forceUpdateList();
155+
resourcesList.focusList();
156+
}
157+
const propertiesEditor = this._propertiesEditor;
158+
if (propertiesEditor) propertiesEditor.forceUpdate();
141159
this.updateToolbar();
142160
}
143161
);
144162
});
145163
};
146164

165+
renameResource = (resource: gdResource, newName: string) => {
166+
const { project, onRenameResource } = this.props;
167+
168+
// Nothing to do if the name is not changed or empty.
169+
if (resource.getName() === newName || newName.length === 0) return;
170+
171+
// Check for duplicate names.
172+
const resourcesManager = project.getResourcesManager();
173+
if (resourcesManager.hasResource(newName)) {
174+
showWarningBox('Another resource with this name already exists', {
175+
delayToNextTick: true,
176+
});
177+
return;
178+
}
179+
180+
onRenameResource(resource, newName, doRename => {
181+
if (!doRename) return;
182+
183+
resource.setName(newName);
184+
185+
const resourcesList = this._resourcesList;
186+
if (resourcesList) {
187+
resourcesList.forceUpdateList();
188+
resourcesList.focusList();
189+
}
190+
const propertiesEditor = this._propertiesEditor;
191+
if (propertiesEditor) propertiesEditor.forceUpdate();
192+
});
193+
};
194+
147195
_removeUnusedResources = (resourceKind: ResourceKind) => {
148196
const { project } = this.props;
149197
const selectedResourceName = this.state.selectedResource
@@ -238,12 +286,7 @@ export default class ResourcesEditor extends React.Component<Props, State> {
238286
};
239287

240288
render() {
241-
const {
242-
project,
243-
onRenameResource,
244-
resourceManagementProps,
245-
fileMetadata,
246-
} = this.props;
289+
const { project, resourceManagementProps, fileMetadata } = this.props;
247290
const { selectedResource } = this.state;
248291
const resourcesActionsMenuBuilder = resourceManagementProps.getStorageProviderResourceOperations();
249292

@@ -277,7 +320,7 @@ export default class ResourcesEditor extends React.Component<Props, State> {
277320
project={project}
278321
fileMetadata={fileMetadata}
279322
onDeleteResource={this.deleteResource}
280-
onRenameResource={onRenameResource}
323+
onRenameResource={this.renameResource}
281324
onSelectResource={this._onResourceSelected}
282325
selectedResource={selectedResource}
283326
ref={resourcesList => (this._resourcesList = resourcesList)}

newIDE/app/src/ResourcesList/ResourcePreview/ImagePreview.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,11 @@ const ImagePreview = ({
485485
const containerLoaded = !!containerWidth && !!containerHeight;
486486
const imageLoaded = !!imageWidth && !!imageHeight && !errored;
487487

488-
// We display the elements only when the image is loaded and
489-
// the zoom is applied to avoid a shift in the image.
488+
// We display the elements only when both the container and image are loaded
489+
// to avoid a shift in the image.
490490
// We use "visibility": "hidden" instead of "display": "none"
491491
// so that the image takes the space of the container whilst being hidden.
492-
// TODO: handle a proper loader.
493-
const visibility = containerLoaded ? undefined : 'hidden';
492+
const visibility = containerLoaded && imageLoaded ? undefined : 'hidden';
494493

495494
const forcedCursor = shouldMoveView ? 'grab' : null;
496495
const forcedCursorStyle = forcedCursor

0 commit comments

Comments
 (0)