Skip to content

Commit b587427

Browse files
committed
#446 improved font and bitmap editor
1 parent 0573767 commit b587427

File tree

7 files changed

+366
-190
lines changed

7 files changed

+366
-190
lines changed

tcMenuGenerator/src/main/java/com/thecoderscorner/menu/editorui/gfxui/CreateBitmapWidgetController.java

Lines changed: 75 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,28 @@
33
import com.thecoderscorner.menu.domain.state.PortableColor;
44
import com.thecoderscorner.menu.domain.util.PortablePalette;
55
import com.thecoderscorner.menu.editorui.dialog.AppInformationPanel;
6+
import com.thecoderscorner.menu.editorui.gfxui.imgedit.SimpleImagePane;
67
import com.thecoderscorner.menu.editorui.gfxui.pixmgr.*;
78
import com.thecoderscorner.menu.editorui.uimodel.CurrentProjectEditorUI;
89
import com.thecoderscorner.menu.editorui.util.SafeNavigator;
910
import javafx.event.ActionEvent;
1011
import javafx.scene.control.*;
1112
import javafx.scene.image.Image;
12-
import javafx.scene.image.ImageView;
1313
import javafx.scene.image.PixelReader;
1414
import javafx.scene.input.Clipboard;
1515
import javafx.scene.input.DataFormat;
1616
import javafx.scene.input.KeyCode;
1717
import javafx.scene.input.KeyEvent;
18+
import javafx.scene.layout.ColumnConstraints;
19+
import javafx.scene.layout.GridPane;
20+
import javafx.scene.layout.Priority;
21+
import javafx.scene.layout.RowConstraints;
1822
import javafx.stage.Stage;
1923

2024
import java.io.*;
2125
import java.nio.file.Path;
22-
import java.util.Arrays;
23-
import java.util.HashMap;
26+
import java.util.ArrayList;
27+
import java.util.List;
2428
import java.util.Map;
2529
import java.util.Optional;
2630

