33import com .thecoderscorner .menu .domain .state .PortableColor ;
44import com .thecoderscorner .menu .domain .util .PortablePalette ;
55import com .thecoderscorner .menu .editorui .dialog .AppInformationPanel ;
6+ import com .thecoderscorner .menu .editorui .gfxui .imgedit .SimpleImagePane ;
67import com .thecoderscorner .menu .editorui .gfxui .pixmgr .*;
78import com .thecoderscorner .menu .editorui .uimodel .CurrentProjectEditorUI ;
89import com .thecoderscorner .menu .editorui .util .SafeNavigator ;
910import javafx .event .ActionEvent ;
1011import javafx .scene .control .*;
1112import javafx .scene .image .Image ;
12- import javafx .scene .image .ImageView ;
1313import javafx .scene .image .PixelReader ;
1414import javafx .scene .input .Clipboard ;
1515import javafx .scene .input .DataFormat ;
1616import javafx .scene .input .KeyCode ;
1717import 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 ;
1822import javafx .stage .Stage ;
1923
2024import java .io .*;
2125import java .nio .file .Path ;
22- import java .util .Arrays ;
23- import java .util .HashMap ;
26+ import java .util .ArrayList ;
27+ import java .util .List ;
2428import java .util .Map ;
2529import 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