Skip to content

Commit e27bdfb

Browse files
committed
small improvements
1 parent 1e143f7 commit e27bdfb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+712
-404
lines changed

src/main/java/pixelitor/Composition.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,11 @@ public boolean contains(Layer searched) {
16541654
return false;
16551655
}
16561656

1657+
/**
1658+
* Recursively checks if this composition contains
1659+
* a layer of the given type at any nesting level.
1660+
* Content compositions inside smart objects are not checked.
1661+
*/
16571662
@Override
16581663
public boolean containsLayerOfType(Class<? extends Layer> type) {
16591664
for (Layer layer : layerList) {

src/main/java/pixelitor/Views.java

Lines changed: 39 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import java.util.Optional;
4747
import java.util.concurrent.CompletableFuture;
4848
import java.util.function.Consumer;
49-
import java.util.function.Function;
5049
import java.util.function.Predicate;
5150

5251
import static java.lang.String.format;
@@ -61,7 +60,7 @@
6160
import static pixelitor.utils.Texts.i18n;
6261

6362
/**
64-
* Static methods related to the list of open views.
63+
* Static methods for managing the collection of open views.
6564
*/
6665
public class Views {
6766
private static final List<View> views = new ArrayList<>();
@@ -108,12 +107,12 @@ public static void viewClosed(View view) {
108107

109108
views.remove(view);
110109
if (views.isEmpty()) {
111-
onAllViewsClosed();
110+
allViewsClosed();
112111
}
113112
ensureActiveViewExists();
114113
}
115114

116-
private static void onAllViewsClosed() {
115+
private static void allViewsClosed() {
117116
setActiveView(null, false);
118117
activationListeners.forEach(ViewActivationListener::allViewsClosed);
119118
History.onAllViewsClosed();
@@ -122,7 +121,7 @@ private static void onAllViewsClosed() {
122121
FramesUI.resetCascadeCount();
123122
}
124123

125-
// ensures that one of the open views is active
124+
// ensures that an active view is set if there are any open views remaining
126125
private static void ensureActiveViewExists() {
127126
if (!views.isEmpty() && !views.contains(activeView)) {
128127
activate(views.getFirst());
@@ -133,6 +132,9 @@ public static void activate(View view) {
133132
setActiveView(view, true);
134133
}
135134

135+
/**
136+
* Sets the active view, optionally triggering full UI activation.
137+
*/
136138
public static void setActiveView(View view, boolean activate) {
137139
if (view == activeView) {
138140
return;
@@ -152,7 +154,7 @@ public static void setActiveView(View view, boolean activate) {
152154
}
153155

154156
/**
155-
* Changes the cursor for all views
157+
* Changes the mouse cursor for all open views.
156158
*/
157159
public static void setCursorForAll(Cursor cursor) {
158160
for (View view : views) {
@@ -240,6 +242,9 @@ public static void forEach(Consumer<View> action) {
240242
}
241243

242244
public static View activateRandomView() {
245+
if (views.isEmpty()) {
246+
return null;
247+
}
243248
View view = Rnd.chooseFrom(views);
244249
if (view != activeView) {
245250
activate(view);
@@ -269,6 +274,12 @@ public static void assertNumViewsIsAtLeast(int minimum) {
269274
minimum, numViews, getOpenCompNamesAsString()));
270275
}
271276

277+
private static String getOpenCompNamesAsString() {
278+
return views.stream()
279+
.map(View::getName)
280+
.collect(joining(", ", "[", "]"));
281+
}
282+
272283
public static void assertZoomOfActiveIs(ZoomLevel expected) {
273284
if (activeView == null) {
274285
throw new AssertionError("no active view");
@@ -280,12 +291,9 @@ public static void assertZoomOfActiveIs(ZoomLevel expected) {
280291
}
281292
}
282293

283-
private static String getOpenCompNamesAsString() {
284-
return views.stream()
285-
.map(View::getName)
286-
.collect(joining(", ", "[", "]"));
287-
}
288-
294+
/**
295+
* Closes the given view, prompting to save unsaved changes if necessary.
296+
*/
289297
public static void warnAndClose(View view) {
290298
if (RandomGUITest.isRunning()) {
291299
return;
@@ -314,6 +322,7 @@ public static void warnAndClose(View view) {
314322
throw new IllegalStateException("answer = " + answer);
315323
}
316324
} else {
325+
// no unsaved changes, close directly
317326
view.close();
318327
}
319328
} catch (Exception ex) {
@@ -333,10 +342,11 @@ private static void warnAndCloseUnmodified() {
333342
warnAndCloseAllIf(view -> !view.getComp().isDirty());
334343
}
335344

345+
// close all views matching a predicate, prompting for unsaved changes
336346
private static void warnAndCloseAllIf(Predicate<View> condition) {
337347
// make a copy because items will be removed from the original while iterating
338-
Iterable<View> tmpCopy = new ArrayList<>(views);
339-
for (View view : tmpCopy) {
348+
List<View> viewsToProcess = new ArrayList<>(views);
349+
for (View view : viewsToProcess) {
340350
if (condition.test(view)) {
341351
warnAndClose(view);
342352
}
@@ -379,19 +389,6 @@ public static void onActiveComp(Consumer<Composition> action) {
379389
}
380390
}
381391

382-
public static <T> T fromActiveComp(Function<Composition, T> function) {
383-
if (activeView != null) {
384-
return function.apply(activeView.getComp());
385-
}
386-
387-
// there is no open view
388-
return null;
389-
}
390-
391-
public static BufferedImage getActiveCompositeImage() {
392-
return fromActiveComp(Composition::getCompositeImage);
393-
}
394-
395392
public static Optional<Composition> findCompByName(String name) {
396393
return views.stream()
397394
.map(View::getComp)
@@ -406,6 +403,9 @@ public static List<Composition> getUnsavedComps() {
406403
.collect(toList());
407404
}
408405

406+
/**
407+
* Adds a newly loaded composition to the application, sets it as active, and updates related UI.
408+
*/
409409
public static Composition addJustLoadedComp(Composition comp) {
410410
assert comp != null;
411411

@@ -423,13 +423,13 @@ public static Composition addJustLoadedComp(Composition comp) {
423423
}
424424

425425
public static void addNewPasted(BufferedImage pastedImage) {
426-
addNew(pastedImage, null, "Pasted Image " + pastedCount++);
427-
}
428-
429-
public static void addNew(BufferedImage image, File file, String name) {
430-
addNew(Composition.fromImage(image, file, name));
426+
String name = "Pasted Image " + pastedCount++;
427+
addNew(Composition.fromImage(pastedImage, null, name));
431428
}
432429

430+
/**
431+
* Adds the given composition to the UI, creating and configuring a new view for it.
432+
*/
433433
public static void addNew(Composition comp) {
434434
try {
435435
assert comp.getView() == null : "already has a view";
@@ -459,14 +459,6 @@ public static int getNumLayersInActiveHolder() {
459459
return getActiveLayer().getHolderForNewLayers().getNumLayers();
460460
}
461461

462-
public static Layer getActiveTopLevelLayer() {
463-
if (activeView != null) {
464-
return activeView.getComp().getActiveTopLevelLayer();
465-
}
466-
467-
return null;
468-
}
469-
470462
public static Layer getActiveLayer() {
471463
if (activeView != null) {
472464
return activeView.getComp().getActiveLayer();
@@ -477,8 +469,7 @@ public static Layer getActiveLayer() {
477469

478470
public static void onActiveLayer(Consumer<Layer> action) {
479471
if (activeView != null) {
480-
Layer activeLayer = activeView.getComp().getActiveLayer();
481-
action.accept(activeLayer);
472+
action.accept(activeView.getComp().getActiveLayer());
482473
}
483474
}
484475

@@ -524,24 +515,14 @@ public static Path getActivePath() {
524515
return null;
525516
}
526517

527-
public static boolean activePathIs(Path path) {
528-
if (activeView != null) {
529-
Path activePath = activeView.getComp().getActivePath();
530-
return activePath == path;
531-
}
532-
533-
// there is no open view
534-
return path == null;
535-
}
536-
537518
public static void setActivePath(Path path) {
538519
if (activeView != null) {
539520
activeView.getComp().setActivePath(path);
540521
}
541522
}
542523

543524
/**
544-
* Checks if a file is already open and prompts the user for confirmation to proceed.
525+
* Warns the user if a file is already open and prompts for confirmation to open it again.
545526
*/
546527
public static boolean warnIfAlreadyOpen(File file) {
547528
View view = findViewByFile(file);
@@ -560,6 +541,7 @@ public static boolean warnIfAlreadyOpen(File file) {
560541
return again;
561542
}
562543

544+
// finds an open view associated with the given file path
563545
private static View findViewByFile(File targetFile) {
564546
for (View view : views) {
565547
File file = view.getComp().getFile();
@@ -571,12 +553,12 @@ private static View findViewByFile(File targetFile) {
571553
}
572554

573555
public static void appWindowActivated() {
574-
// Check if any views need to be automatically reloaded
575-
CompletableFuture<Composition> cf = CompletableFuture.completedFuture(null);
556+
// check if any views need to be automatically reloaded due to external modifications
557+
CompletableFuture<Composition> chainedChecks = CompletableFuture.completedFuture(null);
576558
for (View view : views) {
577559
// make sure that the next reload is not started
578560
// before the previous one is finished
579-
cf = cf.thenCompose(comp -> view.checkForExternalModifications());
561+
chainedChecks = chainedChecks.thenCompose(comp -> view.checkForExternalModifications());
580562
}
581563
}
582564

@@ -598,5 +580,6 @@ public static void updateThumbSize(int newThumbSize) {
598580
public static void clear() {
599581
views.clear();
600582
activeView = null;
583+
pastedCount = 1;
601584
}
602585
}

src/main/java/pixelitor/compactions/Flip.java

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,17 @@
2121
import pixelitor.gui.View;
2222
import pixelitor.guides.Guides;
2323
import pixelitor.layers.ContentLayer;
24-
import pixelitor.utils.Texts;
2524

2625
import java.awt.geom.AffineTransform;
27-
import java.awt.image.BufferedImage;
2826

2927
/**
3028
* Flips (mirrors) all content layers of a composition
3129
* either horizontally or vertically.
3230
*/
3331
public class Flip extends SimpleCompAction {
34-
private final Flip.Direction direction;
32+
private final FlipDirection direction;
3533

36-
public Flip(Direction direction) {
34+
public Flip(FlipDirection direction) {
3735
super(direction.getDisplayName(), false);
3836
this.direction = direction;
3937
}
@@ -68,66 +66,4 @@ protected Guides createTransformedGuides(Guides srcGuides, View view, Canvas src
6866
protected String getStatusBarMessage() {
6967
return direction.getStatusBarMessage();
7068
}
71-
72-
/**
73-
* The direction of the flip
74-
*/
75-
public enum Direction {
76-
HORIZONTAL("flip_horizontal") {
77-
@Override
78-
public String getStatusBarMessage() {
79-
return "Image flipped horizontally";
80-
}
81-
82-
@Override
83-
public AffineTransform createTransform(int width, int height) {
84-
var at = new AffineTransform();
85-
at.translate(width, 0); // keeps the content visible
86-
at.scale(-1, 1);
87-
return at;
88-
}
89-
}, VERTICAL("flip_vertical") {
90-
@Override
91-
public String getStatusBarMessage() {
92-
return "Image flipped vertically";
93-
}
94-
95-
@Override
96-
public AffineTransform createTransform(int width, int height) {
97-
var at = new AffineTransform();
98-
at.translate(0, height); // keeps the content visible
99-
at.scale(1, -1);
100-
return at;
101-
}
102-
};
103-
104-
private final String displayName;
105-
106-
Direction(String uiKey) {
107-
this.displayName = Texts.i18n(uiKey);
108-
}
109-
110-
public String getDisplayName() {
111-
return displayName;
112-
}
113-
114-
public abstract String getStatusBarMessage();
115-
116-
public abstract AffineTransform createTransform(int width, int height);
117-
118-
/**
119-
* Returns the transformation in image space, relative to the canvas.
120-
* Needed for transforming the selection.
121-
*/
122-
public AffineTransform createCanvasTransform(Canvas canvas) {
123-
return createTransform(canvas.getWidth(), canvas.getHeight());
124-
}
125-
126-
/**
127-
* Returns the transformation for the image (image space, relative to the image).
128-
*/
129-
public AffineTransform createImageTransform(BufferedImage image) {
130-
return createTransform(image.getWidth(), image.getHeight());
131-
}
132-
}
13369
}

0 commit comments

Comments
 (0)