@@ -33,55 +37,78 @@ public class CreateBitmapWidgetController {
3337
public CheckBox clipboardCheckBox;
3438
public TextField variableField;
3539
public Button addImgButton;
36-
public Button removeImgButton;
37-
3840
public Button createWidgetButton;
3941
public Button createBitmapButton;
40-
public ToggleButton imageToggle1;
41-
public ToggleButton imageToggle2;
42-
public ToggleButton imageToggle3;
43-
public ToggleButton imageToggle4;
44-
public ToggleButton imageToggle5;
45-
public ToggleButton imageToggle6;
46-
public ToggleButton imageToggle7;
47-
public ToggleButton imageToggle8;
42+
public GridPane imageGridPane;
43+
4844
private CurrentProjectEditorUI editorUI;
4945
private String homeDirectory;
50-
private final Map<Integer, LoadedImage> loadedImages = new HashMap<>();
51-
52-
private ToggleButton[] toggleArray;
46+
private final List<LoadedImage> loadedImages = new ArrayList<>();
5347

5448
public void initialise(CurrentProjectEditorUI editorUI, String homeDirectory) {
5549
this.editorUI = editorUI;
5650
this.homeDirectory = homeDirectory;
5751

58-
toggleArray = new ToggleButton[] { imageToggle1,imageToggle2,imageToggle3,imageToggle4,imageToggle5,imageToggle6,imageToggle7,imageToggle8 };
59-
60-
variableField.textProperty().addListener((observable, oldValue, newValue) -> refreshButtonStates());
52+
variableField.textProperty().addListener((_, _, _) -> refreshButtonStates());
6153

6254
resetAllStates();
6355
}
6456

6557
private void resetAllStates() {
6658
loadedImages.clear();
67-
int counter = 1;
68-
for(var t : toggleArray) {
69-
t.setText("Empty Image " + counter);
70-
t.setSelected(false);
71-
t.setDisable(true);
72-
t.setOnAction(event -> refreshButtonStates());
73-
counter++;
74-
}
59+
refreshGridComponents();
7560
refreshButtonStates();
7661
}
7762

63+
private void refreshGridComponents() {
64+
imageGridPane.getChildren().clear();
65+
imageGridPane.getRowConstraints().clear();
66+
imageGridPane.getColumnConstraints().clear();
67+
68+
int cols = switch(loadedImages.size()) {
69+
case 1 -> 1;
70+
case 2, 3, 4 -> 2;
71+
case 5, 6 -> 3;
72+
default -> 4;
73+
};
74+
int rows = (loadedImages.size() < 3) ? 1 : 2;
75+
76+
for(int i=0; i<cols; i++) {
77+
ColumnConstraints col = new ColumnConstraints();
78+
col.setPercentWidth(98.0 / cols);
79+
col.setHgrow(Priority.SOMETIMES);
80+
imageGridPane.getColumnConstraints().add(col);
81+
}
82+
83+
for(int i=0; i<rows; i++) {
84+
RowConstraints row = new RowConstraints();
85+
row.setVgrow(Priority.SOMETIMES);
86+
imageGridPane.getRowConstraints().add(row);
87+
}
88+
89+
for (int i = 0; i < loadedImages.size(); i++) {
90+
LoadedImage img = loadedImages.get(i);
91+
var editButton = new Button("edit");
92+
var removeButton = new Button("remove");
93+
removeButton.setOnAction(_ -> {
94+
loadedImages.remove(img);
95+
refreshGridComponents();
96+
refreshButtonStates();
97+
});
98+
var buttons = List.of(editButton, removeButton);
99+
var imageView = new SimpleImagePane(img.bmpData(), img.pixelFormat(),false, img.palette(), buttons);
100+
GridPane.setConstraints(imageView, i % cols, i / cols);
101+
imageGridPane.getChildren().add(imageView);
102+
}
103+
}
104+
78105
public void onKeyReleased(KeyEvent keyEvent) {
79106
if(keyEvent.isShortcutDown() && !keyEvent.isShiftDown() && !keyEvent.isAltDown() && keyEvent.getCode() == KeyCode.V) {
80107
onPasteImage(new ActionEvent(keyEvent, pasteImgButton));
81108
}
82109
}
83110

84-
public void onPasteImage(ActionEvent actionEvent) {
111+
public void onPasteImage(ActionEvent ignoredActionEvent) {
85112
var clipboard = Clipboard.getSystemClipboard();
86113
if(clipboard.hasContent(DataFormat.IMAGE)) {
87114
Image image = clipboard.getImage();
@@ -92,110 +119,47 @@ public void onPasteImage(ActionEvent actionEvent) {
92119
}
93120

94121
private void putImageIntoAvailableSlot(Image image) {
95-
int blankImage = findBlankImageIndex();
96-
if (blankImage == -1) return;
122+
if (loadedImages.size() >= 8) return;
97123

98-
BitmapImportPopup popup = new BitmapImportPopup(image, blankImage);
124+
BitmapImportPopup popup = new BitmapImportPopup(image);
99125
popup.showConfigSetup((Stage) addImgButton.getScene().getWindow(), this::importImage);
100126
}
101127
private void importImage(BitmapImportPopup popup) {
102-
var blankImage = popup.getSlot();
103-
var image = popup.getImage();
104-
toggleArray[blankImage].setContentDisplay(ContentDisplay.TOP);
105128
var img = createBitmap(popup);
106-
ImageView imgView = new ImageView(img.bmpData().createImageFromBitmap(popup.getPalette()));
107-
double ratio = image.getWidth() / image.getHeight();
108-
double maxWid = createWidgetButton.getScene().getHeight() * 0.2;
109-
if(image.getWidth() > image.getHeight()) {
110-
imgView.setFitWidth(maxWid);
111-
imgView.setFitHeight(maxWid / ratio);
112-
} else {
113-
imgView.setFitWidth(maxWid * ratio);
114-
imgView.setFitHeight(maxWid);
115-
}
116-
117-
toggleArray[blankImage].setGraphic(imgView);
118-
toggleArray[blankImage].setText(String.format("%s %.0fx%.0f", shortFmtText(popup.getPixelFormat()),
119-
image.getWidth(), image.getHeight()));
120-
toggleArray[blankImage].setSelected(true);
121-
toggleArray[blankImage].setDisable(false);
122-
loadedImages.put(blankImage, img);
123-
129+
loadedImages.add(img);
130+
refreshGridComponents();
124131
refreshButtonStates();
125132
}
126133

127-
private int findBlankImageIndex() {
128-
int blankImage = -1;
129-
for(int i=0; i< 8; i++) {
130-
if(!loadedImages.containsKey(i)) {
131-
blankImage = i;
132-
break;
133-
}
134-
}
135-
136-
if(blankImage == -1) {
137-
editorUI.alertOnError("No image spaces available", "No images spaces are left available for the paste operation, remove at least one image");
138-
}
139-
return blankImage;
140-
}
141-
142-
private String shortFmtText(NativePixelFormat fmtCode) {
143-
return switch (fmtCode) {
144-
case XBM_LSB_FIRST -> "XBMP";
145-
case MONO_BITMAP -> "MONO";
146-
case PALETTE_2BPP -> "2BPP(4)";
147-
case PALETTE_4BPP -> "4BPP(16)";
148-
};
149-
}
150-
151134
private void refreshButtonStates() {
152-
boolean nothingSelected = Arrays.stream(toggleArray).noneMatch(ToggleButton::isSelected);
153-
removeImgButton.setDisable(nothingSelected);
154135
addImgButton.setDisable(loadedImages.size() == 8);
155136
var variableEmpty = variableField.getText().isEmpty();
156-
createWidgetButton.setDisable(nothingSelected || variableEmpty);
157-
createBitmapButton.setDisable(nothingSelected || variableEmpty);
137+
createWidgetButton.setDisable(loadedImages.isEmpty() || variableEmpty);
138+
createBitmapButton.setDisable(loadedImages.isEmpty() || variableEmpty);
158139
}
159140

160-
public void onClose(ActionEvent actionEvent) {
141+
public void onClose(ActionEvent ignoredActionEvent) {
161142
((Stage)createBitmapButton.getScene().getWindow()).close();
162143
}
163144

164-
public void onPixelFormatChange(ActionEvent actionEvent) {
165-
resetAllStates();
166-
}
167-
168-
public void onOnlineHelp(ActionEvent actionEvent) {
145+
public void onOnlineHelp(ActionEvent ignoredActionEvent) {
169146
SafeNavigator.safeNavigateTo(AppInformationPanel.CREATE_USE_BITMAP_PAGE);
170147
}
171148

172-
public void onAddImage(ActionEvent actionEvent) {
149+
public void onAddImage(ActionEvent ignoredActionEvent) {
173150
var maybeFile = editorUI.findFileNameFromUser(getInitialDir(), true, "*");
174151
if(maybeFile.isPresent()) {
175152
try(var is = new BufferedInputStream(new FileInputStream(maybeFile.get()))) {
176153
Image img = new Image(is);
177154
putImageIntoAvailableSlot(img);
178155
} catch (Exception ex) {
179-
logger.log(System.Logger.Level.ERROR, "Image load from file failure " + maybeFile.get(), ex);
156+
logger.log(System.Logger.Level.ERROR, STR."Image load from file failure \{maybeFile.get()}", ex);
180157
editorUI.alertOnError("Error loading image", ex.getMessage());
181158
}
182159
}
183160
}
184161

185-
public void onRemoveImage(ActionEvent actionEvent) {
186-
for(int i=0;i<8;i++) {
187-
if(loadedImages.containsKey(i) && toggleArray[i].isSelected()) {
188-
toggleArray[i].setText("Empty Image" + (i + 1));
189-
toggleArray[i].setDisable(true);
190-
toggleArray[i].setGraphic(null);
191-
toggleArray[i].setSelected(false);
192-
loadedImages.remove(i);
193-
}
194-
}
195-
refreshButtonStates();
196-
}
197-
198-
public void onCreateWidget(ActionEvent actionEvent) {
162+
public void onCreateWidget(ActionEvent ignoredActionEvent) {
199163
if(clipboardCheckBox.isSelected()) {
200164
try(var os = new ByteArrayOutputStream(10240); var fileOut = new PrintStream(os)) {
201165
writeOutTitleWidget(fileOut);
@@ -204,7 +168,7 @@ public void onCreateWidget(ActionEvent actionEvent) {
204168
}
205169
catch (Exception e) {
206170
logger.log(System.Logger.Level.ERROR, "Could not put file content on clipboard", e);
207-
editorUI.alertOnError("Not exported to Clipboard", "Not exported to Clipboard " + e.getMessage());
171+
editorUI.alertOnError("Not exported to Clipboard", STR."Not exported to Clipboard \{e.getMessage()}");
208172
}
209173
return;
210174
}
@@ -222,30 +186,26 @@ public void onCreateWidget(ActionEvent actionEvent) {
222186

223187
private void writeOutTitleWidget(PrintStream fileOut) throws IOException {
224188
var exporter = new NativeBitmapExporter();
225-
for(int i=0;i<8;i++) {
226-
if(loadedImages.containsKey(i) && toggleArray[i].isSelected()) {
227-
exporter.addImageToExport(loadedImages.get(i));
228-
}
189+
for(var li : loadedImages) {
190+
exporter.addImageToExport(li);
229191
}
230192
exporter.exportBitmapDataAsWidget(fileOut, variableField.getText());
231193
}
232194

233-
public void onCreateBitmaps(ActionEvent actionEvent) {
195+
public void onCreateBitmaps(ActionEvent ignoredActionEvent) {
234196
String name = variableField.getText();
235197
if(name.isEmpty() || name.matches(".*[\\s.].*")) {
236198
editorUI.alertOnError("Invalid name", "Not a variable name");
237199
return;
238200
}
239201

240202
var exporter = new NativeBitmapExporter();
241-
for(int i=0;i<8;i++) {
242-
if(loadedImages.containsKey(i) && toggleArray[i].isSelected()) {
243-
exporter.addImageToExport(loadedImages.get(i));
244-
}
203+
for(var li : loadedImages) {
204+
exporter.addImageToExport(li);
245205
}
246206

247207
if(clipboardCheckBox.isSelected()) {
248-
try(var os = new ByteArrayOutputStream(10240); var fileOut = new PrintStream(os);) {
208+
try(var os = new ByteArrayOutputStream(10240); var fileOut = new PrintStream(os)) {
249209
exporter.exportBitmaps(fileOut, name, "Bitmap");
250210
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, os.toString()));
251211
exportSuccessful("clipboard");
@@ -277,8 +237,8 @@ private Optional<Path> getInitialDir() {
277237
}
278238

279239
private void exportSuccessful(String where) {
280-
showAlertAndWait(Alert.AlertType.INFORMATION, variableField.getText() + " successfully exported",
281-
variableField.getText() + " was successfully exported to " + where, ButtonType.CLOSE);
240+
showAlertAndWait(Alert.AlertType.INFORMATION, STR."\{variableField.getText()} successfully exported",
241+
STR."\{variableField.getText()} was successfully exported to \{where}", ButtonType.CLOSE);
282242
}
283243

284244
LoadedImage createBitmap(BitmapImportPopup popup) {

0 commit comments

Comments
 (0)